国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript深入之call和apply的模擬實(shí)現(xiàn)

miya / 2563人閱讀

摘要:深入系列第十篇,通過和的模擬實(shí)現(xiàn),帶你揭開和改變的真相一句話介紹方法在使用一個指定的值和若干個指定的參數(shù)值的前提下調(diào)用某個函數(shù)或方法。如果有錯誤或者不嚴(yán)謹(jǐn)?shù)牡胤剑垊?wù)必給予指正,十分感謝。

JavaScript深入系列第十篇,通過call和apply的模擬實(shí)現(xiàn),帶你揭開call和apply改變this的真相

call

一句話介紹 call:

call() 方法在使用一個指定的 this 值和若干個指定的參數(shù)值的前提下調(diào)用某個函數(shù)或方法。

舉個例子:

var foo = {
    value: 1
};

function bar() {
    console.log(this.value);
}

bar.call(foo); // 1

注意兩點(diǎn):

call 改變了 this 的指向,指向到 foo

bar 函數(shù)執(zhí)行了

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

那么我們該怎么模擬實(shí)現(xiàn)這兩個效果呢?

試想當(dāng)調(diào)用 call 的時候,把 foo 對象改造成如下:

var foo = {
    value: 1,
    bar: function() {
        console.log(this.value)
    }
};

foo.bar(); // 1

這個時候 this 就指向了 foo,是不是很簡單呢?

但是這樣卻給 foo 對象本身添加了一個屬性,這可不行吶!

不過也不用擔(dān)心,我們用 delete 再刪除它不就好了~

所以我們模擬的步驟可以分為:

將函數(shù)設(shè)為對象的屬性

執(zhí)行該函數(shù)

刪除該函數(shù)

以上個例子為例,就是:

// 第一步
foo.fn = bar
// 第二步
foo.fn()
// 第三步
delete foo.fn

fn 是對象的屬性名,反正最后也要刪除它,所以起成什么都無所謂。

根據(jù)這個思路,我們可以嘗試著去寫第一版的 call2 函數(shù):

// 第一版
Function.prototype.call2 = function(context) {
    // 首先要獲取調(diào)用call的函數(shù),用this可以獲取
    context.fn = this;
    context.fn();
    delete context.fn;
}

// 測試一下
var foo = {
    value: 1
};

function bar() {
    console.log(this.value);
}

bar.call2(foo); // 1

正好可以打印 1 哎!是不是很開心!(~ ̄▽ ̄)~

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

最一開始也講了,call 函數(shù)還能給定參數(shù)執(zhí)行函數(shù)。舉個例子:

var foo = {
    value: 1
};

function bar(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value);
}

bar.call(foo, "kevin", 18);
// kevin
// 18
// 1

注意:傳入的參數(shù)并不確定,這可咋辦?

不急,我們可以從 Arguments 對象中取值,取出第二個到最后一個參數(shù),然后放到一個數(shù)組里。

比如這樣:

// 以上個例子為例,此時的arguments為:
// arguments = {
//      0: foo,
//      1: "kevin",
//      2: 18,
//      length: 3
// }
// 因?yàn)閍rguments是類數(shù)組對象,所以可以用for循環(huán)
var args = [];
for(var i = 1, len = arguments.length; i < len; i++) {
    args.push("arguments[" + i + "]");
}

// 執(zhí)行后 args為 [foo, "kevin", 18]

不定長的參數(shù)問題解決了,我們接著要把這個參數(shù)數(shù)組放到要執(zhí)行的函數(shù)的參數(shù)里面去。

// 將數(shù)組里的元素作為多個參數(shù)放進(jìn)函數(shù)的形參里
context.fn(args.join(","))
// (O_o)??
// 這個方法肯定是不行的啦!!!

也許有人想到用 ES6 的方法,不過 call 是 ES3 的方法,我們?yōu)榱四M實(shí)現(xiàn)一個 ES3 的方法,要用到ES6的方法,好像……,嗯,也可以啦。但是我們這次用 eval 方法拼成一個函數(shù),類似于這樣:

eval("context.fn(" + args +")")

這里 args 會自動調(diào)用 Array.toString() 這個方法。

所以我們的第二版克服了兩個大問題,代碼如下:

// 第二版
Function.prototype.call2 = function(context) {
    context.fn = this;
    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push("arguments[" + i + "]");
    }
    eval("context.fn(" + args +")");
    delete context.fn;
}

// 測試一下
var foo = {
    value: 1
};

function bar(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value);
}

bar.call2(foo, "kevin", 18); 
// kevin
// 18
// 1

(??????)??

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

模擬代碼已經(jīng)完成 80%,還有兩個小點(diǎn)要注意:

1.this 參數(shù)可以傳 null,當(dāng)為 null 的時候,視為指向 window

舉個例子:

var value = 1;

function bar() {
    console.log(this.value);
}

bar.call(null); // 1

雖然這個例子本身不使用 call,結(jié)果依然一樣。

2.函數(shù)是可以有返回值的!

舉個例子:

var obj = {
    value: 1
}

function bar(name, age) {
    return {
        value: this.value,
        name: name,
        age: age
    }
}

console.log(bar.call(obj, "kevin", 18));
// Object {
//    value: 1,
//    name: "kevin",
//    age: 18
// }

不過都很好解決,讓我們直接看第三版也就是最后一版的代碼:

// 第三版
Function.prototype.call2 = function (context) {
    var context = context || window;
    context.fn = this;

    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push("arguments[" + i + "]");
    }

    var result = eval("context.fn(" + args +")");

    delete context.fn
    return result;
}

// 測試一下
var value = 2;

var obj = {
    value: 1
}

function bar(name, age) {
    console.log(this.value);
    return {
        value: this.value,
        name: name,
        age: age
    }
}

bar.call(null); // 2

console.log(bar.call2(obj, "kevin", 18));
// 1
// Object {
//    value: 1,
//    name: "kevin",
//    age: 18
// }

到此,我們完成了 call 的模擬實(shí)現(xiàn),給自己一個贊 b( ̄▽ ̄)d

apply的模擬實(shí)現(xiàn)

apply 的實(shí)現(xiàn)跟 call 類似,在這里直接給代碼,代碼來自于知乎 @鄭航的實(shí)現(xiàn):

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

    var result;
    if (!arr) {
        result = context.fn();
    }
    else {
        var args = [];
        for (var i = 0, len = arr.length; i < len; i++) {
            args.push("arr[" + i + "]");
        }
        result = eval("context.fn(" + args + ")")
    }

    delete context.fn
    return result;
}
下一篇文章

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

重要參考

知乎問題 不能使用call、apply、bind,如何用 js 實(shí)現(xiàn) call 或者 apply 的功能?

深入系列

JavaScript深入系列目錄地址:https://github.com/mqyqingfeng/Blog。

JavaScript深入系列預(yù)計(jì)寫十五篇左右,旨在幫大家捋順JavaScript底層知識,重點(diǎn)講解如原型、作用域、執(zhí)行上下文、變量對象、this、閉包、按值傳遞、call、apply、bind、new、繼承等難點(diǎn)概念。

如果有錯誤或者不嚴(yán)謹(jǐn)?shù)牡胤剑垊?wù)必給予指正,十分感謝。如果喜歡或者有所啟發(fā),歡迎star,對作者也是一種鼓勵。

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

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/91675.html

相關(guān)文章

  • JavaScript深入bind模擬實(shí)現(xiàn)

    摘要:也就是說當(dāng)返回的函數(shù)作為構(gòu)造函數(shù)的時候,時指定的值會失效,但傳入的參數(shù)依然生效。構(gòu)造函數(shù)效果的優(yōu)化實(shí)現(xiàn)但是在這個寫法中,我們直接將,我們直接修改的時候,也會直接修改函數(shù)的。 JavaScript深入系列第十一篇,通過bind函數(shù)的模擬實(shí)現(xiàn),帶大家真正了解bind的特性 bind 一句話介紹 bind: bind() 方法會創(chuàng)建一個新函數(shù)。當(dāng)這個新函數(shù)被調(diào)用時,bind() 的第一個參數(shù)...

    FingerLiu 評論0 收藏0
  • JavaScript深入new模擬實(shí)現(xiàn)

    摘要:深入系列第十二篇,通過的模擬實(shí)現(xiàn),帶大家揭開使用獲得構(gòu)造函數(shù)實(shí)例的真相一句話介紹運(yùn)算符創(chuàng)建一個用戶定義的對象類型的實(shí)例或具有構(gòu)造函數(shù)的內(nèi)置對象類型之一也許有點(diǎn)難懂,我們在模擬之前,先看看實(shí)現(xiàn)了哪些功能。 JavaScript深入系列第十二篇,通過new的模擬實(shí)現(xiàn),帶大家揭開使用new獲得構(gòu)造函數(shù)實(shí)例的真相 new 一句話介紹 new: new 運(yùn)算符創(chuàng)建一個用戶定義的對象類型的實(shí)例或具...

    tianlai 評論0 收藏0
  • JavaScript 深入 call apply 模擬實(shí)現(xiàn)

    摘要:第一版首先要獲取調(diào)用的函數(shù),用可以獲取的指向?yàn)椋驗(yàn)槭堑膶?shí)例相當(dāng)于把掛載到上,所以可以取到測試一下但是第一版不可以傳遞多個參數(shù)第二版這里會自動調(diào)用這個方法。 // 第一版 Function.prototype.call2 = function(context) { // 首先要獲取調(diào)用call的函數(shù),用this可以獲取 // this的指向?yàn)閎ar,因?yàn)閎ar是Func...

    邱勇 評論0 收藏0
  • JavaScript深入系列15篇正式完結(jié)!

    摘要:寫在前面深入系列共計(jì)篇已經(jīng)正式完結(jié),這是一個旨在幫助大家,其實(shí)也是幫助自己捋順底層知識的系列。深入系列自月日發(fā)布第一篇文章,到月日發(fā)布最后一篇,感謝各位朋友的收藏點(diǎn)贊,鼓勵指正。 寫在前面 JavaScript 深入系列共計(jì) 15 篇已經(jīng)正式完結(jié),這是一個旨在幫助大家,其實(shí)也是幫助自己捋順 JavaScript 底層知識的系列。重點(diǎn)講解了如原型、作用域、執(zhí)行上下文、變量對象、this、...

    fxp 評論0 收藏0
  • 【進(jìn)階3-3期】深度解析 call apply 原理、使用場景及實(shí)現(xiàn)

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

    godlong_X 評論0 收藏0

發(fā)表評論

0條評論

miya

|高級講師

TA的文章

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