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

資訊專欄INFORMATION COLUMN

【2】this

Alex / 2695人閱讀

摘要:否則如果是或,則設(shè)綁定為全局對(duì)象。令為解釋執(zhí)行的結(jié)果。返回一個(gè)值類型的引用,其基值為且其引用名為,嚴(yán)格模式標(biāo)記為。進(jìn)入函數(shù)代碼,為,非嚴(yán)格模式下將賦值為全局對(duì)象。內(nèi)置函數(shù)如何使用的內(nèi)置函數(shù)修改是通過給的內(nèi)置方法傳遞來實(shí)現(xiàn)的。

this

說到this,需要明確三方面內(nèi)容:

this何時(shí)被賦值

this被賦了什么值

內(nèi)置函數(shù)如何使用this的

this何時(shí)被賦值 進(jìn)入函數(shù)代碼

當(dāng)控制流根據(jù)一個(gè)函數(shù)對(duì)象 F、調(diào)用者提供的 thisArg 以及調(diào)用者提供的 argumentList,進(jìn)入函數(shù)代碼的執(zhí)行環(huán)境時(shí),執(zhí)行以下步驟:

如果函數(shù)代碼是嚴(yán)格模式下的代碼,設(shè) this 綁定 為 thisArg。

否則如果 thisArg 是 null 或 undefined ,則設(shè) this 綁定為全局對(duì)象。

……

以上信息來源:進(jìn)入函數(shù)代碼

從上訴信息中可以知道

this 與調(diào)用者提供的 thisArg 密切相關(guān)

this 在嚴(yán)格模式下為 thisArg

this 在非嚴(yán)格模式下為 thisArg 或 全局對(duì)象

那么 thisArg 又是怎么來的呢?下面來看下函數(shù)調(diào)用過程:

函數(shù)調(diào)用

令 ref 為解釋執(zhí)行 MemberExpression 的結(jié)果。

令 func 為 GetValue(ref)。

令 argList 為解釋執(zhí)行 Arguments 的結(jié)果,產(chǎn)生參數(shù)值們的內(nèi)部列表(參見 11.2.4)。

如果 Type(func) 不是 Object,拋出一個(gè) TypeError 異常。

如果 IsCallable(func) 為 false,拋出一個(gè) TypeError 異常。

如果 Type(ref) 為 Reference,那么

如果 IsPropertyReference(ref) 為 true,

那么令 thisValue 為 GetBase(ref)。

否則,ref 的基值是一個(gè)環(huán)境記錄項(xiàng)。

令 thisValue 為調(diào)用 GetBase(ref) 的 ImplicitThisValue 具體方法的結(jié)果。

否則,Type(ref) 不是 Reference。

令 thisValue 為 undefined。

返回調(diào)用 func 的 [[Call]] 內(nèi)置方法的結(jié)果,傳入 thisValue 作為 this 值和列表 argList 作為參數(shù)列表。

以上信息來源:函數(shù)調(diào)用

從上訴信息中可以知道

thisArg 即 thisValue

thisValue 與 ref 的類型密切相關(guān)

如果 ref 的類型是 Reference(引用規(guī)范類型)

如果 ref 是屬性引用,通過 GetBase(ref)(返回引用值ref的基值部分) 獲取 thisValue

否則,通過 ImplicitThisValue 方法獲取 thisValue

否則,thisValue 為 undefined

那么,了解到這里可能有許多新的疑問,比如:

Reference 是怎樣的類型

ref 是怎么來的

ref 什么時(shí)候是 Reference,什么時(shí)候不是。

GetBase(ref) 和 ImplicitThisValue 是如何產(chǎn)生結(jié)果的

Reference 是怎樣的類型

首先先解釋下 Reference。

其實(shí)ES中的類型分為ECMAScript語言類型和規(guī)范類型

ECMAScript語言類型對(duì)應(yīng)的是程序員使用 ECMAScript 語言直接操作的值,如 Undefined、Null、Boolean、String、Number、Object等。
規(guī)范類型可用來描述 ECMAScript 表達(dá)式運(yùn)算的中間結(jié)果,但這樣的值不能儲(chǔ)存為對(duì)象的屬性或 ECMAScript 語言的變量值。引用尤雨溪的解釋:

這里的 Reference 是一個(gè) Specification Type,也就是 “只存在于規(guī)范里的抽象類型”。它們是為了更好地描述語言的底層行為邏輯才存在的,但并不存在于實(shí)際的 js 代碼中。
ref 是怎么來的

從上訴函數(shù)調(diào)用中可以知道,ref 是解釋執(zhí)行 MemberExpression 的結(jié)果。
下面詳細(xì)看下 MemberExpression 的解析過程:

產(chǎn)生式 CallExpression : MemberExpression Arguments 按照下面的過程執(zhí)行 :

令 baseReference 為解釋執(zhí)行 MemberExpression 的結(jié)果。

令 baseValue 為 GetValue(baseReference)。

令 propertyNameReference 為解釋執(zhí)行 Expression 的結(jié)果。

令 propertyNameValue 為 GetValue(propertyNameReference)。

調(diào)用 CheckObjectCoercible(baseValue)。

令 propertyNameString 為 ToString(propertyNameValue)。

如果正在執(zhí)行中的語法產(chǎn)生式包含在嚴(yán)格模式代碼當(dāng)中,令 strict 為 true,否則令 strict 為 false。

返回一個(gè)值類型的引用,其基值為 baseValue 且其引用名為 propertyNameString,嚴(yán)格模式標(biāo)記為 strict。

從上訴信息中分析可以知道

解釋執(zhí)行 MemberExpression 的結(jié)果是一個(gè)引用規(guī)范類型(Reference)

這個(gè)引用規(guī)范類型包含三部分信息:

baseValue

propertyNameString

strict

thisValue 的值取決于 baseValue

baseValue 是調(diào)用 GetValue 獲得的。

GetValue 得到的基值是 undefined、Object、Boolean、String、Number、環(huán)境記錄項(xiàng)中的任意一個(gè)(詳見:引用規(guī)范類型),而不是引用規(guī)范類型。

GetValue 詳細(xì)過程見:GetValue
ref 什么時(shí)候是 Reference,什么時(shí)候不是 Reference

一般來說,ref 是MemberExpression解析的結(jié)果,都將是 Reference。
但是,如果 MemberExpression 是其函數(shù)表達(dá)式的一部分,則可能將改變最終解析結(jié)果的類型。
而改變解析結(jié)果類型的主要原因取決于是否調(diào)用了 GetValue 方法,如果調(diào)用了 GetValue ,函數(shù)中間值 ref 將是 Object 類型。

那么哪些表達(dá)式不使用 GetValue 呢?

標(biāo)識(shí)符引用 : 標(biāo)識(shí)符執(zhí)行的結(jié)果總是一個(gè) Reference 類型的值。

群組表達(dá)式:本算法不在執(zhí)行 Expression 后使用 GetValue。這主要的目的是讓 delete 與 typeof 運(yùn)算符可以作用在被括號(hào)括起來的表達(dá)式。

成員表達(dá)式

調(diào)用表達(dá)式

更多表達(dá)式詳見:表達(dá)式
GetBase(ref) 和 ImplicitThisValue 是如何產(chǎn)生結(jié)果的

GetBase:返回引用值ref的基值部分

ImplicitThisValue : 聲明式環(huán)境記錄項(xiàng)永遠(yuǎn)將 undefined 作為其 ImplicitThisValue 返回。

this被賦了什么值

其實(shí)在 this何時(shí)被賦值 部分已經(jīng)介紹了 this被賦了什么值。下面總結(jié)三種賦值過程:

第一種this賦值過程:
var v = 1; 
var obj = {
    v: 2,
    fn: function(){
        console.log(this.v);
    }
}
obj.fn(); // 2
(obj.fn)(); // 2

調(diào)用表達(dá)式解析 obj.fn ,返回引用規(guī)范類型,baseValue 為 obj。

函數(shù)調(diào)用,由于 1 過程返回的為引用規(guī)范類型,且為屬性引用,調(diào)用 GetBase 將 baseValue (obj) 作為返回值,返回給 thisValue。

進(jìn)入函數(shù)代碼,thisArg 為 obj,將其賦值給 this。

如果對(duì)步驟1中,baseValue 為 obj 有疑問,詳見屬性訪問, 產(chǎn)生式 MemberExpression : MemberExpression [ Expression ] 執(zhí)行過程。
相當(dāng)于有兩個(gè)過程:

解析obj,baseValue 為聲明式環(huán)境記錄項(xiàng)。

解析obj.fn,baseValue 為 obj。

第二種this賦值過程:
function foo(){
    console.log(this);
}
foo(); // Window

調(diào)用表達(dá)式解析 foo, 返回引用規(guī)范類型,baseValue 為聲明式環(huán)境記錄項(xiàng)(函數(shù)聲明時(shí)綁定)。

函數(shù)調(diào)用,由于 1 過程返回的為引用規(guī)范類型,且不為屬性引用,調(diào)用 ImplicitThisValue 方法,返回 undefined 。

進(jìn)入函數(shù)代碼,thisArg 為 undefined,非嚴(yán)格模式下將 this 賦值為全局對(duì)象。

第三種this賦值過程:
var v = 1; 
var obj = {
    v: 2,
    fn: function(){
        console.log(this.v);
    }
}
var fn2 = obj.fn;
fn2(); // 1
(obj.fn, obj.fn)(); // 1

調(diào)用表達(dá)式解析 fn2,(obj.fn, obj.fn) ,由于賦值表達(dá)式、逗號(hào)表達(dá)式都使用了 GetValue 方法,返回函數(shù)(Object 類型)。

函數(shù)調(diào)用,由于 1 過程返回的不是引用規(guī)范類型,所以 thisValue 為 undefined`。

進(jìn)入函數(shù)代碼,thisArg 為 undefined,非嚴(yán)格模式下將 this 賦值為全局對(duì)象。

內(nèi)置函數(shù)如何使用this的

內(nèi)置函數(shù)修改 this 是通過給 func 的 [[Call]] 內(nèi)置方法傳遞 thisArg 來實(shí)現(xiàn)的。

內(nèi)置方法

Function.prototype.apply (thisArg, argArray)

Function.prototype.call (thisArg [ , arg1 [ , arg2, … ] ] )

Function.prototype.bind (thisArg [, arg1 [, arg2, …] ] )

Array.prototype.every ( callbackfn [ , thisArg ] )

Array.prototype.some ( callbackfn [ , thisArg ] )

Array.prototype.forEach ( callbackfn [ , thisArg ] )

Array.prototype.map ( callbackfn [ , thisArg ] )

Array.prototype.filter ( callbackfn [ , thisArg ] )

new 運(yùn)算符 使用內(nèi)置方法 [[Construct]] 實(shí)現(xiàn)this指定

內(nèi)置方法模擬實(shí)現(xiàn)

使用成員表達(dá)式模擬內(nèi)置方法[[Call]]的效果:

apply
Function.prototype.apply_ = function (context, arr) { 
    var context = Object(context) || window;
    var result;

    // 臨時(shí)記錄需要調(diào)用的function 
    context.fn = this;
      
    if (!arr) {
        result = context.fn();
    }
    else {
        var args = [];
        for (var i = 0, len = arr.length; i < len; i++) {
            args.push("arr[" + i + "]");
        }
        // 使用成員表達(dá)式指定context.fn執(zhí)行時(shí)this為context 
        result = eval("context.fn(" + args + ")")
    }

    delete context.fn
    return result;
}
call
Function.prototype.call_ = function (context) {
    var context = context || window;
    context.fn = this;

    var args = [];
    // 獲取參數(shù)列表 
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push("arguments[" + i + "]");
    } 
    // 使用成員表達(dá)式指定context.fn執(zhí)行時(shí)this為context  
    var result = eval("context.fn(" + args +")");

    delete context.fn
    return result;
}  
bind
Function.prototype.bind_  = function (context) {
    // 記錄bind的函數(shù) 
    var self = this;
    var args = [];
    // 獲取綁定的參數(shù)列表 
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push("arguments[" + i + "]");
    } 

    // 創(chuàng)建新函數(shù) 
    var fbound = function () {
        // 獲取未綁定的參數(shù)列表 
        var bindArgs = Array.prototype.slice.call(arguments);
        // fbound被當(dāng)做構(gòu)造函數(shù)使用,this指向?qū)嵗?。否則,指向 context
        self.apply(this instanceof self ? this : context, args.concat(bindArgs));
    } 
    // 維護(hù)原型關(guān)系   
    fbound.prototype = self.prototype || new Function().prototype ;
    return fbound;
}
參考文檔

【1】冴羽的深入理解系列

【2】ES5 Wiki

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

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

相關(guān)文章

  • canvas之轉(zhuǎn)盤抽獎(jiǎng)

    摘要:最近工作中重構(gòu)了抽獎(jiǎng)轉(zhuǎn)盤,給大家提供一個(gè)開發(fā)轉(zhuǎn)盤抽獎(jiǎng)的思路需求轉(zhuǎn)盤根據(jù)獎(jiǎng)品數(shù)量不同而有變化目錄結(jié)構(gòu)由于業(yè)務(wù)需要所以開發(fā)了兩個(gè)版本抽獎(jiǎng),和,不過部分只能替換圖片,沒有功能邏輯。 最近工作中重構(gòu)了抽獎(jiǎng)轉(zhuǎn)盤,給大家提供一個(gè)開發(fā)轉(zhuǎn)盤抽獎(jiǎng)的思路 需求 1、轉(zhuǎn)盤根據(jù)獎(jiǎng)品數(shù)量不同而有變化 2、canvas 目錄結(jié)構(gòu) showImg(https://segmentfault.com/img/bVbwL...

    _ang 評(píng)論0 收藏0
  • 構(gòu)建二叉樹進(jìn)行數(shù)值數(shù)組的去重及優(yōu)化

    摘要:構(gòu)建二叉樹進(jìn)行數(shù)值數(shù)組的去重及優(yōu)化常見兩層循環(huán)實(shí)現(xiàn)數(shù)組去重構(gòu)建二叉樹實(shí)現(xiàn)去重僅適用于數(shù)值類型的數(shù)組將先前遍歷過的元素,構(gòu)建成二叉樹,樹中每個(gè)結(jié)點(diǎn)都滿足左子結(jié)點(diǎn)的值當(dāng)前結(jié)點(diǎn)的值右子結(jié)點(diǎn)的值這樣優(yōu)化了判斷元素是否之前出現(xiàn)過的過程若元素比當(dāng)前結(jié)點(diǎn) 構(gòu)建二叉樹進(jìn)行數(shù)值數(shù)組的去重及優(yōu)化 常見兩層循環(huán)實(shí)現(xiàn)數(shù)組去重 let arr = [11, 12, 13, 9, 8, 7, 0, 1, 2, 2...

    sarva 評(píng)論0 收藏0
  • ionic 2+ 手勢解鎖界面

    摘要:手勢解鎖界面一些對(duì)安全要求比較高的少不了鎖屏頁面,而手勢解鎖對(duì)于用戶來說使用方便,對(duì)于程序員來說小有挑戰(zhàn),怎么有棄之不用的道理。 ionic 2+ 手勢解鎖界面 一些對(duì)安全要求比較高的app少不了鎖屏頁面,而手勢解鎖對(duì)于用戶來說使用方便,對(duì)于程序員來說小有挑戰(zhàn),怎么有棄之不用的道理。 效果圖 效果圖處理短,方便大家閱讀showImg(https://segmentfault.co...

    Hancock_Xu 評(píng)論0 收藏0
  • JS+canvas實(shí)現(xiàn)五子棋人機(jī)大戰(zhàn)

    摘要:五子棋人機(jī)大戰(zhàn)創(chuàng)建實(shí)例是否結(jié)束我電腦所有棋子已經(jīng)落下的棋子贏法總數(shù)所有贏法統(tǒng)計(jì)我的贏法統(tǒng)計(jì)電腦贏法統(tǒng)計(jì)初始化初始化生成棋盤棋盤初始化鼠標(biāo)移動(dòng)聚焦功能實(shí)現(xiàn)算法初始化落子功能實(shí)現(xiàn)生成棋盤初始化生成不是的倍數(shù)棋盤列初始化棋盤棋盤初始化畫棋盤畫 JS+canvas五子棋人機(jī)大戰(zhàn) 1. 創(chuàng)建實(shí)例 function Gobang () { this.over = false; // 是否結(jié)...

    sutaking 評(píng)論0 收藏0
  • js數(shù)據(jù)結(jié)構(gòu)-二叉樹(二叉堆)

    摘要:二叉樹二叉樹是一種樹形結(jié)構(gòu),它的特點(diǎn)是每個(gè)節(jié)點(diǎn)最多只有兩個(gè)分支節(jié)點(diǎn),一棵二叉樹通常由根節(jié)點(diǎn),分支節(jié)點(diǎn),葉子節(jié)點(diǎn)組成。 二叉樹 二叉樹(Binary Tree)是一種樹形結(jié)構(gòu),它的特點(diǎn)是每個(gè)節(jié)點(diǎn)最多只有兩個(gè)分支節(jié)點(diǎn),一棵二叉樹通常由根節(jié)點(diǎn),分支節(jié)點(diǎn),葉子節(jié)點(diǎn)組成。而每個(gè)分支節(jié)點(diǎn)也常常被稱作為一棵子樹。 showImg(https://segmentfault.com/img/bVbmEd...

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

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

0條評(píng)論

閱讀需要支付1元查看
<