成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

JavaScript中bind方法的實(shí)現(xiàn)

dackel / 962人閱讀

摘要:新函數(shù)也能使用操作符創(chuàng)建對(duì)象這種行為就像把原函數(shù)當(dāng)成構(gòu)造器,提供的值被忽略。說(shuō)明綁定后的新函數(shù)被實(shí)例化之后,需要繼承原函數(shù)的原型鏈方法,且綁定過(guò)程中提供的被忽略繼承原函數(shù)的對(duì)象,但是參數(shù)還是會(huì)使用。

在討論bind方法前,我們可以先看一個(gè)例子:

var getElementsByTagName = document.getElementsByTagName;
getElementsByTagName("body");

這樣在瀏覽器(這里使用的是chrome)執(zhí)行會(huì)報(bào)錯(cuò):

原因也顯而易見(jiàn):上面的getElementsByTagName方法是document.getElementsByTagName的引用,但是在執(zhí)行時(shí)this指向了globalwindow對(duì)象,而不是document對(duì)象。

解決辦法也很簡(jiǎn)單,使用callbind方法來(lái)改變this

var getElementsByTagName = document.getElementsByTagName;
getElementsByTagName.call(document, "body");

var getElementsByTagName = document.getElementsByTagName;
getElementsByTagName.bind(document)("body");

上述兩種解決辦法也可以看出callbind的區(qū)別:call方法是直接執(zhí)行,而bind方法是返回一個(gè)新函數(shù)。

實(shí)現(xiàn)

由于bind方法是從ES5才開(kāi)始引入的,不是所有瀏覽器都支持,為了實(shí)現(xiàn)兼容,需要自己實(shí)現(xiàn)bind方法。

我們先來(lái)看看bind方法的定義:

bind方法會(huì)創(chuàng)建一個(gè)新函數(shù)。當(dāng)這個(gè)新函數(shù)被調(diào)用時(shí),bind的第一個(gè)參數(shù)將作為它運(yùn)行時(shí)的this(該參數(shù)不能被重寫(xiě)), 之后的一序列參數(shù)將會(huì)在傳遞的實(shí)參前傳入作為它的參數(shù)。
新函數(shù)也能使用new操作符創(chuàng)建對(duì)象:這種行為就像把原函數(shù)當(dāng)成構(gòu)造器,提供的this值被忽略。
初步思路

因?yàn)?b>bind方法不是立即執(zhí)行函數(shù),需要返回一個(gè)待執(zhí)行的函數(shù),這里可以利用閉包:return function(){};

作用域綁定:可以使用applycall方法來(lái)實(shí)現(xiàn);

參數(shù)傳遞:由于參數(shù)的不確定性,需要用apply傳遞數(shù)組;

根據(jù)上述思路,我們先來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的customBind方法;

Function.prototype.customBind = function (context) {
    var self = this,
        /**
         * 由于參數(shù)的不確定性,我們用 arguments 來(lái)處理
         * 這里的 arguments 只是一個(gè)類(lèi)數(shù)組對(duì)象,可以用數(shù)組的 slice 方法轉(zhuǎn)化成標(biāo)準(zhǔn)格式數(shù)組
         * 除了作用域?qū)ο?self 以外,后面的所有參數(shù)都需要作為數(shù)組進(jìn)行參數(shù)傳遞
         */
        args = Array.prototype.slice.call(arguments, 1);
    // 返回新函數(shù)
    return function() {
        // 作用域綁定
        return self.apply(context, args);
    }
};
測(cè)試初版
var testFn = function(obj, arg) {
    console.log("作用域?qū)ο髮傩灾担? + this.value);
    console.log("綁定函數(shù)時(shí)參數(shù)對(duì)象屬性值:" + obj.value);
    console.log("調(diào)用新函數(shù)參數(shù)值:" + arg);
}
var testObj = {
    value: 1
};
var newFn = testFn.customBind(testObj, {value: 2});
newFn("hello world");

// 執(zhí)行結(jié)果:
// 作用域?qū)ο髮傩灾担?
// 綁定函數(shù)時(shí)參數(shù)對(duì)象屬性值:2
// 調(diào)用新函數(shù)參數(shù)值:undefined

從測(cè)試執(zhí)行結(jié)果可以看出,上面已經(jīng)實(shí)現(xiàn)了作用域綁定,但是返回新函數(shù)newFn不支持傳參,只能在testFn綁定時(shí)傳參。
因?yàn)槲覀冏罱K需要使用的是newFn,所以我們需要讓newFn支持傳參。

動(dòng)態(tài)參數(shù)

我們來(lái)繼續(xù)改造

Function.prototype.customBind = function (context) {
    var fn = this,
        args = Array.prototype.slice.call(arguments, 1);
    return function() {
        // 將新函數(shù)執(zhí)行時(shí)的參數(shù) arguments 全部數(shù)組化,然后與綁定時(shí)傳參 arg 合并
        var newArgs = Array.prototype.slice.call(arguments);
        return fn.apply(context, args.concat(newArgs));
    }
};
測(cè)試動(dòng)態(tài)參數(shù)
var testFn = function(obj, arg) {
    console.log("作用域?qū)ο髮傩灾担? + this.value);
    console.log("綁定函數(shù)時(shí)參數(shù)對(duì)象屬性值:" + obj.value);
    console.log("調(diào)用新函數(shù)參數(shù)值:" + arg);
}
var testObj = {
    value: 1
};
var newFn = testFn.customBind(testObj, {value: 2});
newFn("hello world");

// 執(zhí)行結(jié)果:
// 作用域?qū)ο髮傩灾担?
// 綁定函數(shù)時(shí)參數(shù)對(duì)象屬性值:2
// 調(diào)用新函數(shù)參數(shù)值:hello world

可以看出,綁定時(shí)傳的參數(shù)和新函數(shù)執(zhí)行時(shí)傳的參數(shù)是合并在一起形成完整參數(shù)的。

原型鏈

我們?cè)倩氐?b>bind方法的定義第二條:新函數(shù)也能使用new操作符創(chuàng)建對(duì)象。
說(shuō)明綁定后的新函數(shù)被new實(shí)例化之后,需要繼承原函數(shù)的原型鏈方法,且綁定過(guò)程中提供的this被忽略(繼承原函數(shù)的this對(duì)象),但是參數(shù)還是會(huì)使用。所以我們需要一個(gè)中轉(zhuǎn)的函數(shù)將原型鏈傳遞下去。

首先我們需要明確new實(shí)例化過(guò)程,比如說(shuō)var a = new b()

創(chuàng)建一個(gè)空對(duì)象a = {},并且this變量引用指向到這個(gè)空對(duì)象a

繼承被實(shí)例化函數(shù)的原型:a.__proto__ = b.prototype

被實(shí)例化方法bthis對(duì)象的屬性和方法將被加入到這個(gè)新的this引用的對(duì)象中:b的屬性和方法被加入的a里面;

新創(chuàng)建的對(duì)象由this所引用:b.call(a);

接下來(lái)我們實(shí)現(xiàn)原型鏈。

Function.prototype.customBind = function (context) {
    var self = this,
        args = Array.prototype.slice.call(arguments, 1);
    // 創(chuàng)建中轉(zhuǎn)函數(shù)
    var cacheFn = function() {};
    var newFn =  function() {
        var newArgs = Array.prototype.slice.call(arguments);
        /**
         * 這里的 this 是指調(diào)用時(shí)的執(zhí)行上下文
         * 如果是 new 操作,需要綁定 new 之后作用域,this 指向新的實(shí)例對(duì)象
         */
        return self.apply(this instanceof cacheFn ? this : context, args.concat(newArgs));
    };

    // 中轉(zhuǎn)原型鏈
    cacheFn.prototype = self.prototype;
    newFn.prototype = new cacheFn();

    return newFn;
};
測(cè)試原型鏈
function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function() {
  return this.x + "," + this.y;
};

var YAxisPoint = Point.customBind({}, 0);
var axisPoint = new YAxisPoint(5);
axisPoint.toString();   // "0,5"

axisPoint instanceof Point; // true
axisPoint instanceof YAxisPoint; // true
new Point(1, 2) instanceof YAxisPoint; // true

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/108910.html

相關(guān)文章

  • 理解 JavaScript call()/apply()/bind()

    摘要:理解文章中已經(jīng)比較全面的分析了在中的指向問(wèn)題,用一句話來(lái)總結(jié)就是的指向一定是在執(zhí)行時(shí)決定的,指向被調(diào)用函數(shù)的對(duì)象。與和直接執(zhí)行原函數(shù)不同的是,返回的是一個(gè)新函數(shù)。這個(gè)新函數(shù)包裹了原函數(shù),并且綁定了的指向?yàn)閭魅氲摹? 理解 JavaScript this 文章中已經(jīng)比較全面的分析了 this 在 JavaScript 中的指向問(wèn)題,用一句話來(lái)總結(jié)就是:this 的指向一定是在執(zhí)行時(shí)決定的,...

    duan199226 評(píng)論0 收藏0
  • Javascriptbind()方法使用與實(shí)現(xiàn)

    摘要:秒后調(diào)用函數(shù)我有朵花瓣注意對(duì)于事件處理函數(shù)和方法也可以使用上面的方法綁定函數(shù)作為構(gòu)造函數(shù)綁定函數(shù)也適用于使用操作符來(lái)構(gòu)造目標(biāo)函數(shù)的實(shí)例。 在討論bind()方法之前我們先來(lái)看一道題目: javascriptvar altwrite = document.write; altwrite(hello); //1.以上代碼有什么問(wèn)題 //2.正確操作是怎樣的 //3.bind()方法怎么實(shí)...

    CastlePeaK 評(píng)論0 收藏0
  • call,apply and bind in JavaScript

    摘要:文章盡量使用大量實(shí)例進(jìn)行講解,它們的使用場(chǎng)景。在嚴(yán)格模式下,函數(shù)被調(diào)用后,里面的默認(rèn)是后面通過(guò)調(diào)用函數(shù)上的和方法,該變指向,函數(shù)里面的指向。利用,可以傳入外層的上下文。同樣適用的還有,里面的對(duì)象,它也是一種類(lèi)數(shù)組對(duì)象。 call,apply and bind in JavaScript 在ECMAScript中,每個(gè)函數(shù)都包含兩個(gè)繼承而來(lái)的方法:apply() 和 call(),這兩個(gè)...

    JohnLui 評(píng)論0 收藏0
  • JavaScript之柯里化

    摘要:簡(jiǎn)介柯里化,又稱(chēng)部分求值,是把接收多個(gè)參數(shù)的函數(shù)變成接受一個(gè)單一參數(shù)最初函數(shù)的第一個(gè)參數(shù)的函數(shù),并且返回接受剩余的參數(shù)而且返回結(jié)果的新函數(shù)的技術(shù)。按照作者的說(shuō)法,所謂柯里化就是使函數(shù)理解并處理部分應(yīng)用。的思想極大地助于提升函數(shù)的復(fù)用性。 簡(jiǎn)介 柯里化(Currying),又稱(chēng)部分求值(Partial Evaluation),是把接收多個(gè)參數(shù)的函數(shù)變成接受一個(gè)單一參數(shù)(最初函數(shù)的第一個(gè)...

    since1986 評(píng)論0 收藏0
  • bind方法javascript實(shí)現(xiàn)及函數(shù)柯里化

    摘要:而模擬的方法返回的函數(shù)用作構(gòu)造函數(shù)時(shí),生成的對(duì)象為。同樣,使用運(yùn)算符時(shí),綁定構(gòu)造函數(shù)和未綁定構(gòu)造函數(shù)并無(wú)兩樣。標(biāo)準(zhǔn)的方法創(chuàng)建一個(gè)新函數(shù)稱(chēng)為綁定函數(shù),新函數(shù)與被調(diào)函數(shù)綁定函數(shù)的目標(biāo)函數(shù)具有相同的函數(shù)體在規(guī)范中內(nèi)置的屬性。 這是一道面試題,題目給出了使用bind方法的樣例,要求用javascript實(shí)現(xiàn)這個(gè)方法,面試官還很善意的提醒我函數(shù)柯里化,然而,我還是不會(huì)這道題目,所以回來(lái)這會(huì)《ja...

    Tamic 評(píng)論0 收藏0
  • JavaScript || 函數(shù)

    摘要:每個(gè)函數(shù)表達(dá)式包括函數(shù)對(duì)象括號(hào)和傳入的實(shí)參組成。和作用都是動(dòng)態(tài)改變函數(shù)體內(nèi)指向,只是接受參數(shù)形式不太一樣。在定義函數(shù)時(shí),形參指定為一個(gè)對(duì)象調(diào)用函數(shù)時(shí),將整個(gè)對(duì)象傳入函數(shù),無(wú)需關(guān)心每個(gè)屬性的順序。 函數(shù) JavaScript中,函數(shù)指只定義一次,但可以多次被多次執(zhí)行或調(diào)用的一段JavaScript代碼。與數(shù)組類(lèi)似,JavaScript中函數(shù)是特殊的對(duì)象,擁有自身屬性和方法 每個(gè)函數(shù)對(duì)象...

    learn_shifeng 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<