洽談javascript裡的bind()函數
理解javascript 裡的bind() 函數
#分享:
bind() 方法會建立一個新函數,當這個新函數被呼叫時,它的this值是傳遞給bind() 的第一個參數, 它的參數是bind()的其他參數和其原本的參數。
語法是這樣樣子的:
fun.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg 當綁定函數被呼叫時,該參數會作為原始函數運行時的 this 指向。當使用 new 操作符呼叫綁定函數時,此參數無效。
arg1, arg2, … (可選)當綁定函數被呼叫時,這些參數加上綁定函數本身的參數會按照順序作為原函數運行時的參數。
參數
bind的第一個參數會作為原始函數運行時的this指向,不多說;而第二個開始的參數是可選的,當綁定函數被呼叫時,這些參數加上綁定函數本身的參數會依照順序作為原函數執行時的參數。怎麼理解?
function fn(a, b, c) { return a + b + c; } var _fn = fn.bind(null, 10); var ans = _fn(20, 30); // 60
fn 函數需要三個參數,_fn 函數將10 作為預設的第一個參數,所以只需要傳入兩個參數即可,如果你不小心傳入了三個參數,放心,也只會取前兩個。
function fn(a, b, c) { return a + b + c; } var _fn = fn.bind(null, 10); var ans = _fn(20, 30, 40); // 60
這有啥用呢?如果某些函數,前幾個參數已經 「內定」 了,我們便可以用 bind 傳回一個新的函數。也就是說,bind() 能使一個函數擁有預設的初始參數。這些參數(如果有的話)作為bind() 的第二個參數跟在this 後面,之後它們會被插入到目標函數的參數列表的開始位置,傳遞給綁定函數的參數會跟在它們的後面。
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 傳回的結果還是個 function,是個 function 就可以被 new 運算子調用,那麼結果呢?規範中說的很清楚了,當使用 new 運算子呼叫綁定函數時,bind 的第一個參數無效。
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 呼叫的情況。
我們也可以設定預設值(參考上一小節),原先提供的那些參數仍然會被前置到建構函式呼叫的前面。
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,當然,setInterval 也是一樣。當使用物件的方法時,需要 this 引用對象,你可能需要明確地把 this 綁定到回呼函數以便繼續使用對象。
var canvas = { render: function() { this.update(); this.draw(); }, update: function() { // ... }, draw: function() { // ... } }; window.setInterval(canvas.render, 1000 / 60);
用 canvas 寫特效或做遊戲時常常會碰到類似的問題。上面的程式碼是有問題的,render 方法中的 this 其實被指向了 window!我們可以用 bind, 明確地把 this 綁定到回呼函數以便繼續使用該物件。
window.setInterval(canvas.render.bind(canvas), 1000);
類似的情況還有 dom 的事件監聽,一不小心可能 this 就被指向了 dom 元素。可以參考下以前做 bigrender 時寫的這部分程式碼 https://github.com/hanzichi/hanzichi.github.io/blob/master/2016/bigrender/js/bigrender.js#L179-L184 。
tip
bind還能做一些有趣的事情。
通常來說,將一個類別數組轉為數組,我們會用 slice(ie9- 不支援)。參考#14
var slice = Array.prototype.slice; // slice.apply(arguments); // slice(arguments, 1); bind 能让调用变的更加简单。 // same as "slice" in the previous example var unboundSlice = Array.prototype.slice; var slice = Function.prototype.call.bind(unboundSlice); // ... slice(arguments); // slice(arguments, 1);
再舉個類似的例子,比如說我們要新增事件到多個節點,for 迴圈當然沒有任何問題,我們還可以「剽竊」 forEach 方法:
Array.prototype.forEach.call(document.querySelectorAll('input[type="button"]'), function(el){ el.addEventListener('click', fn); });
更進一步,我們可以用bind 將函數封裝的更好:
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,看起來是道考察閉包的經典題目。
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); }
推薦教學:《js基礎教學 》
以上是洽談javascript裡的bind()函數的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數
