在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);
Object.getOwnPropertyNames()能夠返回全部實例屬性,無論是可遍歷仍是不可遍歷:
var keys = Object.getOwnPropertyNames(Person.prototype); //」constructor,name,age,job,sayName」