JavaScript中實現new的兩種方式引發的探究
前言
當你 new 一個構造函數時發生瞭什麼?
“眾所周知”的三步:
創建一個空對象,將它的引用賦給 this,繼承函數的原型;通過 this 將屬性和方法添加至這個對象;最後返回 this 指向的新對象,也就是實例。
一般來說在js中大概是這樣的:
function Mynew(parent,...rest){ let obj={}; obj.__proto__=parent.prototype; let res=parent.apply(obj,rest); return typeof res=="object"?res:obj; }
上面提到的“空對象”隻是簡稱。事實上,就算是定義一個
{}
,它也會從Object.prototype
上繼承很多方法和屬性。
《JavaScript語言精髓與編程實踐》中提出瞭一個“更加空白的對象”:它有兩種情況 ——Constructor.prototype
值為null;或者Object.getPrototypeOf(obj)
值為null。
但通常我們還能見到另一種寫法:
function Mynew_2(parent,...rest){ let child=Object.create(parent.prototype); let result=parent.apply(child,rest); return typeof result=="object"?result:child; }
這兩種實現的不同無疑引起瞭我的興趣!
Object.create()是怎麼實現的?
我們來看一段代碼:
var Best1=function(){ this.a=2; } var o1=Object.create(Best1); var o2=Object.create(Best1.prototype); console.log(o1.a); // undefined console.log(o2.a); // undefined
可以看到,以 o1 為例,Object.create()
失去瞭對原來對象屬性的訪問,而 o2 …同理。
再來看另一段代碼:
var Best=function(){ this.a=2; } Best.prototype.a=3; var o1=Object.create(Best); var o2=Object.create(Best.prototype); console.log(o1.a); // undefined console.log(o2.a); // 3
到這裡,我似乎明白瞭什麼,又似乎沒明白…
我決定這麼做:
let b=new Best(); console.log(b);
console.log(Best.prototype);
恍然大悟!
原來我們平時說的 “當讀取實例屬性時,如果找不到,就會查找與對象關聯的原型中的屬性;如果還找不到,就去找原型的原型,直到最頂層(__proto__
為null)為止” 是指 “一直順著 __proto__
向上查找”(註意:不經過prototype!)。
! 那 __proto__
和 prototype
之間又有什麼呢?
console.log(b.__proto__); console.log(Best.prototype);
哦!這就是我們常聽到的“實例的 __proto__
等於對象的 prototype
”吧。
那現在回過頭來,打印一下 o2 這個對象:
console.log(o2);
你有沒有想到什麼?
根據上面所描述的那樣,o2 就是 Best 的實例啊!
所以說,create()
函數實際上返回瞭一個對象的實例?
但 o1 仍然“不為所動”!
所以我們能否猜測:在 Object.create()
函數中應該是拿到對象的原型並以實例的形式返回:
Object.create=function(o){ let F=function(){}; F.prototype=o; return new F(); }
為什麼這裡要用函數再 new 的方式?而不是直接用對象去接收?
這和“為什麼vue中data是一個函數而不是直接的對象”其實是一個問題:JavaScript中的對象是引用類型,在一個實例中改變某一個元素的值其餘實例的值都會發生改變!
而通過create函數則不會:
總結
到此這篇關於JavaScript中實現new的兩種方式的文章就介紹到這瞭,更多相關JS實現new的方式內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Javascript 原型與原型鏈深入詳解
- 如何利用JavaScript 實現繼承
- 一文徹底理解js原生語法prototype,__proto__和constructor
- JavaScript中new操作符的原理與實現詳解
- JavaScript數據結構常見面試問題整理