bind()啄栓、apply()撞叽、call()

bind()

語法:
fun.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg:當(dāng)綁定函數(shù)被調(diào)用時(shí)姻成,該參數(shù)會(huì)作為原函數(shù)運(yùn)行時(shí)的 this 指向。當(dāng)使用new操作符調(diào)用綁定函數(shù)時(shí)愿棋,該參數(shù)無效科展。

arg1, arg2, ...:當(dāng)綁定函數(shù)被調(diào)用時(shí),這些參數(shù)將置于實(shí)參之前傳遞給被綁定的方法糠雨。

return:返回由指定的this值和初始化參數(shù)改造的原函數(shù)拷貝

bind() 函數(shù)會(huì)創(chuàng)建一個(gè)新函數(shù)(稱為綁定函數(shù))才睹,新函數(shù)與被調(diào)函數(shù)(綁定函數(shù)的目標(biāo)函數(shù))具有相同的函數(shù)體。
當(dāng)新函數(shù)被調(diào)用時(shí) this 值綁定到 bind() 的第一個(gè)參數(shù)甘邀,該參數(shù)不能被重寫琅攘。綁定函數(shù)被調(diào)用時(shí),bind() 也接受預(yù)設(shè)的參數(shù)提供給原函數(shù)松邪。一個(gè)綁定函數(shù)也能使用new運(yùn)算符創(chuàng)建一個(gè)用戶定義的對(duì)象類型的實(shí)例或具有構(gòu)造函數(shù)的內(nèi)置對(duì)象的實(shí)例坞琴。")操作符創(chuàng)建對(duì)象:這種行為就像把原函數(shù)當(dāng)成構(gòu)造器。提供的 this 值被忽略逗抑,同時(shí)調(diào)用時(shí)的參數(shù)被提供給模擬函數(shù)剧辐。————MDN

創(chuàng)建綁定函數(shù)
bind() 最簡(jiǎn)單的用法是創(chuàng)建一個(gè)函數(shù)锋八,使這個(gè)函數(shù)不論怎么調(diào)用都有同樣的 this 值浙于。

    this.x = 9;

    var obj = {
        x: 81,
        GetObjx: function() {
            console.log(this.x);
        }
    };

    obj.GetObjx();         // 81

    var againGetObjx = obj.GetObjx;

    againGetObjx();        // 9      無法獲取到obj.x护盈,因?yàn)榇藭r(shí)的this指向Window

    // 創(chuàng)建一個(gè)新函數(shù)挟纱,將this綁定到obj對(duì)象
    var fn = againGetObjx.bind(obj);
    fn();                  // 81

上例中,againGetObjx引用了obj對(duì)象中的GetObjx方法腐宋,但是很顯然紊服,this.x沒有指向obj,是因?yàn)樾鼐海藭r(shí)調(diào)用againGetObjx的對(duì)象是全局對(duì)象欺嗤,理所當(dāng)然的this引用指向window,打印出window.x卫枝,即9煎饼。

使用bind()方法,在方法中我們傳入了obj對(duì)象校赤,強(qiáng)制指定了函數(shù)執(zhí)行上下文吆玖,將this綁定到了obj對(duì)象筒溃。


偏函數(shù)
bind()的另一個(gè)最簡(jiǎn)單的用法是使一個(gè)函數(shù)擁有預(yù)設(shè)的初始參數(shù)。這些參數(shù)(如果有的話)作為bind()的第二個(gè)參數(shù)跟在this(或其他對(duì)象)后面沾乘,之后它們會(huì)被插入到目標(biāo)函數(shù)的參數(shù)列表的開始位置怜奖,傳遞給綁定函數(shù)的參數(shù)會(huì)跟在它們的后面。

    function list() {
        return Array.prototype.slice.call(arguments);
    }
    
    var list1 = list(1,2,3);    
    console.log(list1);                     // [1,2,3];

    var leadingThirtysevenList = list.bind(undefined,37);


    var list2 = leadingThirtysevenList();   // [37]
    console.log(list2);

    var list3 = leadingThirtysevenList(1,2,3);
    console.log(list3);                     // [37,1,2,3]

函數(shù)中的arguments保存著傳入實(shí)參翅阵,但本身是類數(shù)組歪玲,沒有數(shù)組的方法,所以使用數(shù)組"類"中的slice方法來代替掷匠。
var leadingThirtysevenList = list.bind(undefined,37);實(shí)測(cè)滥崩,把undefined換成null也可以,表示不為this指定對(duì)象槐雾,函數(shù)體執(zhí)行不變夭委,那么在bind()方法第二個(gè)參數(shù)傳入的值會(huì)作為fn.bind()中fn的參數(shù)一起傳入,在這就是list()函數(shù)了募强。

改寫:

    function Fn(a,b,c) {
        console.log(a);
        console.log(b);
        console.log(c);
        return a+b+c;
    }
    var fn = Fn.bind(undefined,10); 

    console.log(
        fn(20,30)
    );
    /*
    10
    20
    30
    60
    */

當(dāng)然株灸,如果在bind()方法中傳入足夠的參數(shù),那么后續(xù)的參數(shù)就不會(huì)生效擎值,但是它依然存在在arguments類數(shù)組中慌烧。

    function Fn(a,b,c) {
        console.log(a);
        console.log(b);
        console.log(c);
        console.log(arguments);
        return a+b+c;
    }
    var fn = Fn.bind(undefined,10,1,2); 

    console.log(
        fn(20,30)   // 參數(shù)無效,但仍有arguments類數(shù)組保存
    );
    /*
    10
    1
    2
    13
    [10,1,2,20,30]
    */


配合 setTimeout
在默認(rèn)情況下,使用window.setTimeout()時(shí)鸠儿,this關(guān)鍵字會(huì)指向全局或者對(duì)象屹蚊。當(dāng)使用類的方法時(shí),需要 this 引用類的實(shí)例进每,你可能需要顯式地把 this 綁定到回調(diào)函數(shù)以便繼續(xù)使用實(shí)例汹粤。

    function fn() {
        console.log(this.petalCount);
    }

    function LateBloomer() {
        this.petalCount = Math.ceil(Math.random() * 12) + 1;
    }
    LateBloomer.prototype.bloom = function() {
        window.setTimeout(this.declare.bind(this),1000);
    }

    LateBloomer.prototype.declare = function() {
        console.log("I am beautiful flower with " + this.petalCount + "petals!");
    };

    var flower = new LateBloomer();
    flower.bloom();     // 一秒后,調(diào)用declare方法

apply()

apply() 方法調(diào)用一個(gè)函數(shù), 其具有一個(gè)指定的this值田晚,以及作為一個(gè)數(shù)組提供的參數(shù)嘱兼。
調(diào)用有指定this值和參數(shù)的函數(shù)的結(jié)果。
func.apply(thisArg, [argsArray])

簡(jiǎn)單理解用法:

    var obj = {
        a: 1,
        sum: function(b,c) {
            console.log(this.a + b + c);
        }
    }

    var obj2 = {
        a: 2
    }

    obj.sum.apply(obj2,[5,5]);      // 12

與構(gòu)造函數(shù):

    function Ball(shape) {
        this.shape = shape;
        this.Pi = Math.PI;
    }

    function FootBall(shape,color) {
        Ball.apply(this , arguments);
        this.color = color,
        this.say = function() {
            console.log("shape:" + this.shape + " this.color:" + this.color);
        }
    }

    var football = new FootBall("sphere","black");
    football.say();         // shape:sphere this.color:black

函數(shù)只不過是在特定環(huán)境中執(zhí)行代碼的對(duì)象贤徒,因此通過apply和call方法也可以在新創(chuàng)建的對(duì)象上執(zhí)行構(gòu)造函數(shù)

使用apply來鏈接構(gòu)造器:

Function.prototype.construct = function (aArgs) {
    var oNew = Object.create(this.prototype);
    console.log(this.prototype === MyConstructor.prototype);        // true

    this.apply(oNew, aArgs);        // this為構(gòu)造函數(shù)芹壕,以oNew(構(gòu)造函數(shù)的prototype)為上下文環(huán)境,傳入aArgs數(shù)組
    console.log(this);

    return oNew;
};

function MyConstructor() {
    for (var nProp = 0;nProp < arguments.length; nProp++) {
        this["property" + nProp] = arguments[nProp];
    }
}


var myArray = [4, "Hello world!", false];
var myInstance = MyConstructor.construct(myArray);

console.log(myInstance.property1);                                  // Hello world!

console.log(myInstance instanceof MyConstructor);                   // true
console.log(myInstance.constructor === MyConstructor);              // true
console.log(myInstance.__proto__.constructor === MyConstructor);    // true

construct()方法改寫(可能這樣更易讀):

Function.prototype.construct = function (aArgs) {
    var oNew = {};
    oNew.__proto__ = this.prototype;
    this.apply(oNew, aArgs);
    return oNew;
};

apply借調(diào)內(nèi)置函數(shù)

console.log(Math.max(1,2,3))        // 3    

// 借用Math.max()
var numbers = [5,6,2,3,7];

var max = Math.max.apply(null,numbers);
console.log(max);                   // 7

// 借用Math.min()
var min = Math.min.apply(undefined,numbers);
console.log(min);                   // 2

call()

call() 方法調(diào)用一個(gè)函數(shù), 其具有一個(gè)指定的this值和分別地提供的參數(shù)(參數(shù)的列表)接奈。返回值是你調(diào)用的方法的返回值踢涌,若該方法沒有返回值,則返回undefined序宦。
fun.call(thisArg, arg1, arg2, ...)

語法層面睁壁,與apply不同就是,call()方法傳遞的是一個(gè)參數(shù)列表,apply傳遞的是參數(shù)數(shù)組潘明。

常用用法:使用call方法調(diào)用函數(shù)并且指定上下文的this

function greet() {
  var reply = [this.person, 'Is An Awesome', this.role].join(' ');
  console.log(reply);
}

var i = {
  person: 'Douglas Crockford', role: 'Javascript Developer'
};
greet.call(i);

調(diào)用父構(gòu)造函數(shù)的call方法來實(shí)現(xiàn)繼承

function Product(name,price) {
    this.name = name;
    this.price =  price;
}

function Food(a,b,category) {
    Product.call(this,a,b);

    this.category = category;
}

var food = new Food("sour apple",5,"sour");
console.log(food);      // Food {name: "sour apple", price: 5, category: "sour"}

使用call方法調(diào)用匿名函數(shù)

var animals = [
    { species: "Lion", name: "King" },
    { species: "Whale", name: "Fail" }
]

for (var i = 0; i < animals.length; i++) {
    (function (i) {

        console.log("#" + i + " " + this.species + ": " + this.name);

    }).call(animals[i], i)
}

// #0 Lion: King
// #1 Whale: Fail

Js apply()使用詳解
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末糠惫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子钉疫,更是在濱河造成了極大的恐慌硼讽,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牲阁,死亡現(xiàn)場(chǎng)離奇詭異固阁,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)城菊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門备燃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人凌唬,你說我怎么就攤上這事并齐。” “怎么了客税?”我有些...
    開封第一講書人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵况褪,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我更耻,道長(zhǎng)测垛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任秧均,我火速辦了婚禮食侮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘目胡。我一直安慰自己锯七,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開白布誉己。 她就那樣靜靜地躺著眉尸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪巫延。 梳的紋絲不亂的頭發(fā)上效五,一...
    開封第一講書人閱讀 51,698評(píng)論 1 305
  • 那天地消,我揣著相機(jī)與錄音炉峰,去河邊找鬼。 笑死脉执,一個(gè)胖子當(dāng)著我的面吹牛疼阔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼婆廊,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼迅细!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起淘邻,我...
    開封第一講書人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤茵典,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后宾舅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體统阿,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年筹我,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扶平。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蔬蕊,死狀恐怖结澄,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情岸夯,我是刑警寧澤麻献,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站猜扮,受9級(jí)特大地震影響赎瑰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜破镰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一餐曼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鲜漩,春花似錦源譬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至喉祭,卻和暖如春养渴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泛烙。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工理卑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蔽氨。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓藐唠,卻偏偏與公主長(zhǎng)得像帆疟,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子宇立,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • apply、call润脸、bind apply call借用他人的函數(shù)方法 網(wǎng)上文章雖多染厅,大多復(fù)制粘貼,且晦澀難懂津函,我...
    sponing閱讀 2,002評(píng)論 2 32
  • 作為一名差生肖粮,我一直沒有系統(tǒng)的了解js的apply(),call()尔苦,bind()方法涩馆。之前也找到一些網(wǎng)文介紹這幾...
    一個(gè)廢人閱讀 347評(píng)論 1 3
  • 目錄 學(xué)習(xí)來源 過去的困惑 格式 相同之處 不同 小小知識(shí)點(diǎn) 1. 學(xué)習(xí)來源 推薦一篇教程稠项,用例豐富涯雅、描述準(zhǔn)確、...
    ccminn閱讀 648評(píng)論 0 1
  • 第一次購(gòu)買kindle展运,聽朋友介紹說閱讀體驗(yàn)不錯(cuò)活逆,自己想親自嘗試。優(yōu)點(diǎn)就暫且不說拗胜,下面說說個(gè)人認(rèn)為的缺點(diǎn)蔗候。 1.翻...
    捷后愚生閱讀 596評(píng)論 4 4
  • 今天有點(diǎn)冷 晨今早起的比較早 叫一聲立馬起床了,乖乖的洗臉?biāo)⒀拦∪恚栽顼埿庖#尠职炙腿W(xué)校,下午放學(xué)回家后勘畔,乖乖的自己...
    李云一閱讀 53評(píng)論 0 2