prototype
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了prototype相关的知识,希望对你有一定的参考价值。
在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 = {
constructor : Person, // 防止指向构造函数的引用失效, person1.constructor === Person 才会返回true,不过这样添加的是可遍历的,默认是不可遍历的
sayName : function () {
console.log( this.name);
},
toString : function () {
return "[Person " + this .name + "]" ;
}
};
当使用Object.seal() 或者 Object.freeze()的时候,就不能在实例上新增属性方法了,但是可以通过原型对象添加
Object.keys() 可以返回可遍历的实例属性:
function Person(){}
Person.prototype.name = “Nicholas”;
Person.prototype.age = 29;
Person.prototype.job = “Software Engineer”;
Person.prototype.sayName = function(){
alert(this.name);
};
var keys = Object.keys(Person.prototype);
alert(keys); //”name,age,job,sayName”
var p1 = new Person();
p1.name = “Rob”;
p1.age = 31;
var p1keys = Object.keys(p1);
alert(p1keys); //”name,age”
Object.getOwnPropertyNames()可以返回所有实例属性,不管是可遍历还是不可遍历:
var keys = Object.getOwnPropertyNames(Person.prototype); //”constructor,name,age,job,sayName”
以上是关于prototype的主要内容,如果未能解决你的问题,请参考以下文章