重新理解连续赋值,你的对象能力了解了吗?
2024-02-16 10:29:46
没错,重新理解连续赋值,说白了就是连续赋值。
a = {n: 1};
a.x = 100;
console.log(a.x); // 100
a = {n: 2};
console.log(a.x); // undefined
实际上,上边的语句中,var x
只是声明一个 x
,然后用 y = 100
的结果值去初始化 x
。原因是:a
被重新赋值为 {n:2}
后,a
的引用变成了全新的,而 js
遵循从左向右的执行原则,a.x
拿到的是老的 a
的属性引用,console
输出 undefined
也是情理之中的。
而你可能觉得,如果改成这样就没事了吧:
var a = {n: 1};
a.x = 100;
console.log(a.x); // 100
a = {n: 2, x: 100};
console.log(a.x); // 100
不不不,这样理解还是错了!
第一段代码会打印出 undefined
,第二段代码会打印出 100
。这是因为,变量 a
是一个引用数据类型,而对于引用数据类型来说,赋值就意味着重新指向了另一块内存地址,即之前指向的内存地址的数据无法再通过 a
访问到了。
具体到第二段代码中,即使 a
重新指向了另一块内存地址,但在新地址中依然有一个 x
的属性,且值为 100
,所以 console
打印出的结果依然是 100
。
在哪里可能会发生连续赋值?
-
函数参数:如果向函数传递引用类型的数据,那么函数中的变量其实和函数外的是同一个,只要在函数中改变了该变量,那么函数外的值也会发生改变。
-
函数内部:内部函数中的变量可以访问外部函数中的变量,所以如果内部函数中改变了外部函数中的变量,那么外部函数中的值也会发生改变。
-
闭包:闭包中的变量可以访问外层函数中的变量,所以如果闭包中的变量改变了外层函数中的变量,那么外层函数中的值也会发生改变。
// 全局变量
var a = {n: 1};
// 函数内部
function func() {
a.n = 2;
}
func();
console.log(a.n); // 2
// 闭包
function outerFunc() {
var a = {n: 1};
function innerFunc() {
a.n = 2;
}
return innerFunc;
}
var inner = outerFunc();
inner();
console.log(a.n); // 2
所以说,连续赋值其实是一个挺危险的操作,因为很容易导致我们意料之外的错误。因此,在使用连续赋值的时候,一定要慎重,最好能明确知道自己想要做什么。
另外,在 js
中,let
和 const
都是用来声明变量的,但它们和 var
有着本质的区别。let
和 const
声明的变量都是块级作用域,而 var
声明的变量是全局作用域或函数作用域。这意味着,let
和 const
声明的变量只能在声明它们的块级作用域内使用,而 var
声明的变量可以在整个函数或全局范围内使用。
所以,如果我们想避免连续赋值带来的问题,那么就可以使用 let
或 const
来声明变量,这样就可以确保变量不会被意外重新赋值。
最后,希望大家能够对连续赋值有一个更深刻的理解,这样在以后的编程中才能避免一些不必要的错误。