您的位置:首页 > 其它

prototype

2016-01-28 12:11 260 查看
在prototype上有一个叫做constructor的属性,Person.prototype.constructor指向Person,当new Person的时候,每个实例会有一个[[prototype]]指向该对象构造函数的prototype,在chrome里面就是__proto__属性可以查看,但这不是标准的方法(ecmascript 6 把它标准化),因此实例和构造函数的prototype是有可接入的直接联系,但是实例和构造函数之间没有建立联系





判断一个对象的[[Prototype]]是否指向某个prototype对象:
alert(Person.prototype.isPrototypeOf(person1)); //true
alert(Person.prototype.isPrototypeOf(person2)); //true

使用Object.getPrototypeOf( Internet Explorer 9+,Firefox 3.5+, Safari 5+, Opera 12+, and Chrome)来取得[[Prototype]]上的值:

alert(Object.getPrototypeOf(person1) == Person.prototype); //true
alert(Object.getPrototypeOf(person1).name); //”Nicholas”

变量查找就是沿着实例和构造函数原型间的关系来的,首先在实例本身上找有没有需要的属性方法,没有的话就找构造函数原型上有没有。实例上也能访问到constructor属性值

当在实例上添加一个属性方法时,只是添加在当前实例上,不会覆盖构造函数原型上的。当你删除时,也是删除这个实例上的:





当实例上有找到属性或方法,就不会再去读取构造函数原型上的了,只有你把这个属性方法delete了,才会读取构造函数原型上的,因此有一个方法hasOwnProperty用来判断一个属性到底在哪,可以用来检测一个属性是否只存在于他的构造函数prototype上(用in来检测只要在实例或者prototype上存在该属性都会返回true):
function hasPrototypeProperty(object, name){
return !object.hasOwnProperty(name) && (name in object);
}

使用for-in循环的时候,也会把返回实例上和构造函数原型上的属性。

创建真正的空对象:
使用 var obj = Object.create(null);
将会创建真正意义上的空对象,原型链上也是空的
而使用 var obj = {};
这样obj 的原型将会指向一个位于 Object.prototype 上的对象,继承相应方法
(The most important thing about the expanded form is that object literals always set the newly created object’s prototype to an object located at Object.prototype.)

在这个构造函数里,name是一个存取器(assessor)属性,用来保存真正的名字,在strict模式里面,如果使用构造函数忘记new会出错,this不会指向全局window对象,this会保持为 undefined:

function Person(name) {
Object.defineProperty(this, "name", {
get: function() {
return name;
},
set: function(newName) {
name = newName;
},
enumerable: true,
configurable: true
});
this.sayName = function() {
console.log(this.name);
};
}

直接在原型上扩展的方法在所有实例都是可见的(继承了),Person.prototype.sayHi,但是如果重写整个prototype对象,就是新建了一个Object的实例,再把prototype指向新的实例对象,就会隔断构造函数和旧的prototype:
function Person(){ }
var friend = new Person();
Person.prototype = {
constructor: Person,
name : “Nicholas”, age : 29,
job : “Software Engineer”,
sayName : function () {
alert(this.name); }
};
friend.sayName(); //error friend实例指向的是旧的Person.prototype,而不是新的,新的实例才是指向新的

同时要注意实例的constructor会消失,因为constructor属性是在prototype对象上的:
Person.prototype = {

[align=left] constructor : Person, // 防止指向构造函数的引用失效, person1.constructor === Person 才会返回true,不过这样添加的是可遍历的,默认是不可遍历的[/align]
[align=left] sayName : function () {[/align]
[align=left] console.log( this.name);[/align]
[align=left] },[/align]
[align=left] toString : function () {[/align]
[align=left] return "[Person " + this .name + "]" ;[/align]
[align=left] }[/align]
[align=left]};[/align]
[align=left] [/align]
[align=left] [/align]
[align=left]当使用Object.seal() 或者 Object.freeze()的时候,就不能在实例上新增属性方法了,但是可以通过原型对象添加[/align]
[align=left] [/align]
[align=left] [/align]
[align=left]Object.keys() 可以返回可遍历的实例属性:[/align]

[align=left]function Person(){}[/align]
[align=left] [/align]
[align=left]Person.prototype.name = “Nicholas”;[/align]
[align=left]Person.prototype.age = 29;[/align]
[align=left]Person.prototype.job = “Software Engineer”;[/align]
[align=left]Person.prototype.sayName = function(){[/align]
[align=left] alert(this.name);[/align]
[align=left]};[/align]
[align=left]var keys = Object.keys(Person.prototype);[/align]
[align=left]alert(keys); //”name,age,job,sayName”[/align]
[align=left]var p1 = new Person();[/align]
[align=left]p1.name = “Rob”;[/align]
[align=left]p1.age = 31;[/align]
[align=left]var p1keys = Object.keys(p1);[/align]
[align=left]alert(p1keys); //”name,age”[/align]
[align=left] [/align]

[align=left] Object.getOwnPropertyNames()可以返回所有实例属性,不管是可遍历还是不可遍历:[/align]

[align=left]var keys = Object.getOwnPropertyNames(Person.prototype); //”constructor,name,age,job,sayName” [/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: