JavaScript中實(shí)現(xiàn)new的兩種方式引發(fā)的探究
前言
當(dāng)你 new 一個(gè)構(gòu)造函數(shù)時(shí)發(fā)生了什么?
“眾所周知”的三步:
創(chuàng)建一個(gè)空對(duì)象,將它的引用賦給 this,繼承函數(shù)的原型;通過(guò) this 將屬性和方法添加至這個(gè)對(duì)象;最后返回 this 指向的新對(duì)象,也就是實(shí)例。
一般來(lái)說(shuō)在js中大概是這樣的:
function Mynew(parent,...rest){
let obj={};
obj.__proto__=parent.prototype;
let res=parent.apply(obj,rest);
return typeof res=="object"?res:obj;
}
上面提到的“空對(duì)象”只是簡(jiǎn)稱。事實(shí)上,就算是定義一個(gè)
{},它也會(huì)從Object.prototype上繼承很多方法和屬性。
《JavaScript語(yǔ)言精髓與編程實(shí)踐》中提出了一個(gè)“更加空白的對(duì)象”:它有兩種情況 ——Constructor.prototype值為null;或者Object.getPrototypeOf(obj)值為null。
但通常我們還能見(jiàn)到另一種寫法:
function Mynew_2(parent,...rest){
let child=Object.create(parent.prototype);
let result=parent.apply(child,rest);
return typeof result=="object"?result:child;
}
這兩種實(shí)現(xiàn)的不同無(wú)疑引起了我的興趣!
Object.create()是怎么實(shí)現(xiàn)的?
我們來(lái)看一段代碼:
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() 失去了對(duì)原來(lái)對(duì)象屬性的訪問(wèn),而 o2 …同理。
再來(lái)看另一段代碼:
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

到這里,我似乎明白了什么,又似乎沒(méi)明白…
我決定這么做:
let b=new Best(); console.log(b);

console.log(Best.prototype);

恍然大悟!
原來(lái)我們平時(shí)說(shuō)的 “當(dāng)讀取實(shí)例屬性時(shí),如果找不到,就會(huì)查找與對(duì)象關(guān)聯(lián)的原型中的屬性;如果還找不到,就去找原型的原型,直到最頂層(__proto__ 為null)為止” 是指 “一直順著 __proto__ 向上查找”(注意:不經(jīng)過(guò)prototype?。?。
! 那 __proto__ 和 prototype 之間又有什么呢?
console.log(b.__proto__); console.log(Best.prototype);

哦!這就是我們常聽(tīng)到的“實(shí)例的 __proto__ 等于對(duì)象的 prototype ”吧。
那現(xiàn)在回過(guò)頭來(lái),打印一下 o2 這個(gè)對(duì)象:
console.log(o2);

你有沒(méi)有想到什么?
根據(jù)上面所描述的那樣,o2 就是 Best 的實(shí)例?。?/p>
所以說(shuō),create() 函數(shù)實(shí)際上返回了一個(gè)對(duì)象的實(shí)例?
但 o1 仍然“不為所動(dòng)”!

所以我們能否猜測(cè):在 Object.create() 函數(shù)中應(yīng)該是拿到對(duì)象的原型并以實(shí)例的形式返回:
Object.create=function(o){
let F=function(){};
F.prototype=o;
return new F();
}
為什么這里要用函數(shù)再 new 的方式?而不是直接用對(duì)象去接收?

這和“為什么vue中data是一個(gè)函數(shù)而不是直接的對(duì)象”其實(shí)是一個(gè)問(wèn)題:JavaScript中的對(duì)象是引用類型,在一個(gè)實(shí)例中改變某一個(gè)元素的值其余實(shí)例的值都會(huì)發(fā)生改變!
而通過(guò)create函數(shù)則不會(huì):

總結(jié)
到此這篇關(guān)于JavaScript中實(shí)現(xiàn)new的兩種方式的文章就介紹到這了,更多相關(guān)JS實(shí)現(xiàn)new的方式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Extjs顯示從數(shù)據(jù)庫(kù)取出時(shí)間轉(zhuǎn)換JSON后的出現(xiàn)問(wèn)題
后臺(tái)從數(shù)據(jù)庫(kù)取出時(shí)間,JSON格式化后再傳到gridpanel,這時(shí)時(shí)間變成了:/Date(32331121223)/這樣的格式,本文將詳細(xì)介紹解決Extjs顯示從數(shù)據(jù)庫(kù)取出時(shí)間轉(zhuǎn)換JSON后的出現(xiàn)問(wèn)題2012-11-11
梳理總結(jié)25個(gè)JavaScript數(shù)組操作方法實(shí)例
這篇文章主要分享JavaScript數(shù)組操作方法實(shí)例梳理總結(jié),刪除數(shù)組重復(fù)項(xiàng)、獲取數(shù)組的片段等方法,需要的小伙伴可以參考一下2022-06-06
JS+DIV實(shí)現(xiàn)鼠標(biāo)劃過(guò)切換層效果的實(shí)例代碼
這篇文章主要是對(duì)JS+DIV實(shí)現(xiàn)鼠標(biāo)劃過(guò)切換層效果的實(shí)例代碼進(jìn)行了詳細(xì)的介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-11-11
javascript實(shí)現(xiàn)倒計(jì)時(shí)跳轉(zhuǎn)頁(yè)面
本文給大家介紹了如何使用javascript實(shí)現(xiàn)倒計(jì)時(shí)跳轉(zhuǎn)到其他頁(yè)面的方法以及實(shí)現(xiàn)原理,非常的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下。2016-01-01
從JavaScript純函數(shù)解析最深刻的函子 Monad實(shí)例
這篇文章主要為大家介紹了從JavaScript純函數(shù)解析最深刻的函子 Monad實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
深入理解requireJS-實(shí)現(xiàn)一個(gè)簡(jiǎn)單的模塊加載器
本篇文章主要介紹了深入理解requireJS-實(shí)現(xiàn)一個(gè)簡(jiǎn)單的模塊加載器,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01

