JavaScript(二)-- 面向对象
2016-04-03 17:38
411 查看
JavaScript也是面向对象的编程思想,本文讲解如何创建JavaScript的对象,以及对象的继承等机制。
可以使用工厂方法,在创建多个对象的时候使用:
在对象定义体外定义函数,在定义对象属性时,把函数引用赋给方法属性。
构造函数创建对象也存在这样的问题,这就体现了原型方法的优势。
首先,定义对象的无参构造函数
然后,使用对象的prototype属性
使用原型还可以判断,变量是否指向某一特定对象。
使用 变量 instanceof 对象的方式,返true或false
但是,使用原型方式创建对象,也有弊端:
1)只有无参构造函数,不能在创建对象的时候初始化属性,只能创建好对象后,改变属性值,麻烦
2)使用对象,目的是函数被不同对象变量共享,但是也导致了属性为引用对象的共享,比如属性= new Array(),那么该属性就是被多个对象变量共享的:
介绍了五种创建对象的方法,其中最经常使用的是:混合构造函数/原型方式、和动态原型方式,两者其实等价。
Number的toString方法,向其传入数值16,8等数字,就会返回指定数值的进制数字符串
现在为Number对象添加toHexString()方法,直接返回数值的十六进制数
因为每个对象都继承自Object对象,所以每个新建的对象就有了这个添加的方法。
1、创建对象
1.原始方法new Object()
<html> <head> <meta charset="utf-8"/> <script type="text/javascript"> //如果构造方法为无参的,可以去除(),直接new Object; personObj = new Object; personObj.firstname="yuchen"; personObj.lastname="wu"; personObj.age=25; personObj.eyecolor="black"; personObj.show=function (){ document.write(this.firstname+" "+this.lastname+"的年龄是:"+this.age+"岁!"); } //直接使用对象的属性 document.write(personObj.firstname+"的年龄是:"+personObj.age+"岁。"); //调用对象的方法 personObj.show(); </script> </head> <body> </body> </html>
可以使用工厂方法,在创建多个对象的时候使用:
<script type="text/javascript"> function createPerson(firstname,lastname,age,eyecolor){ //工厂方法的第一步就是使用new Object()创建对象,然后对属性进行赋值 person = new Object(); person.firstname=firstname; person.lastname=lastname; person.age=age; person.eyecolor=eyecolor; person.show = function (){ //一般需要指明this.属性,不使用this也没错 document.write(this.firstname+"的年龄是:"+this.age+"岁!"); } return person; } person1=createPerson("yuchen","wu" , 25,"black"); person1.show(); person2=createPerson("jack","SR",32,"blue"); person2.show(); </script>在对方法进行定义时,出现每个对象都需要定义一次方法的情况,实际上只需要所有对象共享一个同名方法就可以,所以,改进是
在对象定义体外定义函数,在定义对象属性时,把函数引用赋给方法属性。
<script type="text/javascript"> function personshow(){ //一般需要指明this.属性,不使用this也没错 document.write(this.firstname+"的年龄是:"+this.age+"岁!"); } function createPerson(firstname,lastname,age,eyecolor){ //工厂方法的第一步就是使用new Object()创建对象,然后对属性进行赋值 person = new Object(); person.firstname=firstname; person.lastname=lastname; person.age=age; person.eyecolor=eyecolor; //****把函数引用赋给对象属性,函数的定义在对象定义前后都可以 person.show = personshow; return person; } person1=createPerson("yuchen","wu" , 25,"black"); person1.show(); person2=createPerson("jack","SR",32,"blue"); person2.show(); </script>这样就解决了重复定义函数的问题,然而这样看起来,函数就不像对象的方法。
构造函数创建对象也存在这样的问题,这就体现了原型方法的优势。
2.使用构造函数
构造函数定义时,首字母为小写也可用,但一般写为大写。<script type="text/javascript"> function Person(firstname,lastname,age,eyecolor){ this.firstname=firstname; this.lastname=lastname; this.age=age; this.eyecolor=eyecolor; this.show = function (){ //一般需要指明this.属性,不使用this也没错 document.write(this.firstname+"的年龄是:"+age+"岁!"); } } person1=new Person("yuchen","wu" , 25,"black"); person1.show(); person2=new Person("jack","SR",32,"blue"); person2.show(); </script>
3、原型方式
原型方式就是使用对象的prototype属性,将对象属性和方法都赋给prototype,这是属性可以看做对象的基因,通过该属性就可以确定对象。首先,定义对象的无参构造函数
然后,使用对象的prototype属性
<script type="text/javascript"> function Person(){ } Person.prototype.firstname = "yuchen"; Person.prototype.age = 26; Person.prototype.showPerson = function (){ document.write(this.firstname+"的年龄是:"+this.age+"岁"); } var person1=new Person(); person1.showPerson(); document.write("<br/>") var person2=new Person(); person2.showPerson(); </script>这种方法,避免了每个对象都定义方法的弊端,因为是通过prototype将属性与函数的引用关联起来的。而且从语义上看,就能明白所有属性都属于同类对象。
使用原型还可以判断,变量是否指向某一特定对象。
使用 变量 instanceof 对象的方式,返true或false
<script type="text/javascript"> function Person(){ } Person.prototype.firstname = "yuchen"; Person.prototype.age = 26; Person.prototype.showPerson = function (){ document.write(this.firstname+"的年龄是:"+this.age+"岁"); } var person1=new Person(); document.write(person1 instanceof Person);//true </script>
但是,使用原型方式创建对象,也有弊端:
1)只有无参构造函数,不能在创建对象的时候初始化属性,只能创建好对象后,改变属性值,麻烦
2)使用对象,目的是函数被不同对象变量共享,但是也导致了属性为引用对象的共享,比如属性= new Array(),那么该属性就是被多个对象变量共享的:
<script type="text/javascript"> function Person(){ } Person.prototype.firstname = "yuchen"; Person.prototype.age = 26; Person.prototype.cars = new Array("BM","Ford"); Person.prototype.showPerson = function (){ document.write(this.firstname+"的车有:"+this.cars); } var person1=new Person(); person1.showPerson();//yuchen的车有:BM,Ford document.write("<br/>"); var person2 = new Person(); person2.cars.push("Rover"); document.write("person2:"); person2.showPerson();//person1:yuchen的车有:BM,Ford,Rover document.write("<br/>"); document.write("person1:"); person1.showPerson();//person1:yuchen的车有:BM,Ford,Rover </script>造成了引用对象属性的共享,所以引出混合的“构造函数\原型方式”
4、混合的构造函数 原型方式
思想就是,在创建对象中,使用构造函数为对象的属性赋值;使用原型方式为方法属性赋值。<script type="text/javascript"> function Person(firstname, age){ this.firstname = firstname; this.age = age; this.cars = new Array("BM","Ford"); } Person.prototype.show = function (){ document.write(this.firstname+"的车有:"+this.cars); } person1 = new Person("yuchen", 25); person1.cars.push("Rover"); person1.show();//yuchen的车有:BM,Ford,Rover document.write("<br/>"); person2 = new Person("jack",32); person2.cars.push("Benz"); person2.show();//jack的车有:BM,Ford,Benz </script>但是这样的定义方式,与传统意义上的对象封装,把属性和方法都放在类体中不同,纵然人感觉不严格,所以就有了动态原型方法。
5、动态原型方法
动态原型方法的思想,就是在对象中添加一个属性,用以标示判断原型中的方法是否定义过,如果定义过就不许再定义。<script type="text/javascript"> function Person(firstname, age){ this.firstname = firstname; this.age = age; this.cars = new Array("BM","Ford"); //typeof为一元运算符,对Person._initialized进行操作后再与后边"undefined"比较 //typeof判断变量的类型,返回Boolean,String等字符串,如果变量没有定义过,返回"undefined" if(typeof Person._initialized == "undefined"){ Person.prototype.show = function(){ document.write(this.firstname+"的车有:"+this.cars); }; Person._initialized = true; } } p1 = new Person("yuchen",25); p1.cars.push("Rover"); p1.show(); document.write("<br/>") p2 = new Person("jack",32); p2.cars.push("Benz"); p2.show(); </script>这样定义对象的过程,在语句结构上来看,就很符合面向对象的思想模型了。其中_initialized是一个属性变量,可以改为别的名字,只是用来进行判断的。
介绍了五种创建对象的方法,其中最经常使用的是:混合构造函数/原型方式、和动态原型方式,两者其实等价。
2、修改对象
对象的修改,一般都是通过对象的prototype进行修改。1.为已有对象创建新的方法
例1:Number的toString方法,向其传入数值16,8等数字,就会返回指定数值的进制数字符串
现在为Number对象添加toHexString()方法,直接返回数值的十六进制数
<script type="text/javascript"> Number.prototype.toHexString = function(){ return this.toString(16); } var iNum = 15; alert(iNum.toHexString());//f </script>例2:为Array添加indexOf方法,如图String的indexOf方法一样,返回指定值的下标
<script type="text/javascript"> Array.prototype.indexOf = function(val){ for(var i=0;i<this.length;i++){ if(this[i] == val){ return i; } } return -1; } var arr = new Array(1,2,4,5,7,11); alert(arr.indexOf(7));//4 </script>
2、为所有本地对象添加方法
上小节是为单个的已存在对象添加方法,那么为本地所有的对象添加方法,其实就是通过对Object对象添加方法因为每个对象都继承自Object对象,所以每个新建的对象就有了这个添加的方法。
<script type="text/javascript"> Object.prototype.showValue = function(){ //valueOf()返回对象的原始值 alert(this.valueOf()); }; var str = "mylove"; var iNum = 32; str.showValue(); iNum.showValue(); </script>
3、重定义已有的方法
其实就是新添加的函数与原有存在的方法同名,覆盖了以前的方法。<script type="text/javascript"> Array.prototype.push = function(){ alert("aaaa"); } var arr = new Array(); arr.push();//会弹出警告框aaaa </script>
4、极晚绑定
即,先实例化变量,在对对象添加新的方法,在先前定义变量中,同样适用,但一般不这样使用,因为不方便查看与梳理<script type="text/javascript"> var arr = new Array(); Array.prototype.push = function(){ alert("aaaa"); } arr.push();//会弹出警告框aaaa </script>
3、对象的继承
相关文章推荐
- 状态栏文字从右弹出_JS特效代码
- 状态栏文字从右到左移动条_JS特效代码
- 状态栏文字从右到左移动_js特效代码
- 状态栏文字来回出现_JS特效代码
- 【JavaScript】出现即使设置了ID也获取不到的可能原因与window.onload
- 状态栏的停留时间信息_JS特效代码
- 脚本引擎Rhino执行javascript代码
- 状态栏的进度条_JS特效代码
- JSR 303标准
- 特殊字符\u2028导致的Javascript脚本异常
- js javascript:void(0) 真正含义
- 自己封装的JS分页功能[用于搭配后台使用]
- JSTL标签 参考手册
- 【笔记】 《js权威指南》- 第8章 函数 - 8.7 函数属性、方法和构造函数
- JavaScript之事件操作
- JavaScript DOM 编程之高级篇
- Javascript短路表达式
- 【笔记】 《js权威指南》- 第8章 函数 - 8.5 作为命名空间的函数 - 8.6 闭包
- Javascript内存优化
- Javascript"怪异"现象