最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用JS簡單實現(xiàn)apply、call和bind方法的實例代碼

 更新時間:2022年02月20日 08:11:45   作者:MomentYY  
在JavaScript中,call、apply和bind是Function對象自帶的三個方法,這三個方法的主要作用是改變函數(shù)中的this指向,下面這篇文章主要給大家介紹了關(guān)于如何使用JS簡單實現(xiàn)apply、call和bind方法的相關(guān)資料,需要的朋友可以參考下

1.方法介紹

apply、call和bind都是系統(tǒng)提供給我們的內(nèi)置方法,每個函數(shù)都可以使用這三種方法,是因為apply、call和bind都實現(xiàn)在了Function的原型上(Function.prototype),而他們的作用都是給我們函數(shù)調(diào)用時顯式綁定上this。下面先介紹一下它們的基本用法:

apply方法:調(diào)用一個具有給定this值的函數(shù),以及以一個數(shù)組(或類數(shù)組對象)的形式提供的參數(shù)。

使用語法:func.apply(thisArg, [argsArray])

thisArg:在func函數(shù)調(diào)用時綁定的this值;[argsArray]:一個數(shù)組或者類數(shù)組對象,其中的數(shù)組元素將作為單獨的參數(shù)傳給func函數(shù);

使用效果:

function foo(x, y ,z) {
  console.log(this, x, y, z)
}

const obj = { name: 'curry', age: 30 }
/**
 * 1.將obj對象綁定給foo函數(shù)的this
 * 2.數(shù)組中的1 2 3分別傳遞給foo函數(shù)對應(yīng)的三個參數(shù)
 */
foo.apply(obj, [1, 2, 3])

call方法:使用一個指定的 this值和單獨給出的一個或多個參數(shù)來調(diào)用一個函數(shù)。

使用語法:func.call(thisArg, arg1, arg2, ...)

thisArg:在func函數(shù)調(diào)用時綁定的this值;arg1, arg2, ...:指定的參數(shù)列表,將作為參數(shù)傳遞給func函數(shù);

使用效果:

function foo(x, y ,z) {
  console.log(this, x, y, z)
}

const obj = { name: 'curry', age: 30 }
/**
 * 1.將obj對象綁定給foo函數(shù)的this
 * 2.call剩余參數(shù)中的a b c分別傳遞給foo函數(shù)對應(yīng)的三個參數(shù)
 */
foo.call(obj, 'a', 'b', 'c')

bind方法:創(chuàng)建一個新的函數(shù),在bind()被調(diào)用時,這個新函數(shù)的this被指定為bind()的第一個參數(shù),而其余參數(shù)將作為新函數(shù)的參數(shù),供調(diào)用時使用。

使用語法:func.bind(thisArg[, arg1[, arg2[, ...]]])

thisArg:調(diào)用func函數(shù)時作為this參數(shù)傳遞給目標(biāo)函數(shù)的值;arg1, arg2, ...:當(dāng)目標(biāo)函數(shù)被調(diào)用時,被預(yù)置入func函數(shù)的參數(shù)列表中的參數(shù);

使用效果:

function foo(...args) {
  console.log(this, ...args)
}

const obj = { name: 'curry', age: 30 }
/**
 * 1.將obj對象綁定給foo函數(shù)的this
 * 2.bind剩余參數(shù)中的1 2 3分別傳遞給foo函數(shù)中參數(shù)
 * 3.也可在newFoo調(diào)用時傳入?yún)?shù),這時bind傳遞的參數(shù)會與newFoo調(diào)用時傳遞的參數(shù)進行合并
 */
const newFoo = foo.bind(obj, 1, 2, 3)
newFoo()
newFoo('a', 'b', 'c')

總結(jié):

apply和call主要用于在函數(shù)調(diào)用時給函數(shù)的this綁定對應(yīng)的值,兩者作用類似,主要區(qū)別就是除了第一個參數(shù),apply方法接受的是一個參數(shù)數(shù)組,而call方法接受的是參數(shù)列表。

bind也是給函數(shù)指定this所綁定的值,不同于apply和call的是,它會返回一個新的函數(shù),新函數(shù)中的this指向就是我們所指定的值,且分別傳入的參數(shù)會進行合并。

2.apply、call和bind方法的實現(xiàn)

為了所有定義的函數(shù)能夠使用我們自定義的apply、call和bind方法,所以需要將自己實現(xiàn)的方法掛在Function的原型上,這樣所有的函數(shù)就可以通過原型鏈找到自定義的這三個方法了。

2.1.apply的實現(xiàn)

Function.prototype.myApply = function(thisArg, argArray) {
  // 1.獲取當(dāng)前需要被執(zhí)行的函數(shù)
  // 因為myApply是需要被當(dāng)前函數(shù)進行調(diào)用的,根據(jù)this的隱式綁定,此處的this就是指向當(dāng)前需要被執(zhí)行的函數(shù)
  const fn = this

  // 2.對傳入的thisArg進行邊界判斷
  if (thisArg === null || thisArg === undefined) {
    // 當(dāng)傳入的是null或者undefined是,被執(zhí)行函數(shù)的this直接指向全局window
    thisArg = window
  } else {
    // 將傳入的thisArg對象化,方便后面在thisArg添加屬性
    thisArg = Object(thisArg)
  }
  // 也可簡單寫成三元運算符:
  // thisArg = (thisArg === null || thisArg === undefined) ? window : Object(thisArg)

  // 3.將獲取的fn添加到thisArg對象上
  // 這里使用Symbol的原因是避免外部傳入的thisArg中的屬性與添加fn有沖突
  const fnSymbol = Symbol()
  Object.defineProperty(thisArg, fnSymbol, {
    enumerable: false,
    configurable: true,
    writable: false,
    value: fn
  })
  // 也可簡單寫成
  // thisArg[fnSymbol] = fn

  // 4.對argArray進行判斷
  // 看是否有傳入值,沒有值傳入就默認(rèn) []
  argArray = argArray || []

  // 5.調(diào)用獲取的fn函數(shù),并將對應(yīng)傳入的數(shù)組展開傳遞過去
  const result = thisArg[fnSymbol](...argArray)
  // 調(diào)用完后刪除添加的屬性
  delete thisArg[fnSymbol]

  // 6.將結(jié)果返回
  return result
}

測試:雖然打印出來的對象中還存在Symbol屬性,實際上已經(jīng)通過delete刪除了,這里是對象引用的問題。

function foo(x, y, z) {
  console.log(this, x, y, z)
}

foo.myApply({name: 'curry'}, [1, 2, 3])

2.2.call的實現(xiàn)

call方法的實現(xiàn)和apply方法的實現(xiàn)差不多,主要在于后面參數(shù)的處理。

Function.prototype.myCall = function(thisArg, ...args) {
  // 1.獲取當(dāng)前需要被執(zhí)行的函數(shù)
  const fn = this

  // 2.對傳入的thisArg進行邊界判斷
  thisArg = (thisArg === null || thisArg === undefined) ? window : Object(thisArg)

  // 3.將獲取的fn添加到thisArg對象上
  const fnSymbol = Symbol()
  thisArg[fnSymbol] = fn

  // 4.調(diào)用獲取的fn函數(shù),并將對應(yīng)傳入的args傳遞過去
  const result = thisArg[fnSymbol](...args)
  // 調(diào)用完后刪除添加的屬性
  delete thisArg[fnSymbol]

  // 5.將結(jié)果返回
  return result
}

測試:

function foo(x, y, z) {
  console.log(this, x, y, z)
}

foo.myCall({name: 'curry'}, 1, 2, 3)

2.3.bind的實現(xiàn)

bind方法的實現(xiàn)稍微復(fù)雜一點,需要考慮到參數(shù)合并的問題。

Function.prototype.myBind = function(thisArg, ...argsArray) {
  // 1.獲取當(dāng)前的目標(biāo)函數(shù),也就是當(dāng)前使用myBind方法的函數(shù)
  const fn = this

  // 2.對傳入的thisArg進行邊界判斷
  thisArg = (thisArg === null || thisArg === undefined) ? window : Object(thisArg)

  // 3.將獲取的fn添加到thisArg對象上
  const fnSymbol = Symbol()
  thisArg[fnSymbol] = fn

  // 4.定義一個新的函數(shù)
  function newFn(...args) {
    // 4.1.合并myBind和newFn傳入的參數(shù)
    const allArgs = [...argsArray, ...args]
    // 4.2.調(diào)用真正需要被調(diào)用的函數(shù),并將合并后的參數(shù)傳遞過去
    const result = thisArg[fnSymbol](...allArgs)
    // 4.3.調(diào)用完后刪除添加的屬性
    delete thisArg[fnSymbol]

    // 4.4.將結(jié)果返回
    return result
  }

  // 6.將新函數(shù)返回
  return newFn
}

測試:

function foo(x, y, z) {
  console.log(this, x, y, z)
}

const newFoo = foo.myBind({ name: 'curry' }, 1, 2)
newFoo(3)

總結(jié)

到此這篇關(guān)于使用JS簡單實現(xiàn)apply、call和bind方法的文章就介紹到這了,更多相關(guān)JS實現(xiàn)apply、call和bind方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

青川县| 抚州市| 疏附县| 长武县| 和龙市| 扎囊县| 仙居县| 临洮县| 慈溪市| 巴塘县| 义乌市| 岑溪市| 三河市| 灵寿县| 子洲县| 清水河县| 台北县| 白城市| 卢龙县| 南通市| 阿拉善左旗| 宜兰市| 宣威市| 拜城县| 青龙| 壶关县| 白水县| 炎陵县| 黄梅县| 富锦市| 环江| 滕州市| 读书| 神池县| 德昌县| 江津市| 石城县| 东台市| 定安县| 郓城县| 丽水市|