原文: understanding-javascript-function-invocation-and-this
核心原语
- 创建一个参数列表
argList
,包含了所有传入的参数
- 第一个参数是
thisValue
- 调用函数时把
this
设置为 thisValue
,并传入 argList
例如:
函数的简单调用
像上面这样每次都使用 call
来调用函数有点烦人,JavaScript允许我们直接使用括号 hello("world")
这样的语法。
但这个行为在ECMAScript 5的严格模式中有所不同[2]:
The short version is: a function invocation like fn(...args)
is the same as fn.call(window [ES5-strict: undefined], ...args)
.
[2] 实际上是所有情况下都会传入 undefined
,但是在非严格模式时,函数会把这个值改为 thisValue
。
成员函数
上面的 hello
是独立函数,再来看下面的动态添加函数到 person
对象上。
这个时候 hello
的 this
会根据调用方法的不同而变化。
使用 Function.prototype.bind
这里我们调用的 boundHello("world");
会被 脱糖 成 boundHello.call(window, "world")
(可以看上一个例子),但是我们使用 call 方法重新将 this 修改成了person,所以 console 中会打印出 Brendan Eich says hello world
。
我们可以让这个技巧更加通用:
让我们来理解这段代码,
- arguments 是一个类似 Array(但不是 Array)的参数列表,包含所有传入的参数。
- apply 和 call 基本相同,他可以接受参数列表(Array-like)而不需要一个一个列出来
- bind 方法返回一个函数,这个 boundHello 被调用时会设置 this 并使用传入的参数
因为这是一个有点常见的习惯用法,所以 ES5 引入了 bind
在所有的 Function
对象上,来实现下面的用法
例如: