摘要:語法是這樣樣子的當(dāng)綁定函數(shù)被調(diào)用時,該參數(shù)會作為原函數(shù)運行時的指向。當(dāng)使用對象的方法時,需要引用對象,你可能需要顯式地把綁定到回調(diào)函數(shù)以便繼續(xù)使用對象。中方法簡介備忘中的,以及中方法的使用與實現(xiàn)
不看不知道,一看嚇一跳,已經(jīng)整整一個月沒有更新 underscore 源碼解讀系列文章了。前面我們已經(jīng)完成了 Object ,Array,Collection 上的擴展方法的源碼剖析,本文開始來解讀 Function 上的擴展方法。
完整的 underscore 源碼解讀系列文章請移步 https://github.com/hanzichi/u...,覺得還闊以的話,給個 star 鼓勵下樓主唄 ^_^
bind 簡介Ok,今天要講的正是 bind。關(guān)于 bind,可以先移步樓主以前寫的文章 ECMAScript 5(ES5) 中 bind 方法簡介備忘,有個基本的概念。
bind() 方法會創(chuàng)建一個新函數(shù),當(dāng)這個新函數(shù)被調(diào)用時,它的 this 值是傳遞給 bind() 的第一個參數(shù), 它的參數(shù)是 bind() 的其他參數(shù)和其原本的參數(shù)。
語法是這樣樣子的:
fun.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg 當(dāng)綁定函數(shù)被調(diào)用時,該參數(shù)會作為原函數(shù)運行時的 this 指向。當(dāng)使用 new 操作符調(diào)用綁定函數(shù)時,該參數(shù)無效。
arg1, arg2, ... (可選)當(dāng)綁定函數(shù)被調(diào)用時,這些參數(shù)加上綁定函數(shù)本身的參數(shù)會按照順序作為原函數(shù)運行時的參數(shù)。
參數(shù)bind 的第一個參數(shù)會作為原函數(shù)運行時的 this 指向,不多說;而第二個開始的參數(shù)是可選的,當(dāng)綁定函數(shù)被調(diào)用時,這些參數(shù)加上綁定函數(shù)本身的參數(shù)會按照順序作為原函數(shù)運行時的參數(shù)。怎么理解?
function fn(a, b, c) { return a + b + c; } var _fn = fn.bind(null, 10); var ans = _fn(20, 30); // 60
fn 函數(shù)需要三個參數(shù),_fn 函數(shù)將 10 作為默認的第一個參數(shù),所以只需要傳入兩個參數(shù)即可,如果你不小心傳入了三個參數(shù),放心,也只會取前兩個。
function fn(a, b, c) { return a + b + c; } var _fn = fn.bind(null, 10); var ans = _fn(20, 30, 40); // 60
這有啥用呢?如果某些函數(shù),前幾個參數(shù)已經(jīng) “內(nèi)定” 了,我們便可以用 bind 返回一個新的函數(shù)。也就是說,bind() 能使一個函數(shù)擁有預(yù)設(shè)的初始參數(shù)。這些參數(shù)(如果有的話)作為 bind() 的第二個參數(shù)跟在 this 后面,之后它們會被插入到目標(biāo)函數(shù)的參數(shù)列表的開始位置,傳遞給綁定函數(shù)的參數(shù)會跟在它們的后面。
function list() { return Array.prototype.slice.call(arguments); } var list1 = list(1, 2, 3); // [1, 2, 3] // Create a function with a preset leading argument var leadingThirtysevenList = list.bind(undefined, 37); var list2 = leadingThirtysevenList(); // [37] var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]new
使用 bind 返回的結(jié)果還是個 function,是個 function 就可以被 new 運算符調(diào)用,那么結(jié)果呢?規(guī)范中說的很清楚了,當(dāng)使用 new 操作符調(diào)用綁定函數(shù)時,bind 的第一個參數(shù)無效。
function Person(name, age) { this.name = name; this.age = age; } var _Person = Person.bind({}); var p = new _Person("hanzichi", 30); // Person {name: "hanzichi", age: 30}
一般我們不會去這么用,但是如果要寫個 bind 的 polyfill(http://caniuse.com/#search=bind),還是需要考慮用 new 調(diào)用的情況。
我們也可以設(shè)置默認值(參考上一小節(jié)),原先提供的那些參數(shù)仍然會被前置到構(gòu)造函數(shù)調(diào)用的前面。
function Person(name, age) { this.name = name; this.age = age; } var _Person = Person.bind(null, "hanzichi"); var p = new _Person(30); // Person {name: "hanzichi", age: 30}配合 setTimeout
什么時候容易丟失 this 指向?恩,setTimeout 是一個場景,很容易把 this 指向 window,當(dāng)然,setInterval 也是一樣。當(dāng)使用對象的方法時,需要 this 引用對象,你可能需要顯式地把 this 綁定到回調(diào)函數(shù)以便繼續(xù)使用對象。
var canvas = { render: function() { this.update(); this.draw(); }, update: function() { // ... }, draw: function() { // ... } }; window.setInterval(canvas.render, 1000 / 60);
用 canvas 寫特效或者做游戲時經(jīng)常會碰到類似的問題。上面的代碼是有問題的,render 方法中的 this 其實被指向了 window!我們可以用 bind,顯式地把 this 綁定到回調(diào)函數(shù)以便繼續(xù)使用該對象。
window.setInterval(canvas.render.bind(canvas), 1000);
類似的情況還有 dom 的事件監(jiān)聽,一不小心可能 this 就被指向了 dom 元素。可以參考下以前做 bigrender 時寫的這部分代碼 https://github.com/hanzichi/h...。
tipbind 還能做一些有意思的事情。
通常來說,將一個類數(shù)組轉(zhuǎn)為數(shù)組,我們會用 slice(ie9- 不支持)。參考 https://github.com/hanzichi/u...
var slice = Array.prototype.slice; // slice.apply(arguments); // slice(arguments, 1);
bind 能讓調(diào)用變的更加簡單。
// same as "slice" in the previous example var unboundSlice = Array.prototype.slice; var slice = Function.prototype.call.bind(unboundSlice); // ... slice(arguments); // slice(arguments, 1);
再舉個類似的例子,比如說我們要添加事件到多個節(jié)點,for 循環(huán)當(dāng)然沒有任何問題,我們還可以 “剽竊” forEach 方法:
Array.prototype.forEach.call(document.querySelectorAll("input[type="button"]"), function(el){ el.addEventListener("click", fn); });
更進一步,我們可以用 bind 將函數(shù)封裝的更好:
var unboundForEach = Array.prototype.forEach , forEach = Function.prototype.call.bind(unboundForEach); forEach(document.querySelectorAll("input[type="button"]"), function (el) { el.addEventListener("click", fn); });
同樣類似的,我們可以將 x.y(z) 變成 y(x,z) 的形式:
var obj = { num: 10, getCount: function() { return this.num; } }; var unboundBind = Function.prototype.bind , bind = Function.prototype.call.bind(unboundBind); var getCount = bind(obj.getCount, obj); console.log(getCount()); // 10
再舉個栗子。每隔一秒在控制臺打印 1-5,看起來是道考察閉包的經(jīng)典題目。
for(var i = 1; i <= 5; i++) { !function(i) { setTimeout(function() { console.log(i); }, i * 1000); }(i); }
ES6 下能用 let:
for(let i = 1; i <= 5; i++) { setTimeout(function() { console.log(i); }, i * 1000); }
也可以用 bind,瞬間逼格提升:
for(var i = 1; i <= 5; i++) { setTimeout(console.log.bind(console, i), i * 1000); }Read more
關(guān)于 bind 的介紹就到這里,下一篇文章將結(jié)合 underscore 來講講如何實現(xiàn)一個 bind 的 polyfill。
Function.prototype.bind()
ECMAScript 5(ES5) 中 bind 方法簡介備忘
Javascript 中的 Bind ,Call 以及 Apply
Javascript 中 bind() 方法的使用與實現(xiàn)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/80084.html
摘要:返回的綁定函數(shù)也能使用操作符創(chuàng)建對象這種行為就像把原函數(shù)當(dāng)成構(gòu)造器。同時,將第一個參數(shù)以外的其他參數(shù),作為提供給原函數(shù)的預(yù)設(shè)參數(shù),這也是基本的顆粒化基礎(chǔ)。 今天想談?wù)勔坏狼岸嗣嬖囶},我做面試官的時候經(jīng)常喜歡用它來考察面試者的基礎(chǔ)是否扎實,以及邏輯、思維能力和臨場表現(xiàn),題目是:模擬實現(xiàn)ES5中原生bind函數(shù)。也許這道題目已經(jīng)不再新鮮,部分讀者也會有思路來解答。社區(qū)上關(guān)于原生bind的研...
摘要:返回的綁定函數(shù)也能使用操作符創(chuàng)建對象這種行為就像把原函數(shù)當(dāng)成構(gòu)造器。同時,將第一個參數(shù)以外的其他參數(shù),作為提供給原函數(shù)的預(yù)設(shè)參數(shù),這也是基本的顆粒化基礎(chǔ)。 今天想談?wù)勔坏狼岸嗣嬖囶},我做面試官的時候經(jīng)常喜歡用它來考察面試者的基礎(chǔ)是否扎實,以及邏輯、思維能力和臨場表現(xiàn),題目是:模擬實現(xiàn)ES5中原生bind函數(shù)。也許這道題目已經(jīng)不再新鮮,部分讀者也會有思路來解答。社區(qū)上關(guān)于原生bind的研...
摘要:返回的綁定函數(shù)也能使用操作符創(chuàng)建對象這種行為就像把原函數(shù)當(dāng)成構(gòu)造器。同時,將第一個參數(shù)以外的其他參數(shù),作為提供給原函數(shù)的預(yù)設(shè)參數(shù),這也是基本的顆粒化基礎(chǔ)。 今天想談?wù)勔坏狼岸嗣嬖囶},我做面試官的時候經(jīng)常喜歡用它來考察面試者的基礎(chǔ)是否扎實,以及邏輯、思維能力和臨場表現(xiàn),題目是:模擬實現(xiàn)ES5中原生bind函數(shù)。也許這道題目已經(jīng)不再新鮮,部分讀者也會有思路來解答。社區(qū)上關(guān)于原生bind的研...
這是理解SOLID原則中,關(guān)于依賴倒置原則如何幫助我們編寫低耦合和可測試代碼的第一篇文章。 寫在前頭 當(dāng)我們在讀書,或者在和一些別的開發(fā)者聊天的時候,可能會談及或者聽到術(shù)語SOILD。在這些討論中,一些人會提及它的重要性,以及一個理想中的系統(tǒng),應(yīng)當(dāng)包含它所包含的5條原則的特性。 我們在每次的工作中,你可能沒有那么多時間思考關(guān)于架構(gòu)這個比較大的概念,或者在有限的時間內(nèi)或督促下,你也沒有辦法實踐一些好...
摘要:探討判斷橫豎屏的最佳實現(xiàn)前端掘金在移動端,判斷橫豎屏的場景并不少見,比如根據(jù)橫豎屏以不同的樣式來適配,抑或是提醒用戶切換為豎屏以保持良好的用戶體驗。 探討判斷橫豎屏的最佳實現(xiàn) - 前端 - 掘金在移動端,判斷橫豎屏的場景并不少見,比如根據(jù)橫豎屏以不同的樣式來適配,抑或是提醒用戶切換為豎屏以保持良好的用戶體驗。 判斷橫豎屏的實現(xiàn)方法多種多樣,本文就此來探討下目前有哪些實現(xiàn)方法以及其中的優(yōu)...
閱讀 2953·2021-09-26 10:18
閱讀 5279·2021-09-22 15:02
閱讀 2796·2019-08-30 15:53
閱讀 1841·2019-08-29 18:41
閱讀 2692·2019-08-27 10:58
閱讀 2623·2019-08-26 13:49
閱讀 2750·2019-08-26 12:17
閱讀 901·2019-08-26 11:49