摘要:昨天被人问到的的作用是什么这个倒还能回答出来,之后返回一个新的函数,这个函数可以保持传递的上下文。没有完全实现规定的。比如规定了的和行为。
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的时候如果依赖于这些,是要注意的。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/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提供了一种更优雅的方...
阅读 656·2021-11-15 11:39
阅读 2891·2021-10-08 10:04
阅读 3254·2019-08-30 10:57
阅读 3017·2019-08-26 13:25
阅读 1899·2019-08-26 12:14
阅读 2627·2019-08-23 15:27
阅读 2991·2019-08-23 15:18
阅读 1768·2019-08-23 14:26