我在函数外部定义了一个对象,在全局范围内。此对象不作为参数传递给函数,但函数会修改它并返回修改后的对象。
我想知道的是,如果函数返回对象的副本或原始的全局对象?
另外,将该对象作为参数传递给函数会产生影响,因为对象是通过引用传递给函数的吗?
答案 0 :(得分:45)
每当您返回一个对象时,您将返回对该对象的引用。同样,当您传递一个对象时,您正在传递一个引用。但是,将对象作为参数传递可以与仅更改全局范围内的对象不同,如这些示例所示。这是因为对象的引用本身是通过值传递的。
如果要更改对象的成员,那么无论是将其作为参数传递还是仅更新全局对象都没有区别。无论哪种方式,你都在使用相同的对象。
示例1:
var object = {foo:'original'};
function changeObject() {
object.foo = 'changed';
return object;
}
console.log(changeObject()); // outputs {foo:'changed'}
console.log(object); // outputs {foo:'changed'}
示例2:
var object = {foo:'original'};
function changeArgument(object) {
object.foo = 'changed';
return object;
}
console.log(changeArgument(object)); // outputs {foo:'changed'}
console.log(object); // outputs {foo:'changed'}
另一方面,如果您使用新对象覆盖对象,则在对参数执行此操作时更改将不会保留,但如果对全局对象执行此操作,则更改将保持不变。那是因为参数通过值传递对象的引用。将此值替换为对新对象的引用后,您不再讨论同一个对象了。
示例3:
var object = {foo:'original'};
function replaceObject() {
object = {foo:'changed'};
return object;
}
console.log(replaceObject()); // outputs {foo:'changed'}
console.log(object); // outputs {foo:'changed'}
示例4:
var object = {foo:'original'};
function replaceArgument(object) {
object = {foo:'changed'};
return object;
}
console.log(replaceArgument(object)); // outputs {foo:'changed'}
console.log(object); // outputs {foo:'original'}
答案 1 :(得分:2)
可能是迟到的评论,但这是任何语言的典型挑战。 在堆上创建并通过引用传递的对象与基元相对(按值)。 我认为问题的根源是共享实例与唯一实例,以避免不受欢迎的影响。 例如,我们调用一个函数来获取新用户添加到集合的模板(对象),或者想要清除表单 从不同模块取消事件重新开始。它易于理解且容易被忽视。通常是测试用例 不涵盖所有使用排列
理智清单:
这里是共享实例:
var bigo = {
usr: { name: 'steven' },
bigi: function () {
return this.usr;
}
};
var outA = bigo.bigi();
var outB = bigo.bigi();
print(outA.name); // => steven
print(outB.name); // => steven
outA.name = 'ilan'; // change value
print(outA.name); // => ilan
print(outB.name); // => ilan
非共享实例:
var bigo = {
bigi: function () {
var user = { name: 'steven' };
return user;
}
};
var outA = bigo.bigi();
var outB = bigo.bigi();
print(outA.name); // => steven
print(outB.name); // => steven
outA.name = 'ilan'; // change value
print(outA.name); // => ilan
print(outB.name); // => steven
答案 2 :(得分:1)
我想知道的是,如果函数返回对象的副本或原始的全局对象?
实际上,您只处理JavaScript中对象的引用。即使var foo = {}
只是将对象的引用分配给foo
。
答案 3 :(得分:1)
如果对象在函数外部,则无需“返回”它。如果修改函数中的对象,它将更新对象本身。然后,您可以根据需要在其他函数中引用新更新的对象。
答案 4 :(得分:1)
根据您的问题,我认为您的代码看起来(或多或少):
var o = {};
function f() {
o.prop = true;
return o;
}
o
引用一个对象。o
时,您修改了o
个引用。因此它会修改原始对象。o
时,您将返回对原始对象的引用。将对象传递给函数会导致对传递的原始对象的引用。因此,任何修改都会影响原始对象。例如:
var o = {};
f(o);
console.log(o.prop); // true
function f(o) {
o.prop = true;
}