摘要:昨天被人問到的的作用是什么這個倒還能回答出來,之后返回一個新的函數(shù),這個函數(shù)可以保持傳遞的上下文。沒有完全實現(xiàn)規(guī)定的。比如規(guī)定了的和行為。
https://friskfly.github.io/2016/03/24/about-function-bind-in-js/
昨天被人問到j(luò)s的bind的作用是什么?
這個倒還能回答出來,bind 之后返回一個新的函數(shù),這個函數(shù)可以保持傳遞的this上下文。
接著又問了,那么bind兩次不同的上下文會怎樣?
這個一下子就蒙了,因為平時也沒這么用過,于是開始查一下資料。
首先在瀏覽器中測試一下。
function test(){ console.log(this.a) } var bind1 = test.bind({a:1}) //第一次 bind var bind2 = bind1.bind({a:2}) // 第二次 bind bind1() bind2()
結(jié)果如下
1 1
可以看到第二次bind并沒有能再改變this的值。
查一下MDN,F(xiàn)unction.prototype.bind() , 并沒有解釋bind兩次會怎樣。 但是他提供了一個Polyfill,可以了解下bind的實現(xiàn)。
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的實現(xiàn)是oThis做為參數(shù)傳進來,返回一個新的函數(shù),這個時候函數(shù)是個閉包,仍然可以訪問oThis變量,然后調(diào)用call/apply來實現(xiàn)指定的上下文。 這種情況下,如果bind兩次,相當(dāng)于閉包套閉包,不管套幾層,值都是第一次保存的this值。 即上面polyfill的 oThis 變量。
光看polyfill是不夠了,因為并不知道polyfill實現(xiàn)是不是標準。所以還是要看下規(guī)范。這里我們參考下 ES2015文檔
可以直接看到 19.2.3.2 節(jié) 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. 如果調(diào)用bind的是一個箭頭函數(shù)或者是已經(jīng)bind過的函數(shù)(bound function),那么再次bind是不會起作用的。 可以看到規(guī)范已經(jīng)定義了這樣的行為產(chǎn)生的結(jié)果,我們可以直接記住這個結(jié)論。
但是這里值得注意的是,我們看到規(guī)范定義的bind操作 和 MDN 上提供的polyfill并不一致。polyfill沒有完全實現(xiàn)ES2015規(guī)定的bind。
比如ES2015 規(guī)定了 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.
這里會規(guī)定bound function 的 length 屬性,應(yīng)該和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").
這里規(guī)定bound function 的name 應(yīng)該走 SetFunctionName 方法,而這里SetFunctionName之后的返回值應(yīng)該是 bound字符串 + 空格 + 原先函數(shù)的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)
結(jié)果應(yīng)該是
bound a
而 MDN 的 polyfill 是沒有實現(xiàn)這些細節(jié)的,所以用bind的時候如果依賴于這些,是要注意的。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/79032.html
摘要:同樣會綁定,也會穿參數(shù),但是不會立即執(zhí)行我是內(nèi)部的我是內(nèi)部的類似數(shù)組,但不是真的數(shù)組,好吧,就把它當(dāng)成數(shù)組吧,它同樣擁有而且也可以通過下標訪問關(guān)于下面的官方語言警告在嚴格模式下,第版禁止使用。關(guān)于這3個貨,網(wǎng)上有很多文章介紹,我這邊還是記錄下并加上自己的理解,還有arguments函數(shù)內(nèi)置對象順便也記錄下: 簡單的說apply和call 會綁定第一個參數(shù)的作用域給調(diào)用函數(shù)對象實例,并會執(zhí)行...
摘要:在面向?qū)ο蟮闹?,我們了解到在中,一切都是對象。到目前為止,我們已將函?shù)視為由名稱可選,也可以是匿名函數(shù)組成的對象及其在調(diào)用時執(zhí)行的代碼。這意味著,我們可以調(diào)用任何函數(shù),并在調(diào)用函數(shù)中明確指定。和用于完全相同的目的。 What s this 在面向?qū)ο蟮腏S中,我們了解到在JS中,一切都是對象。因為一切都是對象,我們開始明白我們可以為函數(shù)設(shè)置和訪問其他屬性。而this提供了一種更優(yōu)雅的方...
摘要:在面向?qū)ο蟮闹?,我們了解到在中,一切都是對象。到目前為止,我們已將函?shù)視為由名稱可選,也可以是匿名函數(shù)組成的對象及其在調(diào)用時執(zhí)行的代碼。這意味著,我們可以調(diào)用任何函數(shù),并在調(diào)用函數(shù)中明確指定。和用于完全相同的目的。 What s this 在面向?qū)ο蟮腏S中,我們了解到在JS中,一切都是對象。因為一切都是對象,我們開始明白我們可以為函數(shù)設(shè)置和訪問其他屬性。而this提供了一種更優(yōu)雅的方...
摘要:在面向?qū)ο蟮闹校覀兞私獾皆谥?,一切都是對象。到目前為止,我們已將函?shù)視為由名稱可選,也可以是匿名函數(shù)組成的對象及其在調(diào)用時執(zhí)行的代碼。這意味著,我們可以調(diào)用任何函數(shù),并在調(diào)用函數(shù)中明確指定。和用于完全相同的目的。 What s this 在面向?qū)ο蟮腏S中,我們了解到在JS中,一切都是對象。因為一切都是對象,我們開始明白我們可以為函數(shù)設(shè)置和訪問其他屬性。而this提供了一種更優(yōu)雅的方...
閱讀 664·2021-11-15 11:39
閱讀 2901·2021-10-08 10:04
閱讀 3265·2019-08-30 10:57
閱讀 3025·2019-08-26 13:25
閱讀 1908·2019-08-26 12:14
閱讀 2636·2019-08-23 15:27
閱讀 2996·2019-08-23 15:18
閱讀 1777·2019-08-23 14:26