标签:style blog c http strong com
1.
我们创建的每个函数(或称构造函数或对象)都有一个 prototype(原型)属性,这个属性是一个对象(这个对象下有个prototype属性,而这个属性其实是另外一个对象的引用,这个属性就是一个对象),它的用途是
包含可以由特定类型的所有实例共享的属性和方法(prototype共享放到其中的属性和方法,无论实例化多少对象,属性和方法都是共享的。这样有好处也有坏处。)。逻辑上可以这么理解:prototype
通过
调用构造函数而创建的那个对象的原型对象。使用原型的好处可以让所有对象实例共享它所
包含的属性和方法。也就是说,不必在构造函数中定义对象信息,而是可以直接将这些信息
添加到原型中。
//构造函数声明对象方式
function Box(name,age) {
this.name = name; //实例属性
this.age=age;
this.run = function(){ //实例方法
return this.name + this.age + ‘运行中...‘;
}
}
//原型声明对象方式
function Box(){} //构造函数函数体内什么都没有,这里如果有,叫做实例属性,实习方法
Box.prototype.name =
‘Lee‘; //原型属性 原型里添加属性
Box.prototype.age = 100;
Box.prototype.run =
function () { // 原型方法 在原型里添加方法
return this.name + this.age +
‘运行中...‘;
};
比较一下原型内的方法地址是否一致:
var box1 = new Box();
alert(box1.name); //输出lee
alert(box1.run()); //输出lee运行中
var box2 = new Box();
alert(box1.run == box2.run); //true,方法的引用地址保持一致
以上两个例子说明:
如果是实例方法,不同的实例化,他们的方法地址是不一样的,是唯一的
如果是原型方法,那么他们的地址是共享的,大家都一样
2.
为了更进一步了解构造函数的声明方式和原型模式的声明方式,我们通过图示来了解一
下:
(1)构造函数方式中
box1和box2 的实例属性实例方法在内存中是不共享的,box1的name属性和box2的name属性的地址是不同的
(2)原型方式中
function Box(){}
Box.prototype.name = ‘Lee‘;
Box.prototype.age
= 100;
Box.prototype.run = function () {
return this.name +
this.age + ‘运行中...‘;
};
var box1 = new
Box();//Box实例有了,但是里面为空,实际上里面有个自带的属性_proto_
var box1 = new Box();
alert(box1.prototype);// undefined 这个属性是一个对象,访问不到
alert(box1._proto_); // 输出 object 这个属性是一个指针,指向prototype原型对象,但是_proto_在ie浏览器中是不支持的
创建的每个函数都有一个 prototype(原型)属性,但是这里访问不到,应该访问的是那个指针_proto_
_proto_实际上就是prototy,只不过他是个指针属性,指向prototype对象
在原型模式声明中,多了两个属性,这两个属性都是创建对象时自动生成的。__proto__
属性是实例指向原型对象的一个指针,它的作用就是指向构造函数的原型属性
constructor。
通过这两个属性,就可以访问到原型里的属性和方法了。
PS:IE
浏览器在脚本访问__proto__会不能识别,火狐和谷歌浏览器及其他某些浏览器
均能识别。虽然可以输出,但无法获取内部信息。
alert(box1.__proto__);
//[object Object]
alert(box1.constructor); //输出 function Box(){ } 。constructor是构造属性,可以获取构造函数本身 作用是通过被原型指针定位,然后得到构造函数本身,其实就是做一个连接的作用,就是对象实例对应原型对象的作用
3.
判断一个对象实例(对象引用)是否指向了该构造函数的原型对象,可以使用
isPrototypeOf()方法来测试。只要实例化了,他是自动指向的。
alert(Box.prototype.isPrototypeOf(box1));
//true 只要实例化对象,即都会指向
例如:
var obj = new Object();
alert(Object.prototype.isPrototypeOf(obj)); //true
说明只要实例化了,就默认指向
alert(Object.prototype.isPrototypeOf(box1)); //true 因为所有的实例都是Object
alert(Box.prototype.isPrototypeOf(obj)); //false
4.
原型模式的执行流程:
1.先查找构造函数实例里的属性或方法,如果有,立刻返回;
2.如果构造函数实例里没有,则去它的原型对象里找,如果有,就返回;
function Box(){} // 构造函数函数体内什么都没有,如果有,叫做实例属性和实例方法
Box.prototype.name =
‘Lee‘; //原型属性
var box1 = new Box();
alert(box1.name); //输出 Lee 构造函数实例里没有,则去它的原型对象里找
box1.name = ‘jack‘; //实例属性 并没有重写原型
alert(box1.name); //输出 jack 就近原则 先查找构造函数实例里的属性或方法,如果有,立刻返回
var box2 = new Box();
alert(box2.name); //实例属性不会共享,所以box2访问不到实例属性,只能访问到原型属性
delete box1.name; //删除实例中的属性
alert(box1.name); //输出lee
delete Box.prototype.name //删除原型中的属性
alert(box1.name); // undefined
Box.prototype.name = ‘kk‘; //覆盖原型中的属性
alert(box1.name); //输出kk
如果:
function Box(){
this.name = ‘jack‘; //实例属性
}
Box.prototype.name = ‘Lee‘; //原型属性
var box1 = new Box();
alert(box1.name); //输出 jack
5.
如何判断属性是在构造函数的实例里,还是在原型里?可以使用 hasOwnProperty()函数
来验证:
//判断实例中是否存在指定属性
alert(box.hasOwnProperty(‘name‘)); //实例里有返回 true,否则返回 false
//判断原型中是否存在指定属性
就近原则,box1访问Jack,而不是Lee; box2访问Lee,因为没有实例属性
in 操作符会在通过对象能够访问给定属性时返回 true,无论该属性存在于实例中还是原
型中。
alert(‘name‘ in box);
//true,存在实例中或原型中
我们可以通过 hasOwnProperty()方法检测属性是否存在实例中,也可以通过 in
来判断
实例或原型中是否存在属性。那么结合这两种方法,可以判断原型中是否存在属性。且只能判断原型中是否存在。
function isProperty(object, property) { //判断原型中是否存在属性
return
!object.hasOwnProperty(property) && (property in object);
//实例中没有&&原型或实例中有=>原型中有
}
var box = new
Box();
alert(isProperty(box, ‘name‘)) //true,如果原型有
标签:style blog c http strong com
原文地址:http://www.cnblogs.com/mabelstyle/p/3719853.html