繁体   English   中英

ECMAScript 规范:变量赋值

[英]ECMAScript specification: Variable Assignment

我听过多种解释 ECMAScript 规范中赋值背后的想法是什么。 但是 EMCAScript 规范实际适用于哪一个? 我们来看一个简单的实际例子:

  1. 通过复制值进行赋值,又名“经典的 C++/Java 方法”。

     let a = 4 // assign value 4 to variable a let b = a // copy value of a into ba = 5 // reassign a with value 5
  2. 通过共享引用进行分配。 原始值是不可变的,对象是可变的。

     let a = 4 // Assigns a with a reference to the immutable value 4 let b = a // copies the reference of a to ba = 5 // reassigns a with a reference to 5 (in-place mutation would cause b to change as well)

变体 1 为 Arguments:

最重要的是,ECMAScript 本身似乎将赋值指定为复制值。

https://tc39.es/ecma262/#sec-declarative-environment-records-setmutablebinding-nvs

 AssignmentExpression : LeftHandSideExpression = AssignmentExpression

1. If LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral, then
    a. Let lref be ? Evaluation of LeftHandSideExpression.
    b. If IsAnonymousFunctionDefinition(AssignmentExpression) and IsIdentifierRef of LeftHandSideExpression are both true, then
        i. Let rval be ? NamedEvaluation of AssignmentExpression with argument lref.[[ReferencedName]].
    c. Else,
        i. Let rref be ? Evaluation of AssignmentExpression.
        ii. Let rval be ? GetValue(rref).
    d. Perform ? PutValue(lref, rval).
    e. Return rval.
2. Let assignmentPattern be the AssignmentPattern that is covered by LeftHandSideExpression.
3. Let rref be ? Evaluation of AssignmentExpression.
4. Let rval be ? GetValue(rref).
5. Perform ? DestructuringAssignmentEvaluation of assignmentPattern with argument rval.
6. Return rval.

分支 1d 对于原语特别有趣,它最终导致了 EnvironmentRecord 的 SetMutableBinding 方法,其中指出:

https://tc39.es/ecma262/#sec-declarative-environment-records-setmutablebinding-nvs

它尝试将名称为 N 的标识符的当前绑定的绑定值更改为值 V

变体 2 为 Arguments:

另一方面,许多文档表明示例 1 可能就是这种情况。 就像明确提到原始值的不变性一样,只有在有可能通过这样做(通过多个引用指向该值)影响其他变量的情况下才真正有意义。

https://developer.mozilla.org/en-US/docs/Glossary/Primitive?retiredLocale=de

所有原语都是不可变的; 也就是说,它们不能被改变。 重要的是不要将原语本身与分配了原语值的变量混淆。 变量可以重新赋值给一个新的值,但是现有的值不能像对象、arrays 和函数可以改变的方式那样被改变。

Eloquent JavaScript 中的这个解释我假设也讨论了指向不同值的引用(绑定)。

https://eloquentjavascript.net/04_data.html

即使数字值不变,您也可以使用 let 绑定通过更改绑定指向的值来跟踪不断变化的数字。

我的猜测是,规范相当笼统。 这更适用于变体 1,但实现者可以自由地按照您想要的方式实现它。 那是对的吗?

赋值总是按值复制,你可以很容易地检查选项 2 不会发生什么。

有时可能令人困惑的是,如果您(按值)复制一个指针,然后修改它指向的值,那么原始变量指向的值将始终被修改(因为它们都指向相同的 memory 地址)。 对象和 arrays 之类的东西是秘密指针。

let a = {x: 3};
let b = a;

b.x = 5;
// Now a.x is 5 as well because a and b point to the same memory address 

b = {x: 7};
// a.x is still 5 because we changed the value of b

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM