摘要:昨天被人問到的的作用是什么這個倒還能回答出來,之后返回一個新的函數,這個函數可以保持傳遞的上下文。沒有完全實現規定的。比如規定了的和行為。
https://friskfly.github.io/2016/03/24/about-function-bind-in-js/
昨天被人問到js的bind的作用是什么?
這個倒還能回答出來,bind 之后返回一個新的函數,這個函數可以保持傳遞的this上下文。
接著又問了,那么bind兩次不同的上下文會怎樣?
這個一下子就蒙了,因為平時也沒這么用過,于是開始查一下資料。
首先在瀏覽器中測試一下。
function test(){ console.log(this.a) } var bind1 = test.bind({a:1}) //第一次 bind var bind2 = bind1.bind({a:2}) // 第二次 bind bind1() bind2()
結果如下
1 1
可以看到第二次bind并沒有能再改變this的值。
查一下MDN,Function.prototype.bind() , 并沒有解釋bind兩次會怎樣。 但是他提供了一個Polyfill,可以了解下bind的實現。
if (!Function.prototype.bind) { Function.prototype.bind = function(oThis) { if (typeof this !== "function") { // closest thing possible to the ECMAScript 5 // internal IsCallable function throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function() {}, fBound = function() { return fToBind.apply(this instanceof fNOP ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); }; if (this.prototype) { // Function.prototype doesn"t have a prototype property fNOP.prototype = this.prototype; } fBound.prototype = new fNOP(); return fBound; }; }
可以看到MDN提供的polyfill的實現是oThis做為參數傳進來,返回一個新的函數,這個時候函數是個閉包,仍然可以訪問oThis變量,然后調用call/apply來實現指定的上下文。 這種情況下,如果bind兩次,相當于閉包套閉包,不管套幾層,值都是第一次保存的this值。 即上面polyfill的 oThis 變量。
光看polyfill是不夠了,因為并不知道polyfill實現是不是標準。所以還是要看下規范。這里我們參考下 ES2015文檔
可以直接看到 19.2.3.2 節 NOTE 2,If Target is an arrow function or a bound function then the thisArg passed to this method will not be used by subsequent calls to F. 如果調用bind的是一個箭頭函數或者是已經bind過的函數(bound function),那么再次bind是不會起作用的。 可以看到規范已經定義了這樣的行為產生的結果,我們可以直接記住這個結論。
但是這里值得注意的是,我們看到規范定義的bind操作 和 MDN 上提供的polyfill并不一致。polyfill沒有完全實現ES2015規定的bind。
比如ES2015 規定了 bound function 的length 和 name 行為。
Let targetHasLength be HasOwnProperty(Target, "length"). ReturnIfAbrupt(targetHasLength). If targetHasLength is true, then Let targetLen be Get(Target, "length"). ReturnIfAbrupt(targetLen). If Type(targetLen) is not Number, let L be 0. Else, Let targetLen be ToInteger(targetLen). Let L be the larger of 0 and the result of targetLen minus the number of elements of args. Else let L be 0.
這里會規定bound function 的 length 屬性,應該和bind之前的length一致。
再看name 的行為
Let targetName be Get(Target, "name"). ReturnIfAbrupt(targetName). If Type(targetName) is not String, let targetName be the empty string. Perform SetFunctionName(F, targetName, "bound").
這里規定bound function 的name 應該走 SetFunctionName 方法,而這里SetFunctionName之后的返回值應該是 bound字符串 + 空格 + 原先函數的name
......忽略了一些描述 prefix即bound 字符串 If prefix was passed, then Let name be the concatenation of prefix, code unit 0x0020 (SPACE), and name.
即
function a(){} var b = a.bind() console.log(b.name)
結果應該是
bound a
而 MDN 的 polyfill 是沒有實現這些細節的,所以用bind的時候如果依賴于這些,是要注意的。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79032.html
摘要:同樣會綁定,也會穿參數,但是不會立即執行我是內部的我是內部的類似數組,但不是真的數組,好吧,就把它當成數組吧,它同樣擁有而且也可以通過下標訪問關于下面的官方語言警告在嚴格模式下,第版禁止使用。關于這3個貨,網上有很多文章介紹,我這邊還是記錄下并加上自己的理解,還有arguments函數內置對象順便也記錄下: 簡單的說apply和call 會綁定第一個參數的作用域給調用函數對象實例,并會執行...
摘要:在面向對象的中,我們了解到在中,一切都是對象。到目前為止,我們已將函數視為由名稱可選,也可以是匿名函數組成的對象及其在調用時執行的代碼。這意味著,我們可以調用任何函數,并在調用函數中明確指定。和用于完全相同的目的。 What s this 在面向對象的JS中,我們了解到在JS中,一切都是對象。因為一切都是對象,我們開始明白我們可以為函數設置和訪問其他屬性。而this提供了一種更優雅的方...
摘要:在面向對象的中,我們了解到在中,一切都是對象。到目前為止,我們已將函數視為由名稱可選,也可以是匿名函數組成的對象及其在調用時執行的代碼。這意味著,我們可以調用任何函數,并在調用函數中明確指定。和用于完全相同的目的。 What s this 在面向對象的JS中,我們了解到在JS中,一切都是對象。因為一切都是對象,我們開始明白我們可以為函數設置和訪問其他屬性。而this提供了一種更優雅的方...
摘要:在面向對象的中,我們了解到在中,一切都是對象。到目前為止,我們已將函數視為由名稱可選,也可以是匿名函數組成的對象及其在調用時執行的代碼。這意味著,我們可以調用任何函數,并在調用函數中明確指定。和用于完全相同的目的。 What s this 在面向對象的JS中,我們了解到在JS中,一切都是對象。因為一切都是對象,我們開始明白我們可以為函數設置和訪問其他屬性。而this提供了一種更優雅的方...
閱讀 654·2021-11-15 11:39
閱讀 2890·2021-10-08 10:04
閱讀 3252·2019-08-30 10:57
閱讀 3014·2019-08-26 13:25
閱讀 1896·2019-08-26 12:14
閱讀 2626·2019-08-23 15:27
閱讀 2988·2019-08-23 15:18
閱讀 1766·2019-08-23 14:26