JavaScript手寫call,apply,bind方法
前言
改變this指向在書寫業(yè)務(wù)的時候經(jīng)常遇到,我們經(jīng)常采用以下方法進行改寫
- 使用作用聲明變量存儲this
- 使用jJavaScript的原生方法call,apply,以及bind進行改寫
第一種方法就不說了,就是一個變量存儲的問題,主要說第二種如何實現(xiàn)的
call,bind,apply方法都是JavaScript原生的方法,掛載在Function原型上,使得所有函數(shù)都可以調(diào)用,今天我們來實現(xiàn)一下call,apply,bind吧
改寫this實現(xiàn)思路
我們聲明一個函數(shù),函數(shù)接受倆個參數(shù),第一個參數(shù)是接受改變的this指向,第二個是剩余參數(shù),用于執(zhí)行改變方法后傳遞的使用參數(shù),在函數(shù)中里面聲明一個變量用于存儲傳遞過來的this,遵循this指向的準則,this是在執(zhí)行的時候生成的,函數(shù)的準則是誰調(diào)用它就指向誰,傳遞過來的this是一個對象,然后在傳遞過來的this上面聲明一個方法,聲明的方法就是當前函數(shù),該方法由傳遞過來的this進行調(diào)用執(zhí)行,這樣就改變了this指向問題,在把傳遞過來的參數(shù)除第一個外全部傳遞給聲明的方法,我們來實現(xiàn)一下
前期準備
這些數(shù)據(jù)用于配合手寫的方法,由于call,bind,apply他們都是需要把他們掛載到函數(shù)原型上,函數(shù)才能調(diào)用的到,我們這里也把他掛載到原型上
var name = '前端';
var age = "7";
let obj = {
name: '若水',
age: '20'
};
function fnLog(arg) {
let str = `我叫${this.name}今年${this.age}歲了`;
console.log(str, '傳遞過來的', arg);
}手寫的call,bind,apply方法第一個參數(shù)都是改變的this指向,第二個參數(shù)是傳遞的參數(shù)
手寫call方法
call方法是改變this后立即執(zhí)行
Function.prototype.myCall = function(content, ...arg) {
// 創(chuàng)建一個變量接受改變的this,如果改變的this為空則采用window為默認this
let newThis = content || window;
/**newThis是一個對象,它是傳遞過來的this,在newThis上新增一個方法,這個方法就是
當前函數(shù) ,this就是指向的myCall,調(diào)用這個方法就可以改變this指向,因為函數(shù)是誰調(diào)用
它this就指向誰
**/
newThis.fn = this;
/**執(zhí)行改變this方法,接受返回值,這里容易被誤導(dǎo),這里是把myCall傳遞過來的參數(shù)傳遞
給了改變this的函數(shù),由于不確定傳遞多少使用了剩余參數(shù),這里也是 **/
let result = newThis.fn(...arg);
//刪除傳遞過來this上聲明的方法,防止出現(xiàn)問題
delete newThis.fn;
// 將執(zhí)行結(jié)果返回
return result;
};
//執(zhí)行手寫的call方法
fnLog.myCall(obj, 'myCall');手寫apply方法
apply傳遞的參數(shù)只能傳遞數(shù)組
//如果arg沒有傳遞參數(shù),默認為空數(shù)組
Function.prototype.myApply = function(content, arg = []) {
// 判斷傳遞參數(shù)是否為數(shù)組,如果不為數(shù)組則拋出錯誤,為數(shù)組則繼續(xù)執(zhí)行
if (!Array.isArray(arg)) {
throw '傳遞參數(shù)必須為數(shù)組';
}
// 創(chuàng)建一個變量接受改變的this,如果改變的this為空則采用window為默認this
let newThis = content || window;
// 給當前傳遞過來的this,添加一個方法,遵循this準則,誰調(diào)用就指向誰的原則
newThis.fn = this;
// 同mycall相同
let result = newThis.fn(arg);
//刪除傳遞過來this上聲明的方法,防止出現(xiàn)問題
delete newThis.fn;
// 將執(zhí)行結(jié)果返回
return result;
};
//執(zhí)行
fnLog.myApply(obj, [1, 212, 232]);
手寫bind方法
bind不是立即執(zhí)行而是返回一個新的函數(shù)
Function.prototype.myBind = function(content, ...arg) {
// 創(chuàng)建一個變量接受改變的this,如果改變的this為空則采用window為默認this
let newThis = content || window;
// 給當前傳遞過來的this,添加一個方法,遵循this準則,誰調(diào)用就指向誰的原則
newThis.fn = this;
// 由于bind不是立即執(zhí)行,是返回一個函數(shù)作為bind方法執(zhí)行的返回值,所以這里需要return出去一個函數(shù)
return function() {
// 然后在把執(zhí)行當前的方法進行執(zhí)行并把myBind接受剩余參數(shù)傳遞過去,接受返回值
let result = newThis.fn(...arg);
//刪除當前的函數(shù)以及傳遞過來的this,防止出現(xiàn)問題
delete newThis.fn;
// 將執(zhí)行結(jié)果返回
return result;
}
};
//調(diào)用bind函數(shù),獲取返回值,他的返回值是一個函數(shù),所以我們需要在調(diào)用一下
let f1 = fnLog.myBind(obj, 2);
//調(diào)用bind的返回值
f1()到此這篇關(guān)于JavaScript手寫call,apply,bind方法的文章就介紹到這了,更多相關(guān)JavaScript call內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript設(shè)計模式 – 建造者模式原理與應(yīng)用實例分析
這篇文章主要介紹了javascript設(shè)計模式 – 建造者模式,結(jié)合實例形式分析了javascript建造者模式相關(guān)概念、原理、應(yīng)用場景及操作注意事項,需要的朋友可以參考下2020-04-04
Node的優(yōu)勢我就不再亂吹捧了,它讓javascript統(tǒng)一web的前后臺成為了可能。但是對于新手來說,server端的JS代碼可能不像client端的代碼那么好調(diào)試,直觀。client端JS代碼的調(diào)試基本上經(jīng)歷了一個從“肉眼--alert()--firebug(或者其它的developer tools)”的一個過程。而對于server端的調(diào)試,可能新手仍然停留在使用“肉眼--console()”的階段。其實,Node經(jīng)過了這么多年(雖然才短短幾年)的發(fā)展,也有了很多不錯的第三方的調(diào)試工具。包括Node內(nèi)建的調(diào)試工具debugger、node-inspector等。2014-05-05
微信小程序前端通過weixin://wxpay/bizpayurl生成支付二維碼全過程
這篇文章主要給大家介紹了關(guān)于微信小程序前端通過weixin://wxpay/bizpayurl生成支付二維碼的相關(guān)資料,weixin://wxpay/bizpayurl 是一個微信支付的鏈接地址,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-07-07

