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」                                                                               
相關文章
相關標籤/搜索