我在这个网站上看到了下面的例子,并且认为两个答案都是20而不是返回的10.他写道,逗号和赋值都返回一个值,而不是引用.我不太明白这意味着什么.
我理解它与将变量传递给函数或方法有关,即原始类型是通过值传递的,而对象是通过引用传递的,但我不确定它在这种情况下是如何应用的.
我也理解上下文和'this'的值(在stackoverflow的帮助之后),但我认为在这两种情况下我仍然会调用它作为方法,foo.bar()这意味着foo是上下文但它似乎都导致函数调用bar().
为什么会这样,这一切意味着什么?
var x = 10;
var foo = {
x: 20,
bar: function () {return this.x;}
};
(foo.bar = foo.bar)();//returns 10
(foo.bar, foo.bar)();//returns 10
Run Code Online (Sandbox Code Playgroud)
T.J*_*der 12
它与值与引用无关,它与this值(如您所怀疑的)有关.在JavaScript中,this设置完全由函数是如何调用,而不是在那里的定义.您可以通过this以下三种方式之一设置值:
obj.foo())或括号表示法(obj["foo"]())来通过对象属性调用该函数.with语句通过对象属性调用函数(实际上只是#1的变体,但值得单独调用,特别是因为源代码中不明显)apply或call功能.在上面的示例中,您没有执行任何这些操作,因此您最终使用默认this值(全局对象)调用该函数,因此x来自那里而不是来自您的foo对象.这是另一种思考代码正在做什么的方法:
var f = foo.bar; // Not calling it, getting a reference to it
f(); // Calls the function with `this` referencing the global object
Run Code Online (Sandbox Code Playgroud)
如果您不直接使用属性来实际进行调用(而是检索属性的值,然后使用该属性进行调用),则this处理不起作用.
您应该了解内部参考类型的工作原理.
注意:这不是语言数据类型,是处理引用的内部机制.
引用由两个元素组成,即基础对象和属性名称.
在您的示例中,foo.bar引用如下所示.
// pseudo-code
foo.bar = {
baseObject: foo,
propertyName: 'bar'
}
Run Code Online (Sandbox Code Playgroud)
两者中,逗号运算符和一个简单的赋值,依靠获取属性名的值,即会导致丢失基础对象,由于单个值被返回(这是通过内部由GetValue操作).
这是内部GetValue操作的工作方式:
// pseudo-code
GetValue(V) :
if (Type(V) != Reference) return V;
baseObject = GetBase(V); // in your example foo
if (baseObject === null) throw ReferenceError;
return baseObject.[[Get]](GetPropertyName(V));
// equivalent to baseObject[v.PropertyName];
Run Code Online (Sandbox Code Playgroud)
如您所见,返回一个值,因此原始引用将丢失.
编辑:理解为什么(foo.bar = foo.bar)();不等同foo.bar();于简单赋值运算符的关键,让我们看看算法:
11.13.1 Simple Assignment (`=`)
The production `AssignmentExpression` :
`LeftHandSideExpression` = `AssignmentExpression`
is evaluated as follows:
1. Evaluate LeftHandSideExpression.
2. Evaluate AssignmentExpression.
3.Call GetValue(Result(2)).
4.Call PutValue(Result(1), Result(3)).
5.Return Result(3).
基本上,当你进行(foo.bar = foo.bar)实际的赋值(步骤4)没有任何效果时,因为 PutValue只获取引用的值并将它放回到同一个基础对象.
关键是,赋值运算符返回(步骤5)在所获得的值.步骤3和我在以前所说GetValue的伪代码,该内部方法返回一个值,其并没有真正有一个基础对象.