它的Javascript構造函數屬性的意義是什麼?


Answers

第一步是了解constructorprototype是什麼。 這並不難,但必須放棄古典意義上的“繼承”。

構造函數

constructor屬性在你的程序中不會引起任何特殊的效果,除了你可以看看它是否與new運算符一起使用來創建對象。 如果你輸入new Bar()它會是Bar ,你輸入new Foo它會是Foo

原型

如果所討論的對像沒有要求的屬性,那麼prototype屬性用於查找。 如果你編寫x.attr ,JavaScript將嘗試從x的屬性中找到attr 。 如果無法找到它,它會在x.__proto__ 。 如果它不在那裡,只要定義了__proto__ ,它就會在x.__proto__.__proto__等等中查找。

那麼什麼是__proto__ ,它與prototype有什麼關係? 簡而言之, prototype是“類型”,而__proto__是“實例”。 (我用引號表示,因為類型和實例之間沒有任何區別)。 當你寫x = new MyType() ,會發生什麼(除其他外)是x.__proto___被設置為MyType.prototype

這個問題

現在,上述應該是你需要得到你自己的例子意味著什麼,但試圖回答你的實際問題; “為什麼寫一些像”:

Bar.prototype.constructor = Bar;

我個人從來沒有見過它,我覺得它有點愚蠢,但在上下文中,你會發現它將意味著Bar.prototype (由使用new Foo(42)創建)將構成由Bar創建而不是Foo 。 我猜想這個想法有些類似於C ++ / Java / C#類語言,其中類型查找( constructor屬性)總是會產生最具體的類型,而不是原型中更一般對象的類型 -鏈。

我的建議是:不要在JavaScript中考慮“繼承”。 接口和mixin的概念更有意義。 並且不要檢查對象的類型。 檢查所需的屬性,而不是(如果它像鴨子一樣走路,嘎嘎叫鴨子,它是一隻鴨子)。

試圖強制JavaScript成為經典的繼承模型,當它具有上述的原型機制時,就會導致混淆。 許多人建議手動設置constructor -property可能試圖做到這一點。 抽像是好的,但是這個手工賦值的構造函數屬性並不是JavaScript的慣用用法。

Question

試圖圍繞JavaScript的OO ...彎曲,並像其他許多人一樣,對constructor屬性產生混淆。 特別是constructor屬性的意義,因為我似乎無法使它產生任何效果。 例如:

function Foo(age) {
    this.age = age;
}

function Bar() {
    this.name = "baz"; 
}

Bar.prototype = new Foo(42); 
var b = new Bar;    

alert(b.constructor); // "Foo". That's OK because we inherit `Foo`'s prototype.
alert(b.name);        // "baz". Shows that Bar() was called as constructor.
alert(b.age);         // "42", inherited from `Foo`.

在上面的例子中,對象b似乎擁有稱為( Bar )的正確構造函數 - 並且它繼承了Foo的age屬性。 那麼為什麼很多人認為這是一個必要的步驟:

Bar.prototype.constructor = Bar;

顯然,在構造b時調用了正確的Bar構造函數,所以這個prototype屬性有什麼影響? 我很想知道它實際上使構造函數屬性設置為“正確”的實際區別 - 因為我無法看到它在創建對像後實際調用哪個構造函數時有任何影響。




您希望prototype.constructor屬性保留prototype屬性重新分配的用例之一是您在prototype.constructor定義了一個方法,該方法會生成與給定實例相同類型的新實例。 例:

function Car() { }
Car.prototype.orderOneLikeThis = function() {  // Clone producing function
    return new this.constructor();
}
Car.prototype.advertise = function () {
    console.log("I am a generic car.");
}

function BMW() { }
BMW.prototype = Object.create(Car.prototype);
BMW.prototype.constructor = BMW;              // Resetting the constructor property
BMW.prototype.advertise = function () {
    console.log("I am BMW with lots of uber features.");
}

var x5 = new BMW();

var myNewToy = x5.orderOneLikeThis();

myNewToy.advertise(); // => "I am BMW ..." if `BMW.prototype.constructor = BMW;` is not 
                      // commented; "I am a generic car." otherwise.



Links