js中constructor和prototype


在最開始學習js的時候,我們在講到原型鏈和構造函數的時候經常會有一個例子

如果我們定義函數如下:

function Foo() { /* .. */ }
Foo.prototype.bar = function(){}; 
var a1 = new Foo();
a1.constructor === Foo; // true!

但是如果我們中間改變了Foo.prototype的定義,那么a1.constructor的指向就改變了。

function Foo() { /* .. */ }
Foo.prototype = { /* .. */ }; // 創建一個新原型對象
var a1 = new Foo();
a1.constructor === Foo; // false!
a1.constructor === Object; // true!

對於這個事實,這里通過我的理解來解釋一下。

首先js中並沒有像java這種面向對象語言一樣,Foo並不是作為一個類存在,而是普通的函數。當new操作符執行的時候,Foo函數作為構造函數調用,形成a1的原型鏈,將a1的__proto__關聯到Foo.prototype,也就是說這里並不是復制的關系,只是關聯,Foo.prototype改變時,a1.__proto__也會改變。

在第一個例子中a1.constructor === Foo;看起來是a1的constructor指向了Foo,但是事實並非如此。實際上,是在new的時候,a1.constructor被委托給了Foo.prototype.constructor,所以當第二個例子Foo.prototype = {}時,a1.constructor就不再指向Foo了,而是指向了Object。因為如下例子:

var Foo ={};

console.log(Foo.constructor === Object);//true

也就是Foo.prototype的constructor屬性只是在Foo函數聲明的時候默認生成的。如果替換了Foo.prototype的引用,那么constructor也會隨之發生改變。

 

總結:

1. constructor屬性會在函數聲明時默認生成。在利用new創建對象實例時,對象實例本身並沒有constructor屬性,但對象實例的__proto__屬性和Foo.prototype屬性關聯,行程原型鏈,因此會通過原型鏈找到Foo.prototype.constructor屬性,並以此為值。

2. prototype屬性可能會被重寫,重寫后,原來的constructor會發生改變。如果顯示為constructor賦值,可以糾正。

3. 因為constructor的屬性很隨意,所以慎用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM