JavaScript中實(shí)現(xiàn)new的兩種方式引發(fā)的探究
前言
當(dāng)你 new 一個(gè)構(gòu)造函數(shù)時(shí)發(fā)生了什么?
“眾所周知”的三步:
創(chuàng)建一個(gè)空對象,將它的引用賦給 this,繼承函數(shù)的原型;通過 this 將屬性和方法添加至這個(gè)對象;最后返回 this 指向的新對象,也就是實(shí)例。
一般來說在js中大概是這樣的:
function Mynew(parent,...rest){ let obj={}; obj.__proto__=parent.prototype; let res=parent.apply(obj,rest); return typeof res=="object"?res:obj; }
上面提到的“空對象”只是簡稱。事實(shí)上,就算是定義一個(gè)
{}
,它也會(huì)從Object.prototype
上繼承很多方法和屬性。
《JavaScript語言精髓與編程實(shí)踐》中提出了一個(gè)“更加空白的對象”:它有兩種情況 ——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; }
這兩種實(shí)現(xiàn)的不同無疑引起了我的興趣!
Object.create()是怎么實(shí)現(xiàn)的?
我們來看一段代碼:
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);
恍然大悟!
原來我們平時(shí)說的 “當(dāng)讀取實(shí)例屬性時(shí),如果找不到,就會(huì)查找與對象關(guān)聯(lián)的原型中的屬性;如果還找不到,就去找原型的原型,直到最頂層(__proto__
為null)為止” 是指 “一直順著 __proto__
向上查找”(注意:不經(jīng)過prototype?。?。
! 那 __proto__
和 prototype
之間又有什么呢?
console.log(b.__proto__); console.log(Best.prototype);
哦!這就是我們常聽到的“實(shí)例的 __proto__
等于對象的 prototype
”吧。
那現(xiàn)在回過頭來,打印一下 o2 這個(gè)對象:
console.log(o2);
你有沒有想到什么?
根據(jù)上面所描述的那樣,o2 就是 Best 的實(shí)例啊!
所以說,create()
函數(shù)實(shí)際上返回了一個(gè)對象的實(shí)例?
但 o1 仍然“不為所動(dòng)”!
所以我們能否猜測:在 Object.create()
函數(shù)中應(yīng)該是拿到對象的原型并以實(shí)例的形式返回:
Object.create=function(o){ let F=function(){}; F.prototype=o; return new F(); }
為什么這里要用函數(shù)再 new 的方式?而不是直接用對象去接收?
這和“為什么vue中data是一個(gè)函數(shù)而不是直接的對象”其實(shí)是一個(gè)問題:JavaScript中的對象是引用類型,在一個(gè)實(shí)例中改變某一個(gè)元素的值其余實(shí)例的值都會(huì)發(fā)生改變!
而通過create函數(shù)則不會(huì):
總結(jié)
到此這篇關(guān)于JavaScript中實(shí)現(xiàn)new的兩種方式的文章就介紹到這了,更多相關(guān)JS實(shí)現(xiàn)new的方式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解ES6新增字符串?dāng)U張方法includes()、startsWith()、endsWith()
這篇文章主要介紹了詳解ES6新增字符串?dāng)U張方法includes()、startsWith()、endsWith(),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05JavaScript動(dòng)畫實(shí)例之粒子文本的實(shí)現(xiàn)方法詳解
這篇文章主要介紹了JavaScript動(dòng)畫實(shí)例之粒子文本的實(shí)現(xiàn)方法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07JavaScript中有關(guān)一個(gè)數(shù)組中最大值和最小值及它們的下表的輸出的解決辦法
這篇文章主要介紹了JavaScript中有關(guān)一個(gè)數(shù)組中最大值和最小值及它們的下表的輸出的一種解決辦法,本文還給大家介紹了js快速獲取數(shù)組中最大值和最小值的方法,非常不錯(cuò),需要的朋友可以參考下2016-07-07JS獲取計(jì)算機(jī)mac地址以及IP的實(shí)現(xiàn)方法
本篇文章主要是對利用JS獲取計(jì)算機(jī)mac地址以及IP的實(shí)現(xiàn)方法進(jìn)行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助2014-01-01一個(gè)獲取第n個(gè)元素節(jié)點(diǎn)的js函數(shù)
這篇文章主要介紹了一個(gè)獲取第n個(gè)元素節(jié)點(diǎn)的js函數(shù),功能還不完善 ,需要的朋友可以參考下2014-09-09