Javascript “this”在默认参数中如何工作?
所以。。。ES6ª(几小时前刚刚标准化)为函数提供了与PHP、Python等中的函数类似的默认参数。我可以这样做:Javascript “this”在默认参数中如何工作?,javascript,ecmascript-6,default-parameters,Javascript,Ecmascript 6,Default Parameters,所以。。。ES6ª(几小时前刚刚标准化)为函数提供了与PHP、Python等中的函数类似的默认参数。我可以这样做: function foo (bar = 'dum') { return bar; } foo(1); // 1 foo(); // 'dum' foo(undefined); // 'dum' MDN表示参数的默认值在调用时计算。这意味着每次我调用函数时,表达式'dum'都会再次求值(除非实现执行了一些我们不关心的奇怪优化) 我的问题是,这个是如何发挥作用的 let x
function foo (bar = 'dum') {
return bar;
}
foo(1); // 1
foo(); // 'dum'
foo(undefined); // 'dum'
MDN表示参数的默认值在调用时计算。这意味着每次我调用函数时,表达式'dum'
都会再次求值(除非实现执行了一些我们不关心的奇怪优化)
我的问题是,这个
是如何发挥作用的
let x = {
foo (bar = this.foo) {
return bar;
}
}
let y = {
z: x.foo
}
x.foo() === y.z(); // what?
babel transpiler当前将其评估为false
,但我不明白。如果在通话时确实对其进行了评估,那么:
let x = 'x from global';
function bar (thing = x) {
return thing;
}
function foo () {
let x = 'x from foo';
return bar();
}
bar() === foo(); // what?
function bar (thing = x) {}
{
let x = 'x from foo';
return bar();
}
babel transpiler目前将其评估为true
,但我不明白。在foo
内部调用时,为什么bar
不从foo
获取x
1-是的,我知道是ES2015。2-
3- 当他们说“在调用时进行评估”时,我认为他们指的是一个按名称调用的表达式。下面是babel如何输出第三个示例:
'use strict';
var x = 'x from global';
function bar() {
var thing = arguments[0] === undefined ? x : arguments[0];
return thing;
}
function foo() {
var x = 'x from foo';
return bar();
}
bar() === foo(); // what?
由于var x
是在bar
的词法范围内从全局范围继承的,这就是它的使用范围
现在,考虑以下内容:
let i = 0;
function id() {
return i++;
}
function bar (thing = id()) {
return thing;
}
console.info(bar() === bar()); // false
它可以传送到
"use strict";
var i = 0;
function id() {
return i++;
}
function bar() {
var thing = arguments[0] === undefined ? id() : arguments[0];
return thing;
}
console.info(bar() === bar()); // false
注意这里,id
是如何在函数内部调用的,而不是在定义函数时被缓存和记忆的,因此按名称调用而不是按值调用
因此,在第二个示例中,该行为实际上是正确的。没有y.foo
,由于this
在Javascript中是动态范围(即,它根据给定函数调用的接收者而变化),当y.z()
查找this.foo
时,它将在y
中查找,因此y.z()
将返回未定义的,而x.foo()
将只返回foo
函数本身
如果确实要绑定到接收器,则可以在分配时将foo
绑定到x
。那么它应该像预期的那样工作
抱歉,如果有任何不清楚的地方;请在评论中告诉我,我很乐意澄清!:)
我的问题是,这个
是如何发挥作用的?我不明白。他们真的在通话时被评估了吗
是,参数初始值设定项在调用时进行计算,但基本步骤如下:
在堆栈上建立一个属性,
在被调用函数的“闭包范围”中使用
如果有必要,可以
:
将创建参数名称的可变绑定
如有必要,将创建一个绑定的参数对象
参数列表中的参数(包括所有分解结构等)
在这个过程中,
如果涉及任何闭包,将插入一个新环境
为函数体中声明的变量创建可变绑定(如果尚未通过参数名完成),并使用undefined
为函数体中的let
和const
变量创建绑定
函数的绑定(来自主体中的函数声明)是使用实例化函数初始化的
最后,这是一个好消息
因此,参数初始化器确实可以访问调用的this
和参数
,以及之前初始化的其他参数,以及它们的“上限”词法范围内的所有内容。它们不受函数体中声明的变量的影响(尽管它们受所有其他参数的影响,即使在它们的时间死区中也是如此)
那么这个呢:
let x = 'x from global';
function bar (thing = x) {
return thing;
}
function foo () {
let x = 'x from foo';
return bar();
}
bar() === foo(); // what?
function bar (thing = x) {}
{
let x = 'x from foo';
return bar();
}
我不明白。为什么调用bar
时不从foo
获取x
内部foo
因为x
是bar
无权访问的局部变量。我们真幸运,他们是!参数初始化器不是在调用站点求值,而是在被调用函数的作用域内求值。在这种情况下,x
标识符被解析为全局x
变量。董事会是否宣布接受ES6最终草案?@斜视规范现场:)您的比较结果基本上是x.foo==y.foo
,这显然是错误的,因为在这两种情况下,您都在调用foo
函数,但在第一种情况下,this==x
,在第二种情况下,this==y
。问题似乎是,为什么本质上是让x={foo(){returnthis;};设y={z:x.foo};y、 foo()==y
。答案是因为y.foo()
与执行y.foo.call(y)
相同。这就是这个
的定义。“由于它在Javascript中是动态范围”,这就是我的问题所在。使用this.something
不应该被特别对待,因为this.something
不是魔法,只有this
是魔法。我将添加一个明确的例子来澄清这个问题,谢谢你的回答!如果有人关心的话,我们在《如果你想了解更多》中对此进行了进一步讨论:)