2014-05-14 50 views
0

我目前正在通過擴展函數原型和我像這樣函數/變量的對象中設置JavaScript類....出現外原型JS類變量的變化

//class shorthand 
var clss = function(args){ 
    var c = function() {}; 
    _.extend(c.prototype, args); //using underscore.js 
    return c; 
}; 

//class definition 
var ThisIsMyClass = clss({ 
    varExample: 5, 
    test: function() { 
     console.log(this.varExample); 
    }, 
    alter: function(){ 
     this.varExample = 8; 
    } 
}); 

//class initialisers 
var hello = new ThisIsMyClass(); 
var hi = new ThisIsMyClass(); 
var ayup = new ThisIsMyClass(); 

我的問題是,這裏的一切都駐留ThisIsMyClass.prototype和函數可以被調用並且變量被讀取,但是當值被改變時,它們會出現在該對象的原型之外(並且還保留在具有其原始值的原型中)?

運行此代碼

//class initialisers 
hello.varExample = 6; 
hi.alter(); 
//look at object structure 
console.log(hello); 
console.log(ayup); 
console.log(hi); 
//trace the values 
hello.test(); 
ayup.test(); 
hi.test(); 

控制檯看起來像這樣 Console

是原型只是結構的參考,然後在作出任何改變,但它們複製到對象本身後?

回答

1

當您讀取某個對象的屬性時,解釋器首先會查看該屬性的實際對象本身。如果它在那裏找到它,它會返回該值。如果它沒有在實際對象上找到該屬性,那麼它會在原型上查找。如果它在原型上找到屬性,它將返回該值。

當您在對象上設置屬性時,它始終在實際對象上設置屬性(不在原型上)。所以,一旦你設置了一個對象的屬性,任何對該屬性的讀取都將來自你在實際對象上設置的屬性,而不是原型上的屬性。將屬性直接設置到對象上本質上「隱藏」或「覆蓋」原型上設置的值。您可以將原型視爲屬性的默認值,但只要您在對象本身上設置了原型,原型值就不再使用。

function foo() {} 

foo.prototype.greet = function() { 
    console.log("Hello"); 
} 

var x = new foo(); 
x.greet();  // will log "Hello" - finds method on the prototype 

// set new method - will set this property directly on the object itself 
// overriding what was on the prototype 
x.greet = function() { 
    console.log("Goodbye"); 
} 
x.greet();  // will log "Goodbye" - finds method on the object 

演示:http://jsfiddle.net/jfriend00/h6akb/


在javascript對象的實現方式中,對象具有兩個一組對象本身和它的原型的基準上的屬性。查找屬性時,首先查找對象本身。如果在那裏沒有找到,那麼解釋器將獲得對原型的引用,並在原型對象上查找屬性。原型對象本身只是另一個對象,所以解釋器直接在原型對象上查找屬性,並且如果找到則返回它。如果沒有找到,它會檢查原型對象本身是否有原型等等(允許繼承鏈)。