为什么不能将 null 设置为在 JavaScript 中通过引用传递的对象?
Why is it not possible to set null to an Object passed by reference in JavaScript?
我不知道为什么在下面的示例中不能为对象定义 null,但是可以向它添加属性
function callByReference(myFunc) {
myFunc.b = 2;
myFunc = null; // this not set null to Object arg
// myFunc.b = 2; //If I set it after, throws error
}
let customObj = {
a: 1
};
console.log("Before call by reference method");
console.log(customObj);
callByReference(customObj);
console.log("After call by reference method");
console.log(customObj);
即使我先将其设置为 null 然后添加 属性 也会引发错误;
我不太理解这种行为。有什么理由吗?也许我不理解 javascript 在通过引用传递参数时是如何工作的
这是 JavaScript 的工作方式:
参数总是按值传递,但是当变量引用对象时,"value"是对对象的引用。
改变一个变量的值永远不会改变底层的原语或对象,它只是将变量指向一个新的原语或对象(但是如果你改变一个属性一个属性在底层对象也改变了)。
Javascript 的工作方式,每个变量名本质上都是指向某个值的指针(或引用)。当您通过引用旧对象创建新变量时,或者当您调用函数时,您基本上是在复制指针。例如:
const fn = (param) => {
// ...
};
const obj = {};
const obj2 = obj;
fn(obj);
上面,obj2
和param
都指向最初在obj
中创建的空对象,你可能会认为它是:
obj: MemAddress1234
obj2: MemAddress1234
param: MemAddress1234
无论何时使用 =
赋值运算符,都会为该变量名称 重新分配绑定 ,但这样做不会影响可能指向的任何其他变量同样的事情:
param = null;
结果类似于
obj: MemAddress1234
obj2: MemAddress1234
param: MemAddress0
至少,这是一种看待它的方式。 obj
和空对象之间的 link 以及 obj2
和空对象之间的 link 不受影响,因为它只是 param
变量名重新分配。
单独重新分配一个变量几乎不会对其他任何东西产生任何副作用。这两个例外是 arguments
在草率模式下:
function foo(a, b) {
console.log(arguments);
a = 5;
console.log(arguments);
}
foo(1, 2);
以及由 ES6 模块导出的可变变量。
首先,您创建了一个 customObj
对象,它存储在内存中的某处。
然后你有一个带有参数的函数 function callByReference(myFunc)
.
如果您使用对象 callByReference(customObj)
调用该函数,它会将指向 customObj
的引用分配给 myFunc
。所以现在 myFunc
指向内存中与 customObj
.
相同的位置
现在,如果您在 myFunc
中修改某些内容,您将更改与 customObj
相同的内存 - 这就是为什么 myFunc.b = 2;
会修改customObj
。但是如果你给 myFunc
分配新的东西,你就是在修改它指向的地方,而不是里面的东西。所以myFunc = null;
就像告诉"now myFunc points to null memory",但是customObj
还是指向内存的同一部分,所以数据是一样的
我不知道为什么在下面的示例中不能为对象定义 null,但是可以向它添加属性
function callByReference(myFunc) {
myFunc.b = 2;
myFunc = null; // this not set null to Object arg
// myFunc.b = 2; //If I set it after, throws error
}
let customObj = {
a: 1
};
console.log("Before call by reference method");
console.log(customObj);
callByReference(customObj);
console.log("After call by reference method");
console.log(customObj);
即使我先将其设置为 null 然后添加 属性 也会引发错误;
我不太理解这种行为。有什么理由吗?也许我不理解 javascript 在通过引用传递参数时是如何工作的
这是 JavaScript 的工作方式:
参数总是按值传递,但是当变量引用对象时,"value"是对对象的引用。
改变一个变量的值永远不会改变底层的原语或对象,它只是将变量指向一个新的原语或对象(但是如果你改变一个属性一个属性在底层对象也改变了)。
Javascript 的工作方式,每个变量名本质上都是指向某个值的指针(或引用)。当您通过引用旧对象创建新变量时,或者当您调用函数时,您基本上是在复制指针。例如:
const fn = (param) => {
// ...
};
const obj = {};
const obj2 = obj;
fn(obj);
上面,obj2
和param
都指向最初在obj
中创建的空对象,你可能会认为它是:
obj: MemAddress1234
obj2: MemAddress1234
param: MemAddress1234
无论何时使用 =
赋值运算符,都会为该变量名称 重新分配绑定 ,但这样做不会影响可能指向的任何其他变量同样的事情:
param = null;
结果类似于
obj: MemAddress1234
obj2: MemAddress1234
param: MemAddress0
至少,这是一种看待它的方式。 obj
和空对象之间的 link 以及 obj2
和空对象之间的 link 不受影响,因为它只是 param
变量名重新分配。
单独重新分配一个变量几乎不会对其他任何东西产生任何副作用。这两个例外是 arguments
在草率模式下:
function foo(a, b) {
console.log(arguments);
a = 5;
console.log(arguments);
}
foo(1, 2);
以及由 ES6 模块导出的可变变量。
首先,您创建了一个 customObj
对象,它存储在内存中的某处。
然后你有一个带有参数的函数 function callByReference(myFunc)
.
如果您使用对象 callByReference(customObj)
调用该函数,它会将指向 customObj
的引用分配给 myFunc
。所以现在 myFunc
指向内存中与 customObj
.
现在,如果您在 myFunc
中修改某些内容,您将更改与 customObj
相同的内存 - 这就是为什么 myFunc.b = 2;
会修改customObj
。但是如果你给 myFunc
分配新的东西,你就是在修改它指向的地方,而不是里面的东西。所以myFunc = null;
就像告诉"now myFunc points to null memory",但是customObj
还是指向内存的同一部分,所以数据是一样的