为什么赋值运算符返回值而不是引用?

scr*_*key 11 javascript

我在这个网站上看到了下面的例子,并且认为两个答案都是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以下三种方式之一设置值:

  1. 使用属性访问符号(点分表示法obj.foo())或括号表示法(obj["foo"]())来通过对象属性调用该函数.
  2. 使用with语句通过对象属性调用函数(实际上只是#1的变体,但值得单独调用,特别是因为源代码中不明显)
  3. 使用函数实例的applycall功能.

在上面的示例中,您没有执行任何这些操作,因此您最终使用默认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处理不起作用.


CMS*_*CMS 8

您应该了解内部参考类型的工作原理.

注意:这不是语言数据类型,是处理引用的内部机制.

引用由两个元素组成,即基础对象属性名称.

在您的示例中,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的伪代码,该内部方法返回一个,其并没有真正有一个基础对象.