看起来很简单,我想用参数数组调用一个函数。当然,我可以说func.apply(this, ['some', 'arguments']);
,但这会改变this
inside的价值func
。知道如何在不改变它的情况下做到这一点吗?
5 回答
你不能,因为this
JavaScript 的工作方式。继续阅读:
通过 ECMAScript 规范的“进入执行上下文”部分:当你调用一个函数时,它的值this
取决于它剩下的(称为激活对象)。让我们创建一个名为 steve 的函数,并将他放在一个对象中:
function steve(){}
var obj = { method: steve };
…当我们称 steve as 时obj.method()
,他的this
is obj
,因为obj
是激活对象。
棘手的情况是函数调用的左侧没有任何内容:
steve(); // Who am I ?!
函数调用的左边没有任何东西——实际上,它是——所以null
值this
被设置为全局对象的默认值(window
在 Web 浏览器中,global
在 Node.js 中等)。
因此,实际上,this
您每次调用它时都在设置一个函数。
PS callsteve.apply(null, [])
相当于 call steve()
。
请注意,在 ES6 中,您还可以编写:
func(...someArray)
这里this
变成了Window
inside func
,没有用。但是如果你写:
obj.func(...someArray)
this
在里面func
会obj
。
这可能是我 5 年前一直在寻找的功能,但那是 5 年前的事了,所以谁记得 :)
调用函数时的值this
并不神秘,具体取决于“通常”的调用方式(不带call
or apply
):
func(); // `this` is the global object, or undefined in ES5 strict mode
obj.func(); // `this` is `obj`
因此,为避免“更改” 的值this
,只需将正确的值传递给apply
,具体取决于您如何“正常”调用它:
func.apply(undefined, []); // global object, or undefined in ES5 strict mode
obj.func.apply(obj, []);
如果您单独调用一个函数,请传递null
.
func.apply(null, ['some', 'arguments']);
如果您正在调用作为对象方法的函数,请传递该对象。
var arr = [];
arr.push.apply(arr, ['some', 'arguments']);
为了匹配这是如何工作的。
你想要的没有多大意义。
在 ecmascript 标准this
中是这样定义的:
11.1.1 this 关键字 this 关键字计算为当前执行上下文的 ThisBinding 的值。
函数执行上下文的 thisBinding 解析是这样指定的:
10.4.3 进入函数代码 当控制进入函数对象F中包含的函数代码的执行上下文时,调用者提供thisArg和调用者提供argumentsList时,执行以下步骤:
- 如果函数代码是严格代码,则将 ThisBinding 设置为 thisArg。
- 否则,如果 thisArg 为 null 或未定义,则将 ThisBinding 设置为全局对象。
- 否则,如果 Type(thisArg) 不是 Object,则将 ThisBinding 设置为 ToObject(thisArg)。
- 否则将 ThisBinding 设置为 thisArg。
- 让 localEnv 成为调用 NewDeclarativeEnvironment 的结果,并将 F 的 [[Scope]] 内部属性的值作为参数传递。
- 将 LexicalEnvironment 设置为 localEnv。
- 将变量环境设置为 localEnv。
- 令 code 为 F 的 [[Code]] 内部属性的值。
- 使用功能代码代码和argumentList 执行声明绑定实例化,如10.5 中所述。
换句话说:要么你指定它,要么它被自动设置为全局对象。它永远不会从其父范围继承 this 绑定,因此将父范围的 thisBindiong 赋予其子级的唯一方法是
- 将其保存在父范围内的局部变量中,例如 var
self = this
- 像您在问题中提供的代码一样,通过 call/apply 注入它。