Function.prototype.bind() 方法
参考
1.序言
在 深入理解JS:执行上下文中的this(一) 中,我们主要深入分析全局环境和函数环境中函数调用的 this,还留下 bind 方法以及箭头函数的 this 尚未分析,因此我们将在这篇文章进行讲解。
2.Function.prototype.bind() 方法
bind() 方法将会创建返回一个新的函数。在 bind() 被调用时,这个新函数的 this 将被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
ES5 引入了 方法来设置函数的 this 值,而不用考虑函数如何被调用的。
这里给出一种 bind() 的实现算法:
var slice = Array.prototype.slice; Function.prototype.bind = function() { var thatFunc = this, thatArg = arguments[0]; var args = slice.call(arguments, 1); if (typeof thatFunc !== 'function') { throw new TypeError('Function.prototype.bind called on incompatible ' + thatFunc); } return function(){ var funcArgs = args.concat(slice.call(arguments)) return thatFunc.apply(thatArg, funcArgs); }; };注:上述代码并没有完全按照ES5规范实现,只是作为一种实现参考,更加完善的解决方案可以参考 function-bind
但不论哪种实现,其实质上都是通过类似 Function.prototype.apply(thisArg, argArray) 来是实现指定调用函数 this 的。
3.箭头函数
箭头函数表达式的语法比更简洁,并且没有自己的 this,arguments,super 或 new.target。它很适合用作匿名函数,并且不能用作构造函数(为什么呢?详情点击查看)。
ES6 引入了支持 this 词法解析的(它在闭合的执行环境内设置 this 的值)。
如何理解箭头函数在闭合的执行环境内设置 this 的值?
简单理解,箭头函数不会创建自己的 this,它的 this 与封闭词法环境的 this 保持一致,即如果箭头函数在全局环境中,那么它的 this 就指向全局对象,如果箭头函数在某一个函数中,那么它的 this 就指向所在函数的 this。
我们来看几个示例:
(1)全局环境
var global = this var foo = () => { return this } var value = 1 var bar = { value: 2, getValueByArrowFunc: () => { return this.value }, getValue: function (){ return this.value }, } console.log(foo() === global) // true // 箭头函数 this => global console.log(bar.getValueByArrowFunc()) // 1 // 普通函数 this => bar console.log(bar.getValue()) // 2(2)函数环境
ES6的语法:
function foo() { this.value = 1 // 箭头函数表达式 var arr = () => { console.log(this.value) } arr() }转化为ES5:
function foo() { var _this = this; this.value = 1; // 转化为普通函数表达式 var arr = function arr() { console.log(_this.value); }; arr(); }对比转化前后的代码可以看出:箭头函数会转化为一个普通函数,通过一个临时变量 _this 来传递,它之前的 this 就是所在函数的 this
(3)call() 、 apply() 或 bind() 方法
var global = this var foo = { bar: () => { return this } } var obj = { value : 1 } console.log(foo.bar() === global) // true console.log(foo.bar.call(obj) === global) // true console.log(foo.bar.apply(obj) === global) // true var bind = foo.bar.bind(obj) console.log(bind() === global) // true由于箭头函数不会创建自己的 this,那么通过 call() 、 apply() 或 bind() 方法调用一个箭头函数时,只能传递参数,第一个参数会被忽略。
4.参考
ECMAScript5.1中文版
ES6 - Arrow functions