JS new 創(chuàng)建對象原理

前言

業(yè)界最冷的笑話大概是:沒有對象宝穗?new一個唄逮矛!
尷尬而不失禮貌的微笑

怎么new一個對象呢?今天我們就來談談JS中晋控,怎樣使用new關鍵字創(chuàng)建一個對象及其實現(xiàn)原理赡译。
下文中涉及到的題外知識點:

  • es6-擴展運算符
console.log(...[1, 2, 3])
// 1 2 3
  • es6-變量的解構賦值
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

new一個對象

new 操作符后跟一個構造函數(shù)。構造函數(shù)可以是JS原生引用類型(比如:Object综看、Array红碑、Date、Number等)忠寻,也可以是自定義函數(shù)奕剃。
比如這樣

var person = new Object();
var colors = new Array();   // 數(shù)組也是對象喲

或者這樣

function Person(age) {
  this.age = age;
  console.log(this)
}
var p1 = new Person(20);

實現(xiàn)原理

1柿顶、創(chuàng)建一個空對象
2嘁锯、讓空對象的_proto_(IE沒有該屬性)成員指向了構造函數(shù)的prototype成員對象
3家乘、使用apply調用構造器函數(shù),屬性和方法被添加到 this 引用的對象中
4扑馁、如果構造函數(shù)中沒有返回其它對象腻要,那么返回 this,即創(chuàng)建的這個的新對象趟济,否則顷编,返回構造函數(shù)中返回的對象
具體如下:

function _new() {
    let obj= {}; // 創(chuàng)建的新對象
    // 第一個參數(shù)是構造函數(shù)
    let [constructor, ...args] = [...arguments];

    // 執(zhí)行 [[原型]] 連接 ;實際上就是生產(chǎn)了一個新的上下文
    obj.__proto__ = constructor.prototype;

    // 使用apply在obj作用域中調用構造器函數(shù),屬性和方法被添加到 this 引用的對象即obj中
    let result = constructor.apply(obj, args);
    if (result && (typeof (result) == "object" || typeof (result) == "function")) {
        // 如果構造函數(shù)執(zhí)行的結果返回的是一個對象钮惠,那么返回這個對象
        return result;
    }
    // 如果構造函數(shù)返回的不是一個對象,返回創(chuàng)建的新對象
    return obj;
}

結合下面的代碼片段來具體分析下:
代碼片段一

    function Person(age){
        this.age= age;
        console.log(this);
        return {age:age};//返回對象
    }
    Person.prototype.index = 1

    var person1 = new Person(20);  // 此處相當于var person1=_new(Person, 20)
    var person2 = Person(18);
     
    console.log(person1);
    console.log(person2);

    console.log('p1.index=', person1.index)
    console.log('p2.index=', person2.index)

片段一執(zhí)行結果

上面 var person1 = new Person(20)var person1=_new(Person, 20)效果相當。

  • obj._proto_ = constructor.prototype峦筒,即 obj._proto_ = Person.prototype
    將obj的_proto_(隱式原型)指向Person的原型對象,此時obj的原型鏈為:
    obj => Person.prototype => Object.prototype => null
    因此 執(zhí)行到let result = constructor.apply(target, args)這句代碼時术吗,在obj作用域中調用Person函數(shù),打印出 Person {age: 20}
    因為Person函數(shù)返回的是一個對象隘蝎,所以console.log(person1)打印出的就是返回的這個對象:{age: 20},person1.index自然就為undefined

而var person2 = Person(18)曼振,只是簡單的調用了Person函數(shù)冰评,在window全局中執(zhí)行,所以打印出Window對象长已,執(zhí)行console.log(person2)打印出:{age: 18},person2.index為undefined

代碼片段二

    function Person(age){
        this.age= age;
        console.log(this);
        // return {age:age};//返回對象
    }
    Person.prototype.index = 1

    var person1 = new Person(20);  // 相當于var person1 = _new (Person, 20);
    var person2 = Person(18);
     
    console.log(person1);
    console.log(person2);

    console.log('p1.index=', person1.index)
    console.log('p2.index=', person2.index)

片段二執(zhí)行結果

代碼片段二和代碼片段一的區(qū)別在于中剩, 片段二中構造函數(shù)Person沒有返回值(返回的不是一個對象结啼,還可以通過直接返回age驗證下效果)郊愧,所以person1接收到的實際上是_new新創(chuàng)建的對象obj属铁,即Person {age: 20}, person1.index則相當于obj.index屬性時,它會先找自身的index屬性盒发,如果找不到,則會順著原型鏈向上找间学,這時會找到People.prototype.index仍律,person1.index的結果是1善涨。
由于Person沒有返回值炕横,所以console.log(person2)結果為undefined膜钓,進而颂斜,打印person2.index時會報錯沃疮。

總結

通過new操作符糯彬,我們可以創(chuàng)建原對象的一個實例對象似扔,而這個實例對象繼承了原對象的屬性和方法,所以new存在的意義在于它實現(xiàn)了javascript中的繼承偶器,而不僅僅是實例化了一個對象。

PS: 本文參考了網(wǎng)上的一些文章加之自己的理解霎苗,若有錯誤或者不準確的地方,歡迎留言糾正检眯,非常感謝刽严!

參考鏈接:

JavaScript:new關鍵字創(chuàng)建對象底層原理
JavaScript new原理

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末鹏氧,一起剝皮案震驚了整個濱河市实蓬,隨后出現(xiàn)的幾起案子安皱,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔗草,死亡現(xiàn)場離奇詭異旷档,居然都是意外死亡彬犯,警方通過查閱死者的電腦和手機宋列,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門怎静,熙熙樓的掌柜王于貴愁眉苦臉地迎上來夜牡,“玉大人,你說我怎么就攤上這事氢哮。” “怎么了型檀?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵背零,是天一觀的道長侦镇。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么啊犬? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮应闯,結果婚禮上纤控,老公的妹妹穿的比我還像新娘。我一直安慰自己碉纺,他們只是感情好船万,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著骨田,像睡著了一般耿导。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上态贤,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天舱呻,我揣著相機與錄音,去河邊找鬼悠汽。 笑死箱吕,一個胖子當著我的面吹牛,可吹牛的內容都是我干的柿冲。 我是一名探鬼主播殖氏,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼姻采!你這毒婦竟也來了雅采?” 一聲冷哼從身側響起爵憎,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎婚瓜,沒想到半個月后宝鼓,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡巴刻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年愚铡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胡陪。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡沥寥,死狀恐怖,靈堂內的尸體忽然破棺而出柠座,到底是詐尸還是另有隱情邑雅,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布妈经,位于F島的核電站淮野,受9級特大地震影響,放射性物質發(fā)生泄漏吹泡。R本人自食惡果不足惜骤星,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爆哑。 院中可真熱鬧洞难,春花似錦、人聲如沸揭朝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽萝勤。三九已至露筒,卻和暖如春呐伞,著一層夾襖步出監(jiān)牢的瞬間敌卓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工伶氢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留趟径,地道東北人。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓癣防,卻偏偏與公主長得像蜗巧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蕾盯,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內容