亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

【進(jìn)階3-5期】深度解析 new 原理及模擬實(shí)現(xiàn)

Baaaan / 2726人閱讀

摘要:使用指定的參數(shù)調(diào)用構(gòu)造函數(shù),并將綁定到新創(chuàng)建的對(duì)象。由構(gòu)造函數(shù)返回的對(duì)象就是表達(dá)式的結(jié)果。情況返回以外的基本類型實(shí)例中只能訪問(wèn)到構(gòu)造函數(shù)中的屬性,和情況完全相反,結(jié)果相當(dāng)于沒(méi)有返回值。

定義
new 運(yùn)算符創(chuàng)建一個(gè)用戶定義的對(duì)象類型的實(shí)例或具有構(gòu)造函數(shù)的內(nèi)置對(duì)象的實(shí)例。 ——(來(lái)自于MDN)

舉個(gè)栗子

function Car(color) {
    this.color = color;
}
Car.prototype.start = function() {
    console.log(this.color + " car start");
}

var car = new Car("black");
car.color; // 訪問(wèn)構(gòu)造函數(shù)里的屬性
// black

car.start(); // 訪問(wèn)原型里的屬性
// black car start

可以看出 new 創(chuàng)建的實(shí)例有以下 2 個(gè)特性

1、訪問(wèn)到構(gòu)造函數(shù)里的屬性

2、訪問(wèn)到原型里的屬性

注意點(diǎn)

ES6新增 symbol 類型,不可以使用 new Symbol(),因?yàn)?symbol 是基本數(shù)據(jù)類型,每個(gè)從Symbol()返回的 symbol 值都是唯一的。

Number("123"); // 123
String(123); // "123"
Boolean(123); // true
Symbol(123); // Symbol(123)

new Number("123"); // Number?{123}
new String(123); // String?{"123"}
new Boolean(true); // Boolean?{true}
new Symbol(123); // Symbol is not a constructor
模擬實(shí)現(xiàn)

當(dāng)代碼 new Foo(...) 執(zhí)行時(shí),會(huì)發(fā)生以下事情:

一個(gè)繼承自 Foo.prototype 的新對(duì)象被創(chuàng)建。

使用指定的參數(shù)調(diào)用構(gòu)造函數(shù) Foo ,并將 this 綁定到新創(chuàng)建的對(duì)象。new Foo 等同于 new Foo(),也就是沒(méi)有指定參數(shù)列表,Foo 不帶任何參數(shù)調(diào)用的情況。

由構(gòu)造函數(shù)返回的對(duì)象就是 new 表達(dá)式的結(jié)果。如果構(gòu)造函數(shù)沒(méi)有顯式返回一個(gè)對(duì)象,則使用步驟1創(chuàng)建的對(duì)象。

模擬實(shí)現(xiàn)第一步

new 是關(guān)鍵詞,不可以直接覆蓋。這里使用 create 來(lái)模擬實(shí)現(xiàn) new 的效果。

new 返回一個(gè)新對(duì)象,通過(guò) obj.__proto__ = Con.prototype 繼承構(gòu)造函數(shù)的原型,同時(shí)通過(guò) Con.apply(obj, arguments)調(diào)用父構(gòu)造函數(shù)實(shí)現(xiàn)繼承,獲取構(gòu)造函數(shù)上的屬性(【進(jìn)階3-3期】)。

實(shí)現(xiàn)代碼如下

// 第一版
function create() {
    // 創(chuàng)建一個(gè)空的對(duì)象
    var obj = new Object(),
    // 獲得構(gòu)造函數(shù),arguments中去除第一個(gè)參數(shù)
    Con = [].shift.call(arguments);
    // 鏈接到原型,obj 可以訪問(wèn)到構(gòu)造函數(shù)原型中的屬性
    obj.__proto__ = Con.prototype;
    // 綁定 this 實(shí)現(xiàn)繼承,obj 可以訪問(wèn)到構(gòu)造函數(shù)中的屬性
    Con.apply(obj, arguments);
    // 返回對(duì)象
    return obj;
};

測(cè)試一下

// 測(cè)試用例
function Car(color) {
    this.color = color;
}
Car.prototype.start = function() {
    console.log(this.color + " car start");
}

var car = create(Car, "black");
car.color;
// black

car.start();
// black car start

完美!

不熟悉 apply / call 的點(diǎn)擊查看:【進(jìn)階3-3期】深度解析 call 和 apply 原理、使用場(chǎng)景及實(shí)現(xiàn)

不熟悉繼承的點(diǎn)擊查看:JavaScript常用八種繼承方案

模擬實(shí)現(xiàn)第二步

上面的代碼已經(jīng)實(shí)現(xiàn)了 80%,現(xiàn)在繼續(xù)優(yōu)化。

構(gòu)造函數(shù)返回值有如下三種情況:

1、返回一個(gè)對(duì)象

2、沒(méi)有 return,即返回 undefined

3、返回undefined 以外的基本類型

情況1:返回一個(gè)對(duì)象

function Car(color, name) {
    this.color = color;
    return {
        name: name
    }
}

var car = new Car("black", "BMW");
car.color;
// undefined

car.name;
// "BMW"

實(shí)例 car 中只能訪問(wèn)到返回對(duì)象中的屬性。

情況2:沒(méi)有 return,即返回 undefined

function Car(color, name) {
    this.color = color;
}

var car = new Car("black", "BMW");
car.color;
// black

car.name;
// undefined

實(shí)例 car 中只能訪問(wèn)到構(gòu)造函數(shù)中的屬性,和情況1完全相反。

情況3:返回undefined 以外的基本類型

function Car(color, name) {
    this.color = color;
    return "new car";
}

var car = new Car("black", "BMW");
car.color;
// black

car.name;
// undefined

實(shí)例 car 中只能訪問(wèn)到構(gòu)造函數(shù)中的屬性,和情況1完全相反,結(jié)果相當(dāng)于沒(méi)有返回值。

所以需要判斷下返回的值是不是一個(gè)對(duì)象,如果是對(duì)象則返回這個(gè)對(duì)象,不然返回新創(chuàng)建的 obj對(duì)象。

所以實(shí)現(xiàn)代碼如下:

// 第二版
function create() {
    // 創(chuàng)建一個(gè)空的對(duì)象
    var obj = new Object(),
    // 獲得構(gòu)造函數(shù),arguments中去除第一個(gè)參數(shù)
    Con = [].shift.call(arguments);
    // 鏈接到原型,obj 可以訪問(wèn)到構(gòu)造函數(shù)原型中的屬性
    obj.__proto__ = Con.prototype;
    // 綁定 this 實(shí)現(xiàn)繼承,obj 可以訪問(wèn)到構(gòu)造函數(shù)中的屬性
    var ret = Con.apply(obj, arguments);
    // 優(yōu)先返回構(gòu)造函數(shù)返回的對(duì)象
    return ret instanceof Object ? ret : obj;
};
【進(jìn)階3-4期】思考題解

問(wèn)題:用 JS 實(shí)現(xiàn)一個(gè)無(wú)限累加的函數(shù) add,示例如下:

add(1); // 1
add(1)(2);  // 3
add(1)(2)(3); // 6
add(1)(2)(3)(4); // 10 

// 以此類推

實(shí)現(xiàn):

function add(a) {
    function sum(b) { // 使用閉包
        a = a + b; // 累加
        return sum;
     }
     sum.toString = function() { // 重寫(xiě)toString()方法
        return a;
    }
     return sum; // 返回一個(gè)函數(shù)
}

add(1); // 1
add(1)(2);  // 3
add(1)(2)(3); // 6
add(1)(2)(3)(4); // 10 

我們知道打印函數(shù)時(shí)會(huì)自動(dòng)調(diào)用 toString()方法,函數(shù) add(a) 返回一個(gè)閉包 sum(b),函數(shù) sum() 中累加計(jì)算 a = a + b,只需要重寫(xiě)sum.toString()方法返回變量 a 就OK了。

參考
JavaScript 深入之 new 的模擬實(shí)現(xiàn)

MDN 之 new 運(yùn)算符

MDN 之 Symbol

javascript 函數(shù) add(1)(2)(3)(4) 實(shí)現(xiàn)無(wú)限極累加

進(jìn)階系列目錄

【進(jìn)階1期】 調(diào)用堆棧

【進(jìn)階2期】 作用域閉包

【進(jìn)階3期】 this全面解析

【進(jìn)階4期】 深淺拷貝原理

【進(jìn)階5期】 原型Prototype

【進(jìn)階6期】 高階函數(shù)

【進(jìn)階7期】 事件機(jī)制

【進(jìn)階8期】 Event Loop原理

【進(jìn)階9期】 Promise原理

【進(jìn)階10期】Async/Await原理

【進(jìn)階11期】防抖/節(jié)流原理

【進(jìn)階12期】模塊化詳解

【進(jìn)階13期】ES6重難點(diǎn)

【進(jìn)階14期】計(jì)算機(jī)網(wǎng)絡(luò)概述

【進(jìn)階15期】瀏覽器渲染原理

【進(jìn)階16期】webpack配置

【進(jìn)階17期】webpack原理

【進(jìn)階18期】前端監(jiān)控

【進(jìn)階19期】跨域和安全

【進(jìn)階20期】性能優(yōu)化

【進(jìn)階21期】VirtualDom原理

【進(jìn)階22期】Diff算法

【進(jìn)階23期】MVVM雙向綁定

【進(jìn)階24期】Vuex原理

【進(jìn)階25期】Redux原理

【進(jìn)階26期】路由原理

【進(jìn)階27期】VueRouter源碼解析

【進(jìn)階28期】ReactRouter源碼解析

交流

進(jìn)階系列文章匯總?cè)缦拢瑑?nèi)有優(yōu)質(zhì)前端資料,覺(jué)得不錯(cuò)點(diǎn)個(gè)star。

https://github.com/yygmind/blog

我是木易楊,網(wǎng)易高級(jí)前端工程師,跟著我每周重點(diǎn)攻克一個(gè)前端面試重難點(diǎn)。接下來(lái)讓我?guī)阕哌M(jìn)高級(jí)前端的世界,在進(jìn)階的路上,共勉!

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

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

相關(guān)文章

  • 進(jìn)階3-4深度解析bind原理、使用場(chǎng)景模擬實(shí)現(xiàn)

    摘要:返回的綁定函數(shù)也能使用操作符創(chuàng)建對(duì)象這種行為就像把原函數(shù)當(dāng)成構(gòu)造器,提供的值被忽略,同時(shí)調(diào)用時(shí)的參數(shù)被提供給模擬函數(shù)。 bind() bind() 方法會(huì)創(chuàng)建一個(gè)新函數(shù),當(dāng)這個(gè)新函數(shù)被調(diào)用時(shí),它的 this 值是傳遞給 bind() 的第一個(gè)參數(shù),傳入bind方法的第二個(gè)以及以后的參數(shù)加上綁定函數(shù)運(yùn)行時(shí)本身的參數(shù)按照順序作為原函數(shù)的參數(shù)來(lái)調(diào)用原函數(shù)。bind返回的綁定函數(shù)也能使用 n...

    guyan0319 評(píng)論0 收藏0
  • 進(jìn)階3-3深度解析 call 和 apply 原理、使用場(chǎng)景實(shí)現(xiàn)

    摘要:之前文章詳細(xì)介紹了的使用,不了解的查看進(jìn)階期。不同的引擎有不同的限制,核心限制在,有些引擎會(huì)拋出異常,有些不拋出異常但丟失多余參數(shù)。存儲(chǔ)的對(duì)象能動(dòng)態(tài)增多和減少,并且可以存儲(chǔ)任何值。這邊采用方法來(lái)實(shí)現(xiàn),拼成一個(gè)函數(shù)。 之前文章詳細(xì)介紹了 this 的使用,不了解的查看【進(jìn)階3-1期】。 call() 和 apply() call() 方法調(diào)用一個(gè)函數(shù), 其具有一個(gè)指定的 this 值和分...

    godlong_X 評(píng)論0 收藏0
  • 進(jìn)階1-5】JavaScript深入之4類常見(jiàn)內(nèi)存泄漏如何避免

    摘要:本期推薦文章類內(nèi)存泄漏及如何避免,由于微信不能訪問(wèn)外鏈,點(diǎn)擊閱讀原文就可以啦。四種常見(jiàn)的內(nèi)存泄漏劃重點(diǎn)這是個(gè)考點(diǎn)意外的全局變量未定義的變量會(huì)在全局對(duì)象創(chuàng)建一個(gè)新變量,如下。因?yàn)槔习姹镜氖菬o(wú)法檢測(cè)節(jié)點(diǎn)與代碼之間的循環(huán)引用,會(huì)導(dǎo)致內(nèi)存泄漏。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開(kāi)始前端進(jìn)階的第一期,本周的主題...

    red_bricks 評(píng)論0 收藏0
  • 進(jìn)階4-2】Object.assign 原理實(shí)現(xiàn)

    摘要:木易楊注意原始類型被包裝為對(duì)象木易楊原始類型會(huì)被包裝,和會(huì)被忽略。木易楊原因在于時(shí),其屬性描述符為不可寫(xiě),即。木易楊解決方法也很簡(jiǎn)單,使用我們?cè)谶M(jìn)階期中介紹的就可以了,使用如下。 引言 上篇文章介紹了賦值、淺拷貝和深拷貝,其中介紹了很多賦值和淺拷貝的相關(guān)知識(shí)以及兩者區(qū)別,限于篇幅只介紹了一種常用深拷貝方案。 本篇文章會(huì)先介紹淺拷貝 Object.assign 的實(shí)現(xiàn)原理,然后帶你手動(dòng)實(shí)...

    layman 評(píng)論0 收藏0
  • 進(jìn)階4-3】面試題之如何實(shí)現(xiàn)一個(gè)深拷貝

    摘要:今天這篇文章我們來(lái)看看一道必會(huì)面試題,即如何實(shí)現(xiàn)一個(gè)深拷貝。木易楊注意這里使用上面測(cè)試用例測(cè)試一下一個(gè)簡(jiǎn)單的深拷貝就完成了,但是這個(gè)實(shí)現(xiàn)還存在很多問(wèn)題。 引言 上篇文章詳細(xì)介紹了淺拷貝 Object.assign,并對(duì)其進(jìn)行了模擬實(shí)現(xiàn),在實(shí)現(xiàn)的過(guò)程中,介紹了很多基礎(chǔ)知識(shí)。今天這篇文章我們來(lái)看看一道必會(huì)面試題,即如何實(shí)現(xiàn)一個(gè)深拷貝。本文會(huì)詳細(xì)介紹對(duì)象、數(shù)組、循環(huán)引用、引用丟失、Symbo...

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

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

0條評(píng)論

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