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

一文搞懂JavaScript中bind,apply,call的實(shí)現(xiàn)

 更新時(shí)間:2022年06月24日 09:16:05   作者:諸葛小愚  
bind、call和apply都是Function原型鏈上面的方法,因此不管是使用function聲明的函數(shù),還是箭頭函數(shù)都可以直接調(diào)用。本文就帶你看看如何實(shí)現(xiàn)bind、call和apply

bind、call和apply都是Function原型鏈上面的方法,因此不管是使用function聲明的函數(shù),還是箭頭函數(shù)都可以直接調(diào)用。這三個(gè)函數(shù)在使用時(shí)都可以改變this指向,本文就帶你看看如何實(shí)現(xiàn)bind、call和apply。

bind、call和apply的用法

bind

bind()方法可以被函數(shù)對(duì)象調(diào)用,并返回一個(gè)新創(chuàng)建的函數(shù)。

語(yǔ)法:

function.bind(thisArg[, arg1[, arg2[, ...]]])

bind()會(huì)將第一個(gè)參數(shù)作為新函數(shù)的this,如果未傳入?yún)?shù)列表,或者第一個(gè)參數(shù)是nullundefined,那么新函數(shù)的this將會(huì)是該函數(shù)執(zhí)行作用域的this。使用bind()應(yīng)注意以下事項(xiàng):

  • 返回一個(gè)新的函數(shù),但是不會(huì)立即執(zhí)行該函數(shù)
  • 根據(jù)傳入的參數(shù)列表綁定this指向,如果未傳入thisArg,那么需要明確this的指向
  • 如果是箭頭函數(shù),無(wú)法改變this,只能改變參數(shù),這一點(diǎn)我們?cè)?a href="http://m.fzitv.net/article/252806.htm" target="_blank">這些情況下不建議你使用箭頭函數(shù)也講到過(guò)

舉個(gè)例子:

正常使用

function fn(a) {
    console.log(this, a)
}
const fn1 = fn.bind({x: 100}); // fn1是一個(gè)函數(shù),但是并沒(méi)有立即執(zhí)行
fn1(); // {x:100} 100
console.log(fn === fn1); // false,bind返回的是一個(gè)新的函數(shù)

箭頭函數(shù)

const fn = (a) => {
    console.log(this, a);
}
const fn1 = fn.bind({x: 100}, 100); // 返回一個(gè)新的函數(shù)fn1,不會(huì)執(zhí)行
fn1(); // window,100 箭頭函數(shù)通過(guò)bind返回的函數(shù)無(wú)法修改其this指向

未綁定this,或綁定到null、undefined

const fn = (a) => {
    console.log(this, a);
}
const fn1 = fn.bind(); // 未綁定
const fn2 = fn.bind(null); // 綁定null
const fn3 = fn.bind(undefined); // 綁定undefined
fn1(); // 綁定到執(zhí)行作用域,默認(rèn)為window
fn2(); // 綁定到執(zhí)行作用域,默認(rèn)為window
fn3(); // 綁定到執(zhí)行作用域,默認(rèn)為window

call&apply

bind不同,callapply都是用來(lái)執(zhí)行函數(shù)的,可以解決執(zhí)行的函數(shù)的this指向問(wèn)題。

語(yǔ)法:

function.call(thisArg, arg1, arg2, ...)
function.apply(thisArg, argsArray)

call的參數(shù)列表是可選的,如果傳入的thisArgnull或者undefined,那么會(huì)自動(dòng)替換為全局對(duì)象;如果是傳入的原始值,則會(huì)替換為原始值對(duì)應(yīng)的包裝類型。apply的用法和call類似,不同點(diǎn)在于其額外傳入的參數(shù)是一個(gè)數(shù)組或類數(shù)組對(duì)象,而call的額外參數(shù)是不確定參數(shù)。

舉個(gè)栗子:

function fn(a, b) {
    console.log(this, a, b);
}
fn.call({x: 100}, 10, 20); // {x: 100} 10 20
fn.apply({x: 100}, [10, 20]); // {x: 100} 10 20

callapply無(wú)法修改箭頭函數(shù)的this指向:

const fn = (a, b) => {
    console.log(this, a, b);
}
fn.call({x: 100}, 10, 20); // Window 10 20
fn.apply({x: 100}, [10, 20]); // Window 10 20

簡(jiǎn)單回顧了以下bind、call、apply的使用,接下來(lái)就看看應(yīng)該如何來(lái)實(shí)現(xiàn)。

實(shí)現(xiàn)bind

根據(jù)我們剛剛使用的bind(),在設(shè)計(jì)時(shí)需要如下考慮:

  • 最終返回的是一個(gè)新的函數(shù),可通過(guò)function來(lái)聲明
  • 需要綁定新函數(shù)的this
  • 需要綁定運(yùn)行時(shí)的參數(shù),可通過(guò)apply或call來(lái)實(shí)現(xiàn)

實(shí)現(xiàn)代碼:

// 通過(guò)原型鏈注冊(cè)方法
// context:傳遞的上下文this;bindArgs表示需要綁定的額外參數(shù)
Function.prototype.newBind = function (context, ...bindArgs) {
    const self = this; // 當(dāng)前調(diào)用bind的函數(shù)對(duì)象

    // 返回的函數(shù)本身也是可以再傳入?yún)?shù)的
    return function (...args) {
        // 拼接參數(shù)
        const newArgs = bindArgs.concat(args);
        return self.apply(context, newArgs)
    }
}
function fn(a,b) {
    console.log(this, a, b);
}
const fn1 = fn.newBind({x: 100}, 10);
fn1(20); // {x: 100} 10 20

bind()返回的是一個(gè)新函數(shù),執(zhí)行新函數(shù)就相當(dāng)于是通過(guò)callapply來(lái)調(diào)用原函數(shù),并傳入this和參數(shù)。

實(shí)現(xiàn)call和apply

在實(shí)現(xiàn)bind的過(guò)程中,我們使用了apply來(lái)完成this的綁定,那么要實(shí)現(xiàn)apply又應(yīng)該用什么來(lái)綁定this呢?可能會(huì)有小機(jī)靈鬼發(fā)現(xiàn),好像在apply中使用call,在call中使用apply也可以完成this綁定。這不就形成了嵌套嘛,不是我們最終想要的。

我們先來(lái)

call和apply的應(yīng)用:

  • bind返回一個(gè)新的函數(shù),并不會(huì)執(zhí)行;call和apply會(huì)立即執(zhí)行函數(shù)
  • 綁定this
  • 傳入執(zhí)行參數(shù)

舉個(gè)栗子:

function fn(a, b) {
    console.log(this, a, b);
}
fn.call({x: 100}, 10, 20); // {x: 100} 10 20
fn.apply({x: 100}, [10, 20]); // {x: 100} 10 20

call和apply的實(shí)現(xiàn)效果是一樣的,都是立即執(zhí)行函數(shù),不同的是call需要傳入單個(gè)或者多個(gè)參數(shù),apply可以傳入一個(gè)參數(shù)數(shù)組。

如何在函數(shù)執(zhí)行時(shí)綁定this:

  • const obj = {x: 100, fn() {this.x}}
  • 執(zhí)行obj.fn(),此時(shí)fn()內(nèi)部的this指向的就是obj
  • 可以借此實(shí)現(xiàn)函數(shù)綁定this

使用過(guò)Vue的朋友都知道,Vue實(shí)例其實(shí)就是一個(gè)對(duì)象,其里面的方法在調(diào)用時(shí),this就會(huì)指向當(dāng)前對(duì)象。舉個(gè)栗子:

let obj = {
    key: 'key',
    getKey: () => {
        return this.key;
    },
    getKey2() {
        return this.key;
    }
};
obj.getKey(); // this指向window,返回值取決于window中是否有對(duì)應(yīng)的屬性
obj.getKey2(); // this指向obj,返回 'key'

這個(gè)例子在這些情況下不建議你使用箭頭函數(shù)也是有提及的,感興趣的朋友可以去看看。根據(jù)此原理,我們就可以來(lái)嘗試給函數(shù)綁定this了:某函數(shù)調(diào)用apply,那么我們就將這個(gè)函數(shù)添加到傳入的this對(duì)象中(如果未傳入則this為全局對(duì)象,如果傳入的是原始值,則使用其包裝類型),然后使用()來(lái)執(zhí)行函數(shù),這個(gè)時(shí)候函數(shù)的this指向的就是我們傳入的this了。

實(shí)現(xiàn)代碼:

Function.prototype.newCall = function(context, ...args) {
    if (context == null) context = globalThis; // 如果傳入的上下文是null或者undefined,則使用全局globalThis,一般指向的就是window
    if (typeof context !== 'object') context = new Object(context); // 如果是原始類型(數(shù)字、字符串、布爾值等),則使用其包裝類型

    const fnKey = Symbol(); // 使用Symbol可確保key值不會(huì)重復(fù),避免屬性覆蓋
    context[fnKey] = this; // this指向的是當(dāng)前調(diào)用newCall的函數(shù)

    console.log(context[fnKey]); // 打印當(dāng)前函數(shù)以及上下文this
    console.log(context);

    const res = context[fnKey](...args); // 執(zhí)行函數(shù),函數(shù)的this指向?yàn)閏ontext
    delete context[fnKey]; // 刪除fn,防止污染

    return res; // 返回結(jié)果
}
fn.newCall({x: 100}, 10, 20); // {x: 100} 10 20
function fn(a,b) {
    console.log(this, a, b);
}

這樣我們就實(shí)現(xiàn)了call,那么apply實(shí)現(xiàn)類似,只不過(guò)傳入的額外參數(shù)要變成數(shù)組或類數(shù)組的方式

Function.prototype.newCall = function(context, args) {
    if (context == null) context = globalThis; // 如果傳入的上下文是null或者undefined,則使用全局globalThis,一般指向的就是window
    if (typeof context !== 'object') context = new Object(context); // 如果是原始類型(數(shù)字、字符串、布爾值等),則使用其包裝類型

    const fnKey = Symbol(); // 使用Symbol可確保key值不會(huì)重復(fù),避免屬性覆蓋
    context[fnKey] = this; // this指向的是當(dāng)前調(diào)用newCall的函數(shù)

    console.log(context[fnKey]); // 打印當(dāng)前函數(shù)以及上下文this
    console.log(context);

    const res = context[fnKey](...args); // 執(zhí)行函數(shù),函數(shù)的this指向?yàn)閏ontext
    delete context[fnKey]; // 刪除fn,防止污染

    return res; // 返回結(jié)果
}
fn.newCall({x: 100}, 10, 20); // {x: 100} 10 20
function fn(a,b) {
    console.log(this, a, b);
}

注意打印的當(dāng)前函數(shù)以及上下文:

實(shí)現(xiàn)callapplybind有很大的不同就是如何來(lái)處理this綁定。

總結(jié)

學(xué)會(huì)了如何實(shí)現(xiàn)bind、call和apply,對(duì)于理解如何使用,以及如何避免潛在的錯(cuò)誤有很大的幫助。特別是callapply,我們?cè)趯?shí)現(xiàn)的時(shí)候借助于對(duì)象內(nèi)部的非箭頭函數(shù),其this指向?qū)ο笞陨?/strong>這一基礎(chǔ)知識(shí),實(shí)現(xiàn)了this綁定。如果還未搞清楚的朋友,可以將代碼運(yùn)行起來(lái)看看,也許能幫助你更好的理解。

以上就是一文搞懂JavaScript中bind,apply,call的實(shí)現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于JavaScript bind apply call的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JavaScript制作簡(jiǎn)單的框選圖表

    JavaScript制作簡(jiǎn)單的框選圖表

    這篇文章主要為大家詳細(xì)介紹了JavaScript制作一個(gè)簡(jiǎn)單的框選圖表,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • js HTML5 canvas繪制圖片的方法

    js HTML5 canvas繪制圖片的方法

    這篇文章主要為大家詳細(xì)介紹了js HTML5 canvas繪制圖片的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • JavaScript中的console.group()函數(shù)詳細(xì)介紹

    JavaScript中的console.group()函數(shù)詳細(xì)介紹

    這篇文章主要介紹了JavaScript中的console.group()函數(shù)詳細(xì)介紹,當(dāng)程序調(diào)試日志過(guò)多時(shí)會(huì)有些雜亂,此時(shí)可以使用console.group()函數(shù)調(diào)來(lái)分組顯示,需要的朋友可以參考下
    2014-12-12
  • Javascript頁(yè)面跳轉(zhuǎn)常見(jiàn)實(shí)現(xiàn)方式匯總

    Javascript頁(yè)面跳轉(zhuǎn)常見(jiàn)實(shí)現(xiàn)方式匯總

    這篇文章主要介紹了Javascript頁(yè)面跳轉(zhuǎn)常見(jiàn)實(shí)現(xiàn)方式,結(jié)合實(shí)例匯總分析了JavaScript常用的七種頁(yè)面跳轉(zhuǎn)實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-11-11
  • 當(dāng)達(dá)到輸入長(zhǎng)度時(shí)表單自動(dòng)切換焦點(diǎn)

    當(dāng)達(dá)到輸入長(zhǎng)度時(shí)表單自動(dòng)切換焦點(diǎn)

    給每個(gè)字段限制輸入長(zhǎng)度,當(dāng)達(dá)到輸入長(zhǎng)度時(shí)自動(dòng)切換焦點(diǎn),以增強(qiáng)表單的易用性,需要的朋友可以參考下
    2014-04-04
  • 老生常談Bootstrap媒體對(duì)象

    老生常談Bootstrap媒體對(duì)象

    下面小編就為大家?guī)?lái)一篇老生常談Bootstrap媒體對(duì)象。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • js+css在交互上的應(yīng)用

    js+css在交互上的應(yīng)用

    關(guān)于css應(yīng)用。以前一直認(rèn)為css就是做布局樣式,只能表現(xiàn)頁(yè)面,跟交互是沒(méi)關(guān)系的。事實(shí)上也基本不會(huì)往那邊想。
    2010-07-07
  • js 取時(shí)間差去掉周六周日實(shí)現(xiàn)代碼

    js 取時(shí)間差去掉周六周日實(shí)現(xiàn)代碼

    js 求時(shí)間差在生活中經(jīng)常會(huì)觸及到,本文整理了一些,希望可以幫助有需求的朋友可以,而起還可以實(shí)現(xiàn)去掉周六周日這些東東,廢話不多說(shuō),進(jìn)入正題
    2012-12-12
  • TypeScript 學(xué)習(xí)筆記之基本類型

    TypeScript 學(xué)習(xí)筆記之基本類型

    TypeScript 是 JavaScript 的超集,TypeScript 經(jīng)過(guò)編譯之后都會(huì)生成 JavaScript 代碼。TypeScript 最大的特點(diǎn)就是類型化,因此才叫做 TypeScript。比起弱類型的 JavaScript,類型化的 TypeScript 顯得更加容易維護(hù)。
    2015-06-06
  • 詳解JS: reduce方法實(shí)現(xiàn) webpack多文件入口

    詳解JS: reduce方法實(shí)現(xiàn) webpack多文件入口

    本篇文章主要介紹了詳解JS: reduce方法實(shí)現(xiàn) webpack多文件入口,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-02-02

最新評(píng)論

宽城| 治县。| 河北省| 子长县| 隆德县| 观塘区| 长葛市| 屏边| 汝阳县| 舞阳县| 新乡县| 屏东县| 林口县| 海门市| 正安县| 平昌县| 南郑县| 正定县| 淳化县| 岑巩县| 墨竹工卡县| 林芝县| 信阳市| 山东省| 托克逊县| 蚌埠市| 新乡市| 桂东县| 靖江市| 池州市| 昆山市| 正定县| 邹平县| 龙江县| 叶城县| 东方市| 林州市| 贵德县| 醴陵市| 肃北| 嵊泗县|