前言:用了這么久js,對於它的原型鏈一直有種模糊的不確切感,很不爽,隧解析之。
本文主要解決的問題有以下三個:
(1)constructor 和 prototype 以及實例之間啥關系?
(2)prototype是啥,__proto__又是啥,他們之間啥關系?
(3)如果改變一個 constructor 的 prototype,他的實例會發生什么改變?
ok,下面一個一個解決。
(1)constructor 和 prototype 以及實例對象三者之間啥關系?
舉例:
如上,當我們創建一個函數,系統就會為這個函數自動分配一個prototype指針,指向它的原型對象。並且可以發現,這個原型對象包含兩個部分(constructor 和 __proto__)其中constructor指向函數自身。(這里形成了一個小閉環)
當我們將該函數作為模版創建實例(new方法)的時候,我們發現創建出的實例是一個與構造函數同名的object,這個object是獨立的,他只包含了一個__proto__指針(實例沒有prototype,強行訪問則會輸出undefined),這個指針指向上面提到的構造函數的prototype原型對象。
這時候我們發現三者形成了一個大"閉環"。之所以加上引號,因為構造函數和實例之間無法直接訪問,需要通過__proto__指針間接讀取。
這個"大閉環"畫出來就是下面這個樣子啦:
到此第一個問題已經解決。
(2)prototype是啥,__proto__又是啥,他們之間啥關系?
在上一個問題中,我們用到了實例對象的__proto__指針,實際上在JavaScript中大部分類型的值都擁有__proto__屬性,例如:
當然object和function對象也有:
不過也有不存在__proto___屬性的類型,比如:
等等。
然而。只有function對象才有prototype屬性,其他任何類型的值都沒有。即使是使用new方法從function構造出的實例對象也沒有prototype屬性。
(object類型的值的prototype輸出undefined)
(我們改變了test的prototype的值,將其鏈接到一個函數名為test的函數,接着,函數類型的值的prototype輸出了一個原型對象)
so,do you understand?
(3)如果改變一個 constructor 的 prototype,他的實例會發生什么改變?
我們來做一個嘗試:
我們可以發現,改變了prototype之后創建的實例指向了新的prototype對象,而之前的依然指向老的prototype對象。
下面是個應用這個方法拓展實例的小例子:
var shape = function () { }; var p = { a: function () { console.log('aaa'); } }; shape.prototype = p; var circle = new shape(); circle.a(); //輸出'aaa'
好啦,到這里就講完啦~~撒花哈哈哈哈~~~
本文內容原創,轉載請告知~