JavaScript手寫call,apply,bind方法
前言
改變this指向在書寫業(yè)務的時候經常遇到,我們經常采用以下方法進行改寫
- 使用作用聲明變量存儲this
- 使用jJavaScript的原生方法call,apply,以及bind進行改寫
第一種方法就不說了,就是一個變量存儲的問題,主要說第二種如何實現的
call,bind,apply方法都是JavaScript原生的方法,掛載在Function原型上,使得所有函數都可以調用,今天我們來實現一下call,apply,bind吧
改寫this實現思路
我們聲明一個函數,函數接受倆個參數,第一個參數是接受改變的this指向,第二個是剩余參數,用于執(zhí)行改變方法后傳遞的使用參數,在函數中里面聲明一個變量用于存儲傳遞過來的this,遵循this指向的準則,this是在執(zhí)行的時候生成的,函數的準則是誰調用它就指向誰,傳遞過來的this是一個對象,然后在傳遞過來的this上面聲明一個方法,聲明的方法就是當前函數,該方法由傳遞過來的this進行調用執(zhí)行,這樣就改變了this指向問題,在把傳遞過來的參數除第一個外全部傳遞給聲明的方法,我們來實現一下
前期準備
這些數據用于配合手寫的方法,由于call,bind,apply他們都是需要把他們掛載到函數原型上,函數才能調用的到,我們這里也把他掛載到原型上
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方法第一個參數都是改變的this指向,第二個參數是傳遞的參數
手寫call方法
call方法是改變this后立即執(zhí)行
Function.prototype.myCall = function(content, ...arg) { // 創(chuàng)建一個變量接受改變的this,如果改變的this為空則采用window為默認this let newThis = content || window; /**newThis是一個對象,它是傳遞過來的this,在newThis上新增一個方法,這個方法就是 當前函數 ,this就是指向的myCall,調用這個方法就可以改變this指向,因為函數是誰調用 它this就指向誰 **/ newThis.fn = this; /**執(zhí)行改變this方法,接受返回值,這里容易被誤導,這里是把myCall傳遞過來的參數傳遞 給了改變this的函數,由于不確定傳遞多少使用了剩余參數,這里也是 **/ let result = newThis.fn(...arg); //刪除傳遞過來this上聲明的方法,防止出現問題 delete newThis.fn; // 將執(zhí)行結果返回 return result; }; //執(zhí)行手寫的call方法 fnLog.myCall(obj, 'myCall');
手寫apply方法
apply傳遞的參數只能傳遞數組
//如果arg沒有傳遞參數,默認為空數組 Function.prototype.myApply = function(content, arg = []) { // 判斷傳遞參數是否為數組,如果不為數組則拋出錯誤,為數組則繼續(xù)執(zhí)行 if (!Array.isArray(arg)) { throw '傳遞參數必須為數組'; } // 創(chuàng)建一個變量接受改變的this,如果改變的this為空則采用window為默認this let newThis = content || window; // 給當前傳遞過來的this,添加一個方法,遵循this準則,誰調用就指向誰的原則 newThis.fn = this; // 同mycall相同 let result = newThis.fn(arg); //刪除傳遞過來this上聲明的方法,防止出現問題 delete newThis.fn; // 將執(zhí)行結果返回 return result; }; //執(zhí)行 fnLog.myApply(obj, [1, 212, 232]);
手寫bind方法
bind不是立即執(zhí)行而是返回一個新的函數
Function.prototype.myBind = function(content, ...arg) { // 創(chuàng)建一個變量接受改變的this,如果改變的this為空則采用window為默認this let newThis = content || window; // 給當前傳遞過來的this,添加一個方法,遵循this準則,誰調用就指向誰的原則 newThis.fn = this; // 由于bind不是立即執(zhí)行,是返回一個函數作為bind方法執(zhí)行的返回值,所以這里需要return出去一個函數 return function() { // 然后在把執(zhí)行當前的方法進行執(zhí)行并把myBind接受剩余參數傳遞過去,接受返回值 let result = newThis.fn(...arg); //刪除當前的函數以及傳遞過來的this,防止出現問題 delete newThis.fn; // 將執(zhí)行結果返回 return result; } }; //調用bind函數,獲取返回值,他的返回值是一個函數,所以我們需要在調用一下 let f1 = fnLog.myBind(obj, 2); //調用bind的返回值 f1()
到此這篇關于JavaScript手寫call,apply,bind方法的文章就介紹到這了,更多相關JavaScript call內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
鼠標事件的screenY,pageY,clientY,layerY,offsetY屬性詳解
這篇文章主要介紹了鼠標事件的screenY,pageY,clientY,layerY,offsetY屬性詳解,需要的朋友可以參考下2015-03-03一文帶你掌握JavaScript中的執(zhí)行上下文和作用域
作為一名前端工作人員,我們必須知道JavaScript內部是如何執(zhí)行的。那對于執(zhí)行上下文和作用域的理解至關重要,無論是工作還是面試都是無法跳躍的一步,本文就來帶大家深入了解一下2023-02-02JavaScript中使用正則匹配多條,且獲取每條中的分組數據
該問題在使用Ajax遠程獲取某網頁數據時經常遇見 如果目標頁面是XML,就好辦了,實用XMLDOM可以很輕松完成任務。2010-11-11