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

資訊專欄INFORMATION COLUMN

function作為構(gòu)造函數(shù)和非構(gòu)造函數(shù)調(diào)用的區(qū)別

didikee / 2823人閱讀

摘要:把這個(gè)執(zhí)行上下文壓入調(diào)用棧的頂部,即設(shè)置成運(yùn)行執(zhí)行上下文。函數(shù)作為構(gòu)造函數(shù)調(diào)用沒有繼承關(guān)系有繼承關(guān)系我們把一個(gè)函數(shù)被當(dāng)作構(gòu)造函數(shù),使用操作符調(diào)用時(shí)發(fā)生的主要步驟新建一個(gè)普通對象,把其原型指向構(gòu)造函數(shù)的屬性的值。把當(dāng)前執(zhí)行上下文彈出調(diào)用棧。

var currentTime = Date() 能生成一個(gè)當(dāng)前時(shí)間的日期對象,var currentTime = new Date() 也能生成一個(gè)同樣的對象。如果你看過一些框架,那么你會發(fā)現(xiàn)有的框架生成對象寫法是 new ClassName(),有的框架是 className()。 那么兩種方式有什么區(qū)別呢?

普通函數(shù)/方法調(diào)用

假設(shè)我們定義了一個(gè)函數(shù):

function normalFunc() {
  console.log( this );
}
// 第一種調(diào)法
normalFunc();
// 第二種調(diào)法
normalFunc.call( null );
// 第三種調(diào)法
var obj = {
  method: normalFunc
}
obj.method();

我們把一個(gè)函數(shù)被當(dāng)作一個(gè)普通函數(shù)或者方法調(diào)用歸為一類,其被調(diào)用時(shí)發(fā)生的主要步驟:

生成一個(gè)新的執(zhí)行上下文和對應(yīng)的作用域。(如果對執(zhí)行上下文是什么不了解的話,可以參考我上一篇《什么是作用域和執(zhí)行上下文》)

把當(dāng)前函數(shù)和這個(gè)新的執(zhí)行上下文和作用域關(guān)聯(lián)起來。
2.1. 如果當(dāng)前函數(shù)是箭頭函數(shù),那么把作用域中的 environment record 對象的內(nèi)部屬性 [[thisBindingStatus]] 設(shè)置成 lexical。

把這個(gè)執(zhí)行上下文壓入調(diào)用棧的頂部,即設(shè)置成運(yùn)行執(zhí)行上下文(running execution context)。

接下來處理當(dāng)前函數(shù)的屬性 this 的取值:
4.1. 如果當(dāng)前函數(shù)是箭頭函數(shù),那么這步就不做任何處理(因?yàn)橐呀?jīng)在步驟2.1中做了標(biāo)志位)。

4.2. 如果不是箭頭函數(shù),那么先查看當(dāng)前函數(shù)是否處在嚴(yán)格模式下。

4.2.1. 嚴(yán)格模式:this 的取值取決于如何調(diào)用當(dāng)前函數(shù),譬如上例代碼中第一種調(diào)法,取值為 undefined,第二種調(diào)法取值為 `normalFunc.call(` 的第一個(gè)參數(shù),第三種調(diào)法取值為 obj。
4.2.2. 非嚴(yán)格模式:先按4.2.1的分類獲得 this 的取值,如果是 null 或者 undefined,用全局對象代替 null 或者 undefined。如果 this 的取值是非空值那么把 this 指向這個(gè)非空值(注1)。 

4.3. 把 this 的取值保存在作用域中的 environment record 對象的內(nèi)部屬性 [[thisValue]] 中(步驟4中并非把 this 直接指向這些取值,而是把值保存在作用域特定內(nèi)部屬性中,this 的尋值過程還有額外一步,下面會說明)。

執(zhí)行函數(shù)體。

把當(dāng)前執(zhí)行上下文彈出調(diào)用棧。

如果步驟5有返回,則返回這個(gè)結(jié)果。如果步驟5沒有返回,則返回 undefined。

注1:這里非空值還要判斷是原始類型(primitive value),還是對象類型。如果是原始類型,取值還要再把原始類型包裝成對象才能作為 this 的取值。步驟中避免太繁瑣,省略了細(xì)節(jié)顧特地加上注釋。

函數(shù)中 this 的取值過程(ResolveThisBinding)

結(jié)合上面描述的步驟,我們來看看當(dāng)你在函數(shù)中使用 this 時(shí)(上面的步驟5中 this 已經(jīng)可用),程序時(shí)如何尋找 this 的:

根據(jù)當(dāng)前執(zhí)行上下文查找到對應(yīng)的 enviroment record(execution context -> scope -> environment record)。

判斷當(dāng)前這個(gè) record 是否存儲過[[thisValue]],如果沒有的就沿著作用域鏈向上查找,以全局作用域?yàn)榻K點(diǎn)。

如果找到了,則返回。

如上所述,箭頭函數(shù)本身的作用域并沒有存儲[[thisValue]],所以其內(nèi)部使用 this 會去定義箭頭函數(shù)的地方(函數(shù))去取 this,如果取不到繼續(xù)向上查找。

函數(shù)作為構(gòu)造函數(shù)調(diào)用
// 沒有繼承關(guān)系
function normalFuncAsContructor() {
  // return a new object?
  // return {}
  // or not
  // [return]
}
var o = new normalFuncAsContructor();
// 有繼承關(guān)系
function Parent(){}
function Child(){}
Child.prototype = new Parent();
var c = new Child();

我們把一個(gè)函數(shù)被當(dāng)作構(gòu)造函數(shù),使用 new 操作符調(diào)用時(shí)發(fā)生的主要步驟:

新建一個(gè)普通對象,把其原型 [[Prototype]] 指向構(gòu)造函數(shù)的 prototype 屬性的值。

如普通函數(shù)調(diào)用的步驟1一樣,生成一個(gè)新的執(zhí)行上下文和對應(yīng)的作用域,并把當(dāng)前構(gòu)造函數(shù)和兩者關(guān)聯(lián)起來。

把這個(gè)執(zhí)行上下文壓入調(diào)用棧的頂部。

把第一步生成的對象當(dāng)作 this 的取值保存到作用域中的 environment record 對象的內(nèi)部屬性 [[thisValue]] 中。

執(zhí)行函數(shù)體。

把當(dāng)前執(zhí)行上下文彈出調(diào)用棧。

處理函數(shù)執(zhí)行的結(jié)果,即 new 了之后返回啥:
7.1 如果步驟5返回一個(gè)對象,那么就把這個(gè)對象作為此次 new 操作的返回值。

7.2 如果返回的不是對象,而且這個(gè)函數(shù)不是 generator 函數(shù),那么返回第一步生成的對象(generator 就先不在這里討論了)。

知道了兩者的區(qū)別,我們就能在函數(shù)體里面搞文章了,你可以通過如下代碼檢測用戶怎么調(diào)用你的函數(shù)。如果你知道了用戶怎么調(diào)用,你自然可以根據(jù)你想要的結(jié)果限制用戶的使用方法。

function myFunc() {
  if ( this && myFunc.prototype.isPrototypeOf( this ) ) {
    console.log( "called by new operator" );
  } else {
    console.log( "commonly invoked" );
  }
}
myFunc(); // commonly invoked
new myFunc(); // called by new operator
var obj = {
  method: myFunc
}
obj.method(); // commonly invoked

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

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

相關(guān)文章

  • JavaScript中this

    摘要:作為構(gòu)造函數(shù)何為構(gòu)造函數(shù)所謂構(gòu)造函數(shù)就是用來對象的函數(shù),像等都是全局定義的構(gòu)造函數(shù)。正在跑步正在說話正在跑步正在說話如上,如果函數(shù)作為構(gòu)造函數(shù)用,那么其中的就代表它即將出來的對象。 前言 總括:詳解JavaScript中的this的一篇總結(jié),不懂this這個(gè)難點(diǎn),很多時(shí)候會造成一些困擾,寫出一些bug不知如何收場,所以一起來寫bug吧,不對,一起來寫代碼吧。 原文地址:JavaScr...

    SimpleTriangle 評論0 收藏0
  • 箭頭函數(shù)

    摘要:帶有塊體的箭頭函數(shù)不會自動返回值。使用箭頭函數(shù)創(chuàng)建普通對象時(shí)有一點(diǎn)需要注意。箭頭函數(shù)內(nèi)部的值始終從封閉范圍繼承。對于將使用語法調(diào)用的方法,請使用非箭頭函數(shù)。 箭頭函數(shù)的格式 // ES5 var selected = allJobs.filter(function (job) { return job.isSelected(); }); // ES6 箭頭函數(shù) var selec...

    bingchen 評論0 收藏0
  • 你應(yīng)該要知道JS中this

    摘要:在用創(chuàng)建對象時(shí),指向發(fā)生改變是在第二步創(chuàng)建一個(gè)對象實(shí)例將構(gòu)造函數(shù)中的指向這個(gè)對象執(zhí)行構(gòu)造函數(shù)中的代碼返回這個(gè)新創(chuàng)建的對象箭頭函數(shù)中的箭頭函數(shù)內(nèi)部是不會綁定的,它會捕獲外層作用域中的,作為自己的值。參考你不知道的上卷 前言 this 是 JavaScript 中不可不談的一個(gè)知識點(diǎn),它非常重要但又不容易理解。因?yàn)?JavaScript 中的 this 不同于其他語言。不同場景下的 thi...

    edgardeng 評論0 收藏0
  • js函數(shù)this理解?手寫apply、call、bind就夠了

    摘要:一是什么函數(shù)的內(nèi)部屬性,引用的是函數(shù)據(jù)以執(zhí)行的環(huán)境對象。函數(shù)做為節(jié)點(diǎn)事件調(diào)用時(shí)指向節(jié)點(diǎn)本身做為構(gòu)造函數(shù)實(shí)力化方法時(shí)指向?qū)嵗龑ο蠹^函數(shù)里的普通函數(shù),由于閉包函數(shù)是執(zhí)行的,所以指向箭頭函數(shù)的指向函數(shù)創(chuàng)建時(shí)的作用域。 一、this是什么? 函數(shù)的內(nèi)部屬性,this引用的是函數(shù)據(jù)以執(zhí)行的環(huán)境對象。也就是說函數(shù)的this會指向調(diào)用函數(shù)的執(zhí)行環(huán)境。 function a(){ retur...

    Cciradih 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<