JS修改this指向:call、apply和bind函數(shù)

call 函數(shù)

語(yǔ)法

obj.call(thisObj,arg[,arg2[,arg3[,...agr]]]);

簡(jiǎn)介

修改obj的this指向?yàn)閠hisObj,后面的參數(shù)會(huì)當(dāng)成obj的參數(shù)安裝順序傳遞進(jìn)去。

我們先來(lái)看一下下面這段代碼會(huì)輸出什么:

function say(arg1, arg2) {

? console.log(this.name, arg1, arg2);

}

const obj = {

? name: "tom",

? say: function () {

? ? console.log(this.name);

? }

};

say();

輸出結(jié)果:

我們發(fā)現(xiàn)報(bào)錯(cuò)了,程序并沒(méi)有找到name;

現(xiàn)在我們來(lái)改動(dòng)一下,使用call函數(shù)來(lái)改變this的指向,看看會(huì)發(fā)生什么:

say.call(obj, "1", "2");

發(fā)現(xiàn)輸出的結(jié)果變成了:

call把say函數(shù)的this變?yōu)榱薿bj。

下面我們來(lái)實(shí)現(xiàn)一個(gè)call函數(shù)

Function.prototype._call = function (context) {

? // 判斷是否是一個(gè)函數(shù)

? // this指的是調(diào)用的函數(shù)

? if (typeof this !== "function") {

????????throw new TypeError("Error");

? }

? context = context || window;

? context.fn = this;

? const args = [...arguments].slice(1);

? const result = context.fn(...args);

? delete context.fn;

? return result;

};

驗(yàn)證一下:

say._call(obj, "1", "2");

發(fā)現(xiàn)輸出結(jié)果與期望的相同


apply函數(shù)

語(yǔ)法

obj.call(thisObj[,argArray]);

簡(jiǎn)介

apply與call函數(shù)的用法相同,只是參數(shù)的傳遞變成了數(shù)組形式。

say.apply(obj, ["1", "2"]);

輸出的結(jié)果與調(diào)用call相同:

與call的實(shí)現(xiàn)相比,只需要修改一下參數(shù)的傳遞:

Function.prototype._apply = function (context, args) {

? // 判斷是否是一個(gè)函數(shù)

? // this指的是調(diào)用的函數(shù)

? if (typeof this !== "function") {

? ? throw new TypeError("Error");

? }

? context = context || window;

? context.fn = this;

? let result = null;

? if (args) {

? ? result = context.fn(...args);

? } else {

? ? result = context.fn();

? }

? delete context.fn;

? return result;

};


bind 函數(shù)

語(yǔ)法

obj.bind(thisObj,arg[,arg2[,arg3[,...agr]]]);

簡(jiǎn)介

bind函數(shù)會(huì)返回一個(gè)新函數(shù),但是不會(huì)像call和apply一樣立即執(zhí)行函數(shù),bind后面的參數(shù)會(huì)當(dāng)成obj的參數(shù)安裝順序傳遞進(jìn)去。

我們先來(lái)看兩段代碼

const s = say.bind(obj, "1", "2");

s()

const s = say.bind(obj);

s("1", "2");

發(fā)現(xiàn)這兩段代碼輸出的結(jié)果是一樣的。

我們來(lái)簡(jiǎn)單實(shí)現(xiàn)一下bind函數(shù):

Function.prototype._bind = function (context) {

? // 判斷是否是一個(gè)函數(shù)

? if (typeof this !== "function") {

? ? throw new TypeError("Error");

? }

? const args = [...arguments].slice(1);

? const fn = this;

? const F = function () {},

? ? fBound = function () {

? ? ? return fn.apply(

? ? ? ? this instanceof F && context ? this : context || window,

? ? ? ? args.concat(...arguments)

? ? ? );

? ? };

? F.prototype = this.prototype;

? fBound.prototype = new F();

? return fBound;

};

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容