深入理解JS:执行上下文中的this(二)

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

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsszpf.html