Dev*_*555 52 javascript pass-by-reference
我知道在JS中,对象是通过引用传递的,例如:
function test(obj) {
obj.name = 'new name';
}
var my_obj = { name: 'foo' };
test(my_obj);
alert(my_obj.name); // new name
Run Code Online (Sandbox Code Playgroud)
但为什么下面没有工作:
function test(obj) {
obj = {};
}
var my_obj = { name: 'foo' };
test(my_obj);
alert(my_obj.name); // foo
Run Code Online (Sandbox Code Playgroud)
我已经将对象设置为{}(空)但它仍然说foo.
任何人都可以解释这背后的逻辑吗?
Ale*_*ijk 67
如果您熟悉指针,那么您可以采用类比.你实际上是在传递一个指针,因此obj.someProperty会取消引用该属性并实际覆盖它,而只是覆盖obj会杀死指针并且不会覆盖该对象.
Ada*_*kis 30
因为JavaScript实际上是通过pass-by- copy -reference 传递对象.
当你传递my_obj到你的test函数,一个拷贝到该对象的引用中传递其结果是,当你重新分配的对象.test你真的只有重新分配正在拷贝原始对象的引用; 你的原件my_obj保持不变.
Que*_*tin 27
因为您要覆盖引用,而不是对象.
// Create a new object and assign a reference to it
// to the variable my_obj
var my_obj = { name: 'foo' };
// Pass the reference to the test function
test(my_obj);
// Assign the reference to a variable called obj
// (since that is the first argument)
function test(obj) {
// Create a new (empty) object and assign a reference to it to obj
// This replaces the existing REFERENCE
obj = {};
}
// my_obj still has a reference to the original object,
// because my_obj wasn't overwritten
alert(my_obj.name); // foo
Run Code Online (Sandbox Code Playgroud)
Javascript缺乏对引用传递的支持(尽管对象是通过引用传递的,并且引用只要没有使用赋值就可以保留,例如使用=),但是您可以ref使用以下技术模仿C#的关键字:
function test(obj) {
obj.Value = {};
//obj.Value = {name:"changed"};
}
var my_obj = { name: 'foo' };
(function ()
{
my_obj = {Value: my_obj};
var $return = test(my_obj);
my_obj = my_obj.Value;
return $return;
}).call(this);
alert(my_obj.name); // undefined, as expected
// In the question this returns "foo" because
// assignment causes dereference
Run Code Online (Sandbox Code Playgroud)
当然你可以使用全局变量并且不带参数调用函数,在这种情况下引用不会像这样:
var obj = { name: 'foo' };
function test() {
obj = {};
}
test();
alert(obj.name); // undefined
Run Code Online (Sandbox Code Playgroud)
如果你的所有代码都在闭包中,那么事情就更简单了,就像全局变量没有污染全局命名空间一样:
(function(){
var obj = { name: 'foo' };
function test() {
obj = {};
}
test();
alert(obj.name); // undefined
}).call(this);
Run Code Online (Sandbox Code Playgroud)
如果你必须将一些带有ref参数的C#代码移植到Javascript中,那么上面的"globals inside closure"-technique是很好的.例如.以下C#代码:
void MainLoop()
{
// ...
MyStruct pt1 = CreateMyStruct(1);
MyStruct pt2 = CreateMyStruct(2);
SwapPoints(ref pt1, ref pt2);
// ...
}
void SwapPoints(ref MyStruct pt1, ref MyStruct pt2)
{
MyStruct tmp = pt1;
pt1 = pt2;
pt2 = tmp;
}
Run Code Online (Sandbox Code Playgroud)
可以使用类似的东西移植到Javascript:
(function(){
var pt1, pt2;
function CreateMyStruct(myvar)
{
return {"myvar":myvar}
}
function MainLoop()
{
// ...
pt1 = CreateMyStruct(1);
pt2 = CreateMyStruct(2);
console.log("ORIG:",pt1,pt2);
SwapPoints();
console.log("SWAPPED:",pt1,pt2);
// ...
}
function SwapPoints()
{
var tmp = pt1;
pt1 = pt2;
pt2 = tmp;
}
MainLoop();
}).call(this);
Run Code Online (Sandbox Code Playgroud)
或者如果使用局部变量和函数参数是必要的,那么解决方案可以基于我的答案的第一个例子,如下所示:
(function(){
function CreateMyStruct(myvar)
{
return {"myvar":myvar}
}
function MainLoop()
{
// ...
var pt1 = CreateMyStruct(1);
var pt2 = CreateMyStruct(2);
console.log("ORIG:",pt1,pt2);
(function ()
{
pt1 = {Value: pt1};
pt2 = {Value: pt2};
var $return = SwapPoints(pt1, pt2);
pt1 = pt1.Value;
pt2 = pt2.Value;
return $return;
}).call(this);
console.log("SWAPPED:",pt1,pt2);
// ...
}
function SwapPoints(pt1, pt2)
{
var tmp = pt1.Value;
pt1.Value = pt2.Value;
pt2.Value = tmp;
}
MainLoop();
}).call(this);
Run Code Online (Sandbox Code Playgroud)
真的不得不说Javascript在没有原生的时候缺少很多ref!代码会简单得多.
| 归档时间: |
|
| 查看次数: |
17300 次 |
| 最近记录: |