成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

你真的弄明白 new 了嗎

tolerious / 622人閱讀

摘要:如果構(gòu)造函數(shù)有返回值呢一般情況下構(gòu)造函數(shù)沒有返回值,但是我們依舊可以得到該對(duì)象的實(shí)例如果構(gòu)造函數(shù)有返回值,憑直覺來說情況應(yīng)該會(huì)不一樣。歡迎光臨小弟博客我的博客原文你真的弄明白了嗎參考再談面向?qū)ο缶幊痰膶?shí)例化與繼承請(qǐng)停止使用關(guān)鍵字

好久沒有寫點(diǎn)東西了,總覺得自己應(yīng)該寫點(diǎn)牛逼的,卻又不知道如何下筆。既然如此,還是回歸最基本的吧,今天就來說一說這個(gè)new。關(guān)于javascript的new關(guān)鍵字的內(nèi)容上網(wǎng)搜一搜還真不少,大家都說new干了3件事:

創(chuàng)建一個(gè)空對(duì)象

將空對(duì)象的__proto__指向構(gòu)造函數(shù)的prototype

使用空對(duì)象作為上下文調(diào)用構(gòu)造函數(shù)

文字比較難懂,翻譯成javascript:

javascriptfunction Base() {
    this.str = "aa";
}

// new Base()干了下面的事
var obj  = {};
obj.__proto__ = Base.prototype;
Base.call(obj);

想想是這么回事哈,那就趕快試試:

javascriptvar b = new Base();
console.dir(b); // Base {str: "aa", __proto__: Base}

好像是正確的,但是真的正確嗎???

真的就3件事?

每個(gè)對(duì)象都有一個(gè)constructor屬性,那么我們來試試看new出來的實(shí)例的constructor是什么吧。

javascriptconsole.dir(b.constructor); // [Function: Base]

可以看出實(shí)例b的constructor屬性就是Base,那么我們可以猜測(cè)new是不是至少還做了第4件事:

javascriptb.constructor = Base;

以上結(jié)果看似正確,下面我們進(jìn)行一點(diǎn)修改,這里我們修改掉原型的constructor屬性:

javascriptBase.prototype.constructor = function Other(){ };
var b = new Base();
console.dir(b.constructor); // [Function: Other]

情況就不一樣了,可以看出,之前的猜測(cè)是錯(cuò)誤的,第4件事應(yīng)該是這樣的:

javascriptb.constructor = Base.prototype.constructor;

這里犯了一個(gè)錯(cuò)誤,那就是沒有理解好這個(gè)constructor的實(shí)質(zhì):當(dāng)我們創(chuàng)建一個(gè)函數(shù)時(shí),會(huì)自動(dòng)生成對(duì)應(yīng)的原型,這個(gè)原型包含一個(gè)constructor屬性,使用new構(gòu)造的實(shí)例,可以通過原型鏈查找到constructor。如下圖所示:

這里非常感謝zonxin同學(xué)指出我的錯(cuò)誤。

如果構(gòu)造函數(shù)有返回值呢?

一般情況下構(gòu)造函數(shù)沒有返回值,但是我們依舊可以得到該對(duì)象的實(shí)例;如果構(gòu)造函數(shù)有返回值,憑直覺來說情況應(yīng)該會(huì)不一樣。我們對(duì)于之前的構(gòu)造函數(shù)進(jìn)行一點(diǎn)點(diǎn)修改:

javascriptfunction Base() {
    this.str = "aa";
    return 1;
    // return "a";
    // return true;
}
var b = new Base();
console.dir(b); // { str: "aa"}

我們?cè)跇?gòu)造函數(shù)里設(shè)置的返回值好像沒什么用,返回的還是原來對(duì)象的實(shí)例,換一些例子試試:

javascriptfunction Base() {
    this.str = "aa";
    return [1];
    // return {a:1};
}
var b = new Base();
console.dir(b); // [1] or {a: 1}

此時(shí)結(jié)果就不一樣了,從上面的例子可以看出,如果構(gòu)造函數(shù)返回的是原始值,那么這個(gè)返回值會(huì)被忽略,如果返回的是對(duì)象,就會(huì)覆蓋構(gòu)造的實(shí)例。

new至少做了4件事

總結(jié)一下,new至少做了4件事:

javascript// new Base();

// 1.創(chuàng)建一個(gè)空對(duì)象 obj
var obj = {};
// 2.設(shè)置obj的__proto__為原型
obj.__proto__ = Base.prototype;
// 3.使用obj作為上下文調(diào)用Base函數(shù)
var ret = Base.call(obj);
// 4.如果構(gòu)造函數(shù)返回的是原始值,那么這個(gè)返回值會(huì)被忽略,如果返回的是對(duì)象,就會(huì)覆蓋構(gòu)造的實(shí)例
if(typeof ret == "object"){
    return ret;
} else {
    return obj;
}
new的不足

在《Javascript語言精粹》(Javascript: The Good Parts)中,道格拉斯認(rèn)為應(yīng)該避免使用new關(guān)鍵字:

  

If you forget to include the new prefix when calling a constructor function, then this will not be bound to the new object. Sadly, this will be bound to the global object, so instead of augmenting your new object, you will be clobbering global variables. That is really bad. There is no compile warning, and there is no runtime warning.

大意是說在應(yīng)該使用new的時(shí)候如果忘了new關(guān)鍵字,會(huì)引發(fā)一些問題。最重要的問題就是影響了原型查找,原型查找是沿著__proto__進(jìn)行的,而任何函數(shù)都是Function的實(shí)例,一旦沒用使用new,你就會(huì)發(fā)現(xiàn)什么屬性都查找不到了,因?yàn)橄喈?dāng)于直接短路了。如下面例子所示,沒有使用new來創(chuàng)建對(duì)象的話,就無法找到原型上的fa1屬性了:

javascriptfunction F(){ }
F.prototype.fa1 = "fa1";

console.log(F.fa1);       // undefined
console.log(new F().fa1); // fa1

這里我配合一張圖來說明其中原理,黃色的線為原型鏈,使用new構(gòu)造的對(duì)象可以正常查找到屬性fa1,沒有使用new則完全走向了另外一條查找路徑:

以上的問題對(duì)于有繼承的情況表現(xiàn)得更為明顯,沿著原型鏈的方法和屬性全都找不到,你能使用的只有短路之后的Function.prototype的屬性和方法了。

當(dāng)然了,遺忘使用任何關(guān)鍵字都會(huì)引起一系列的問題。再退一步說,這個(gè)問題是完全可以避免的:

javascriptfunction foo()
{   
   // 如果忘了使用關(guān)鍵字,這一步驟會(huì)悄悄幫你修復(fù)這個(gè)問題
   if ( !(this instanceof foo) )
      return new foo();

   // 構(gòu)造函數(shù)的邏輯繼續(xù)……
}

可以看出new并不是一個(gè)很好的實(shí)踐,道格拉斯將這個(gè)問題描述為:

  

This indirection was intended to make the language seem more familiar to classically trained programmers, but failed to do that, as we can see from the very low opinion Java programmers have of JavaScript. JavaScript’s constructor pattern did not appeal to the classical crowd. It also obscured JavaScript’s true prototypal nature. As a result, there are very few programmers who know how to use the language effectively.

簡(jiǎn)單來說,JavaScript是一種prototypical類型語言,在創(chuàng)建之初,是為了迎合市場(chǎng)的需要,讓人們覺得它和Java是類似的,才引入了new關(guān)鍵字。Javascript本應(yīng)通過它的Prototypical特性來實(shí)現(xiàn)實(shí)例化和繼承,但new關(guān)鍵字讓它變得不倫不類。

再說一點(diǎn)關(guān)于constructor的

雖然使用new創(chuàng)建新對(duì)象的時(shí)候用討論了這個(gè)constructor屬性,但是這個(gè)屬性似乎并沒有什么用,也許設(shè)置這個(gè)屬性就是一種習(xí)慣,能夠讓其他人直觀理解對(duì)象之間的關(guān)系。

歡迎光臨小弟博客:Superlin"s Blog
我的博客原文:你真的弄明白new了嗎

參考

再談javascript面向?qū)ο缶幊?/p>

JavaScript的實(shí)例化與繼承:請(qǐng)停止使用new關(guān)鍵字

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/85678.html

相關(guān)文章

  • 真的明白javascript中的原型和原型鏈了嗎

    摘要:補(bǔ)充的知識(shí)這個(gè)是原型中的自帶屬性,指向構(gòu)造函數(shù)這個(gè)屬性其實(shí)是瀏覽器實(shí)現(xiàn)的,不是標(biāo)準(zhǔn)的訪問原型的方式中規(guī)定的正式方法是以上知識(shí),最終的圖如下思考題在文章開頭我們說過函數(shù)也是對(duì)象,既然是對(duì)象就有原型,那的原型指向誰呢是嗎 文章開頭說的話 首先你必須明白(或者記住)的JavaScript常識(shí): 在JavaScript中每個(gè)函數(shù)都有一個(gè)prototype屬性 在JavaScript中每個(gè)對(duì)象...

    Harpsichord1207 評(píng)論0 收藏0
  • 說下性能優(yōu)化

    摘要:性能優(yōu)化追求的是什么是你的網(wǎng)頁可以以最快的速度打開比如說用戶點(diǎn)一下啪的就開了點(diǎn)哪里哪里開什么操作都是立刻有反饋關(guān)鍵字是速度試想未來有一天到了時(shí)代每個(gè)人的網(wǎng)速都是的那你還優(yōu)化什么你的網(wǎng)站就算是大小也不怕可是那是遙遠(yuǎn)的未來當(dāng)下網(wǎng)速還沒有這么快。 性能優(yōu)化 追求的是什么, 是你的網(wǎng)頁可以 以最快的速度 打開, 比如說用戶點(diǎn)一下啪的就開了點(diǎn)哪里哪里開, 什么操作都是立刻有反饋. 關(guān)鍵字是:速度...

    王偉廷 評(píng)論0 收藏0
  • 關(guān)于python編碼,真的明白了嗎

    摘要:二進(jìn)制位,是計(jì)算機(jī)內(nèi)部數(shù)據(jù)儲(chǔ)存的最小單位,是一個(gè)位二進(jìn)制數(shù)。由于源代碼也是一個(gè)文本文件,所以,當(dāng)你的源代碼中包含中文的時(shí)候,在保存源代碼時(shí),就需要?jiǎng)?wù)必指定保存為編碼。 計(jì)算機(jī)存儲(chǔ)的幾個(gè)概念 想要徹底搞清楚編碼問題,我們必須要先搞清楚計(jì)算機(jī)是怎么存儲(chǔ)數(shù)據(jù)的,這就涉及到了計(jì)算機(jī)基礎(chǔ)的幾個(gè)概念了,開篇我們就先來捋捋這幾個(gè)容易混淆的概念。 bit 二進(jìn)制位, 是計(jì)算機(jī)內(nèi)部數(shù)據(jù)儲(chǔ)存的最小單位,1...

    darcrand 評(píng)論0 收藏0
  • 一份Docker的反方辯論——我還是用Heroku好了

    摘要:那都是老一套了。已死已經(jīng)沒有人用了?,F(xiàn)在所有的一切都在容器化,它是未來。這是確保它可靠的唯一方式。我現(xiàn)在需要一個(gè)是的,為了穩(wěn)定性。我猜是規(guī)模的對(duì),沒錯(cuò)。我明白了,好吧,我懂了。那我來重復(fù)一遍確保我領(lǐng)悟了這些。 這是一篇在國外社區(qū)非常火的文章。由CircleCI創(chuàng)始人所寫,追逐熱點(diǎn)新技術(shù)的程序員與只想做個(gè)簡(jiǎn)單web應(yīng)用的程序員對(duì)話,Docker到底能否解決簡(jiǎn)單小應(yīng)用的問題嗎?Herok...

    codeGoogle 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<