欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

apply?call?bind方法原理及使用場景示例詳解

 更新時間:2023年08月30日 08:48:44   作者:codeteenager  
這篇文章主要為大家介紹了apply&call&bind方法原理及使用場景示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

正文

call、apply 和 bind 是掛在 Function 對象上的三個方法,調(diào)用這三個方法的必須是一個函數(shù)。

基本用法如下:

func.call(thisArg, param1, param2, ...)
func.apply(thisArg, [param1,param2,...])
func.bind(thisArg, param1, param2, ...)

其中 func 是要調(diào)用的函數(shù),thisArg 一般為 this 所指向的對象,后面的 param1、2 為函數(shù) func 的多個參數(shù),如果 func 不需要參數(shù),則后面的 param1、2 可以不寫。

這三個方法共有的、比較明顯的作用就是,都可以改變函數(shù) func 的 this 指向。call 和 apply 的區(qū)別在于,傳參的寫法不同:apply 的第 2 個參數(shù)為數(shù)組; call 則是從第 2 個至第 N 個都是給 func 的傳參;而 bind 和這兩個(call、apply)又不同,bind 雖然改變了 func 的 this 指向,但不是馬上執(zhí)行,而這兩個(call、apply)是在改變了函數(shù)的 this 指向之后立馬執(zhí)行。

這三個方法的理念都是借用方法的思路,例如A 對象有個 getName 的方法,B 對象也需要臨時使用同樣的方法,那么這時候我們是單獨為 B 對象擴展一個方法,還是借用一下 A 對象的方法呢?當然是可以借用 A 對象的 getName 方法,既達到了目的,又節(jié)省重復(fù)定義,節(jié)約內(nèi)存空間。

方法/特征callapplybind
方法參數(shù)多個單個數(shù)組多個
方法功能函數(shù)調(diào)用改變this函數(shù)調(diào)用改變this函數(shù)調(diào)用改變this
返回結(jié)果的直接執(zhí)行的直接執(zhí)行返回待執(zhí)行函數(shù)
底層實現(xiàn)通過eval通過eval間接調(diào)用apply

應(yīng)用場景

我們來看看應(yīng)用場景有哪些?

判斷數(shù)據(jù)類型

用 Object.prototype.toString 來判斷類型是最合適的,借用它我們幾乎可以判斷所有類型的數(shù)據(jù)。

function getType(obj){
  let type  = typeof obj;
  if (type !== "object") {
    return type;
  }
  return Object.prototype.toString.call(obj).replace(/^$/, '$1');
}

判斷數(shù)據(jù)類型就是借用了 Object 的原型鏈上的 toString 方法,最后返回用來判斷傳入的 obj 的字符串,來確定最后的數(shù)據(jù)類型。

類數(shù)組借用方法

類數(shù)組因為不是真正的數(shù)組,所有沒有數(shù)組類型上自帶的種種方法,所以我們就可以利用一些方法去借用數(shù)組的方法,例如:

var arrayLike = { 
  0: 'java',
  1: 'script',
  length: 2
} 
Array.prototype.push.call(arrayLike, 'jack', 'lily'); 
console.log(typeof arrayLike); // 'object'
console.log(arrayLike);
// {0: "java", 1: "script", 2: "jack", 3: "lily", length: 4}

arrayLike 是一個對象,模擬數(shù)組的一個類數(shù)組。從數(shù)據(jù)類型上看,它是一個對象。從上面的代碼中可以看出,用 typeof 來判斷輸出的是 'object',它自身是不會有數(shù)組的 push 方法的,這里我們就用 call 的方法來借用 Array 原型鏈上的 push 方法,可以實現(xiàn)一個類數(shù)組的 push 方法,給 arrayLike 添加新的元素。

獲取數(shù)組的最大/最小值

我們可以用 apply 來實現(xiàn)數(shù)組中判斷最大 / 最小值,apply 直接傳遞數(shù)組作為調(diào)用方法的參數(shù),也可以減少一步展開數(shù)組,可以直接使用 Math.max、Math.min 來獲取數(shù)組的最大值 / 最小值,例如:

let arr = [13, 6, 10, 11, 16];
const max = Math.max.apply(Math, arr); 
const min = Math.min.apply(Math, arr);
console.log(max);  // 16
console.log(min);  // 6

apply和call的實現(xiàn)

apply 和 call 基本原理是差不多的,只是參數(shù)存在區(qū)別。

Function.prototype.call = function (context, ...args) {
  var context = context || window;
  context.fn = this;
  var result = eval('context.fn(...args)');
  delete context.fn
  return result;
}
Function.prototype.apply = function (context, args) {
  let context = context || window;
  context.fn = this;
  let result = eval('context.fn(...args)');
  delete context.fn
  return result;
}

實現(xiàn) call 和 apply 的關(guān)鍵就在 eval 這行代碼。其中顯示了用 context 這個臨時變量來指定上下文,然后還是通過執(zhí)行 eval 來執(zhí)行 context.fn 這個函數(shù),最后返回 result。

要注意這兩個方法和 bind 的區(qū)別就在于,這兩個方法是直接返回執(zhí)行結(jié)果,而 bind 方法是返回一個函數(shù),因此這里直接用 eval 執(zhí)行得到結(jié)果。

bind的實現(xiàn)

bind 的實現(xiàn)思路基本和 apply 一樣,但是在最后實現(xiàn)返回結(jié)果這里,bind 和 apply 有著比較大的差異,bind 不需要直接執(zhí)行,因此不再需要用 eval ,而是需要通過返回一個函數(shù)的方式將結(jié)果返回,之后再通過執(zhí)行這個結(jié)果,得到想要的執(zhí)行效果。

Function.prototype.bind = function (context, ...args) {
    if (typeof this !== "function") {
      throw new Error("this must be a function");
    }
    var self = this;
    var fbound = function () {
        self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments)));
    }
    if(this.prototype) {
      fbound.prototype = Object.create(this.prototype);
    }
    return fbound;
}

實現(xiàn) bind 的核心在于返回的時候需要返回一個函數(shù),故這里的 fbound 需要返回,但是在返回的過程中原型鏈對象上的屬性不能丟失。因此這里需要用Object.create 方法,將 this.prototype 上面的屬性掛到 fbound 的原型上面,最后再返回 fbound。這樣調(diào)用 bind 方法接收到函數(shù)的對象,再通過執(zhí)行接收的函數(shù),即可得到想要的結(jié)果。

以上就是apply call bind方法原理及使用場景示例詳解的詳細內(nèi)容,更多關(guān)于apply call bind原理的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 使用?render?函數(shù)封裝高擴展的組件

    使用?render?函數(shù)封裝高擴展的組件

    這篇文章主要介紹了使用?render?函數(shù)封裝高擴展的組件,vue?官網(wǎng)給出的?render?函數(shù)的例子只能體現(xiàn)?render?函數(shù)的優(yōu)雅的一方面,卻不能看出其擴展性,今天就來封裝一個體現(xiàn)其擴展性的組件,需要的朋友可以參考一下
    2021-12-12
  • 客戶端靜態(tài)頁面玩分頁

    客戶端靜態(tài)頁面玩分頁

    客戶端靜態(tài)頁面玩分頁...
    2006-06-06
  • 前端常見跨域解決方案(全)

    前端常見跨域解決方案(全)

    這篇文章主要介紹了前端常見跨域解決方案的相關(guān)內(nèi)容,包括對跨域的解釋,常見跨域場景以及跨域解決方案,內(nèi)容豐富,需要的朋友可以參考下。
    2017-09-09
  • JavaScript?ES新特性塊級作用域

    JavaScript?ES新特性塊級作用域

    這篇文章主要介紹了JavaScript?ES新特性塊級作用域,所謂的塊級作用域,就是該變量只能在聲明時的代碼塊或者子代碼塊中使用,使JavaScript出現(xiàn)了塊級作用域,具體詳細內(nèi)容請參考下面文章內(nèi)容
    2021-12-12
  • 微信小程序 火車票查詢實例講解

    微信小程序 火車票查詢實例講解

    這篇文章主要介紹了微信小程序 火車票查詢實例講解的相關(guān)資料,這里提供了簡單實例來說明微信小程序的框架及如何開發(fā),需要的朋友可以參考下
    2016-10-10
  • 微信小程序 網(wǎng)絡(luò)請求(GET請求)詳解

    微信小程序 網(wǎng)絡(luò)請求(GET請求)詳解

    這篇文章主要介紹了微信小程序 網(wǎng)絡(luò)請求(GET請求)詳解的相關(guān)資料,需要的朋友可以參考下
    2016-11-11
  • 微信小程序 地圖map詳解及簡單實例

    微信小程序 地圖map詳解及簡單實例

    這篇文章主要介紹了微信小程序 地圖map詳解及簡單實例的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • js?websocket斷線重連實例代碼

    js?websocket斷線重連實例代碼

    這篇文章主要為大家介紹了js?websocket斷線重連實例代碼詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-07-07
  • You-Dont-Know-JS詞法作用域及兩種常見的模型學(xué)習文檔

    You-Dont-Know-JS詞法作用域及兩種常見的模型學(xué)習文檔

    這篇文章主要為大家介紹了JS?詞法作用域及兩種常見的模型詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • JS原始類型為什么能調(diào)用方法原理詳解

    JS原始類型為什么能調(diào)用方法原理詳解

    這篇文章主要為大家介紹了JS原始類型為什么能調(diào)用方法原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-06-06

最新評論