成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

JavaScript進(jìn)階之模擬new Object過(guò)程

chengtao1633 / 779人閱讀

摘要:后續(xù)我將推出進(jìn)階系列,一方面是一個(gè)監(jiān)督自己學(xué)習(xí)的一個(gè)過(guò)程,另一方面也會(huì)給看到的童鞋一些啟發(fā)。第二步鏈接到原型中現(xiàn)在把構(gòu)造函數(shù)和參數(shù)都打印出來(lái)了。

原文:https://zhehuaxuan.github.io/...  
作者:zhehuaxuan
寫(xiě)在前面的話

前端的入門(mén)相對(duì)簡(jiǎn)單,相對(duì)于其他方向天花板可能會(huì)相對(duì)較低。但是在市場(chǎng)上一個(gè)優(yōu)秀的前端依舊是很搶手的。能夠站在金字塔上的人往往寥寥無(wú)幾。

目前前端也已經(jīng)一年半了,在公司的知識(shí)棧相對(duì)落后,就業(yè)形勢(shì)不容樂(lè)觀,所以有必要自己琢磨,往中高級(jí)前端進(jìn)階。后續(xù)我將推出《JavaScript進(jìn)階系列》,一方面是一個(gè)監(jiān)督自己學(xué)習(xí)的一個(gè)過(guò)程,另一方面也會(huì)給看到的童鞋一些啟發(fā)。

JavaScript新建對(duì)象的過(guò)程

在ES5中定義一個(gè)函數(shù)來(lái)創(chuàng)建對(duì)象,如下:

function Person(name){
    this.name = name;
}
Person.prototype.getName = function(){
    return name;
}
var person = new Person("xuan");
console.log(person.name);//輸出:xuan
console.log(person.getName());//輸出:xuan

我們看到當(dāng)我們新建一個(gè)對(duì)象,我們就可以訪問(wèn)構(gòu)造器中的指向this的屬性,還可以訪問(wèn)原型中的屬性。我們不妨把JavaScript調(diào)用new的過(guò)程主要由下面四步組成:

新生成一個(gè)空對(duì)象

將空對(duì)象鏈接到原型中

綁定this

返回新對(duì)象

下面跟著我按照這個(gè)思路來(lái)創(chuàng)建對(duì)象:

function create(){
    //Todo
}
person = create(Person,"xuan");//create(ObjectName,...arguments)

我們使用如上所示的函數(shù)來(lái)模擬new關(guān)鍵字。

首先第一步新建一個(gè)對(duì)象:

function create(){
    var obj = new Object();
    return obj;
}
person = create(Person,"xuan");

現(xiàn)在已經(jīng)創(chuàng)建并返回一個(gè)對(duì)象,當(dāng)然現(xiàn)在打印出來(lái)肯定是一個(gè)普通的對(duì)象,畢竟流程還沒(méi)有走完,我們接著往下看。

第二步鏈接到原型中:

function create(){
    var obj = new Object();
    var constructor = [].shift.call(arguments);
    console.log(constructor);
    console.log(arguments);
    obj.__proto__ = constructor.prototype;
    return obj;
}

person = create(Person,"xuan");

現(xiàn)在把構(gòu)造函數(shù)和參數(shù)都打印出來(lái)了。沒(méi)問(wèn)題!

第三步綁定this,如下:

function create() {
  let obj = new Object();
  let constructor = [].shift.call(arguments)
  obj.__proto__ = constructor.prototype
  constructor.apply(obj, arguments);
  console.log(obj);  
  return obj;
}
person = create(Person,"xuan");

打印結(jié)果實(shí)現(xiàn)new對(duì)象的效果。

現(xiàn)在改一下構(gòu)造函數(shù)代碼:

function Person(name){
    this.name = name;
    return {
        name:"abc"
    }
}
var person = new Person("xuan");
console.log(person);
console.log(Object.prototype.toString.call(person));

效果如下:


我們執(zhí)行一下我們構(gòu)建的函數(shù)效果如下:

發(fā)現(xiàn)不一致,所以我們要處理第三步綁定this中apply函數(shù)的返回值:

function create() {
  let obj = new Object();
  let constructor = [].shift.call(arguments)
  obj.__proto__ = constructor.prototype
  //constructor.apply(obj, arguments);
  let res = constructor.apply(obj, arguments);
  if(res){
     return res;
  }else{
     return obj;
  }
}
person = create(Person,"xuan");

效果如下:


完美!

現(xiàn)在我們思考一下這里的res返回值有三種情況:undefined,基本類(lèi)型,對(duì)象。

如果res是undefined時(shí),返回obj;

如果res是基本類(lèi)型我們也返回obj;

如果res是對(duì)象我們返回res對(duì)象;

綜合一下:

如果返回的res對(duì)象是Object類(lèi)型那么返回res,否則返回obj。當(dāng)然其他的判斷條件也是可以的。最后代碼優(yōu)化如下:

function create() {
  let obj = new Object();
  let constructor = [].shift.call(arguments)
  obj.__proto__ = constructor.prototype
  //constructor.apply(obj, arguments);
  let res = constructor.apply(obj, arguments);
  return res instanceof Object?res:obj;
}
person = create(Person,"xuan");
幾個(gè)問(wèn)題

現(xiàn)在的代碼已經(jīng)完美了么?我們先來(lái)提幾個(gè)問(wèn)題。

new Object()創(chuàng)建的對(duì)象純凈么?

為啥使用[].shift.call()來(lái)進(jìn)行參數(shù)分割?arguments是一個(gè)數(shù)組么?

new Object()創(chuàng)建的對(duì)象純凈么?

首先什么是純凈?我們定義一個(gè)對(duì)象的__proto__屬性為空的對(duì)象是一個(gè)純凈的對(duì)象。

在第二步的時(shí)候中已經(jīng)改變的obj的原型鏈,所以無(wú)論它前面的原型鏈?zhǔn)钦拥亩紵o(wú)所謂,但是為了保證對(duì)象的純凈性,我們有必要引出Object.create(),該方法創(chuàng)建一個(gè)新對(duì)象,使用現(xiàn)有的對(duì)象來(lái)提供新創(chuàng)建的對(duì)象的__proto__。我們來(lái)看一下:

var person1 = Object.create({});

打印如下:

我們看到person1的__proto__指向了{}對(duì)象,所以我們?cè)谏鲜龃a中直接修改如下:

function create() {
  let constructor = [].shift.call(arguments);
  let obj = Object.create(constructor.prototype);
  let res = constructor.apply(obj, arguments);
  return res instanceof Object?res:obj;
}
person = create(Person,"xuan");
為啥使用[].shift.call()來(lái)進(jìn)行參數(shù)分割?arguments是一個(gè)數(shù)組么?

首先我們知道arguments是函數(shù)傳入的參數(shù),那么這個(gè)參數(shù)是數(shù)組么?我們打印一下便知:

console.log(arguments);
console.log(Object.prototype.toString.call(arguments));
console.log(arguments instanceof Array);

結(jié)果如下

不是數(shù)組。我們展開(kāi)發(fā)現(xiàn)他跟數(shù)組很像,查一下資料發(fā)現(xiàn)這個(gè)對(duì)象是類(lèi)數(shù)組。里面沒(méi)有shift函數(shù),直接調(diào)用shift會(huì)報(bào)錯(cuò)。我們使用使用Array.from(arguments)將arguments轉(zhuǎn)成數(shù)組,然后在調(diào)用shift函數(shù)也是一種思路。但是在這里我們使用apply最適合。所以下述代碼是模擬new Object()的最優(yōu)代碼:

function create() {
  let constructor = [].shift.call(arguments);
  let obj = Object.create(constructor.prototype);
  let res = constructor.apply(obj, arguments);
  return res instanceof Object?res:obj;
}
person = create(Person,"xuan");

還有更優(yōu)的實(shí)現(xiàn)方法,請(qǐng)大佬們不吝拍磚!

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/102538.html

相關(guān)文章

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

    摘要:使用指定的參數(shù)調(diào)用構(gòu)造函數(shù),并將綁定到新創(chuàng)建的對(duì)象。由構(gòu)造函數(shù)返回的對(duì)象就是表達(dá)式的結(jié)果。情況返回以外的基本類(lèi)型實(shí)例中只能訪問(wèn)到構(gòu)造函數(shù)中的屬性,和情況完全相反,結(jié)果相當(dāng)于沒(méi)有返回值。 定義 new 運(yùn)算符創(chuàng)建一個(gè)用戶定義的對(duì)象類(lèi)型的實(shí)例或具有構(gòu)造函數(shù)的內(nèi)置對(duì)象的實(shí)例。 ——(來(lái)自于MDN) 舉個(gè)栗子 function Car(color) { this.color = co...

    Baaaan 評(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)階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)階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
  • 進(jìn)階 6-2 期】深入高階函數(shù)應(yīng)用柯里化

    摘要:引言上一節(jié)介紹了高階函數(shù)的定義,并結(jié)合實(shí)例說(shuō)明了使用高階函數(shù)和不使用高階函數(shù)的情況。我們期望函數(shù)輸出,但是實(shí)際上調(diào)用柯里化函數(shù)時(shí),所以調(diào)用時(shí)就已經(jīng)執(zhí)行并輸出了,而不是理想中的返回閉包函數(shù),所以后續(xù)調(diào)用將會(huì)報(bào)錯(cuò)。引言 上一節(jié)介紹了高階函數(shù)的定義,并結(jié)合實(shí)例說(shuō)明了使用高階函數(shù)和不使用高階函數(shù)的情況。后面幾部分將結(jié)合實(shí)際應(yīng)用場(chǎng)景介紹高階函數(shù)的應(yīng)用,本節(jié)先來(lái)聊聊函數(shù)柯里化,通過(guò)介紹其定義、比較常見(jiàn)的...

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

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

0條評(píng)論

閱讀需要支付1元查看
<