我确定这必须存在于某个地方,但我无法找到它......
我正在尝试编写一个将对象作为参数并更新其引用的函数。不是引用的属性,也不是重新分配对象,而是更新整个引用。
请注意,PubSub只是为了证明在传入和更新的对象类型中需要异步性和灵活性。
最好用例子解释:
//ideally how function would work
function watch(event, obj) {
PubSub.on(event, function(model) {
// I want to update the entire object
// I understand that currently, this is just reassigning
// I know I can do obj.prop = model, but that's not what I want to do
obj = model;
}
};
//example usage
var myObj = {"name" : "Tom"};
watch("anEvent", myObj);
console.log(myObj.name); //still "Tom"
// time passes, then somewhere
PubSub.trigger("anEvent", {"name" : "John"})
console.log(myObj.name); // now should read "John"
这是一种bind()
方法,例如$.bind()
或currying会有用,还是只是在适当的上下文中使用“this”?
答案 0 :(得分:8)
这是不可能的。
让您感到困惑的是,在js运行时,您无法管理实际参考值,但只能为变量分配一些参考值。
就是这样 - 您可以“附加”对给定变量名称的另一个引用,但不能修改引用值。
清除我上面所说的内容:对象的内存是在其初始化
上分配的var o = {};
之后,对未命名对象(对象没有名称,变量为)的引用被分配给o
变量。之后,您无法将另一个对象重新分配到内存中的相同位置。
答案 1 :(得分:3)
我将假设您已阅读我的解释:Why are objects' values captured inside function calls?。
如果你了解发生了什么。而且你认为这很难。你会看到一个明显的工作。
所以,与其他人的回答相反,我会说:是的,这是可能的(在极限范围内)。
首先,回顾一下。你意识到你拥有的实际上是对同一个对象的两个独立引用?分配一个引用不会导致重新分配另一个引用:
var foo = {some : 'values'};
(function (bar) {
// 'bar' in here points to the
// same object as foo but is a
// completely different reference
})(foo)
// is it obvious yet?
所以,虽然直截了当的bar = new_object
不起作用。意识到两个引用都指向您感兴趣的点上的同一个对象。
这意味着,即使您无法访问原始引用(在我的示例中为'foo',在您的示例中为'myObj'),您所拥有的是它所指向的对象。这是我们可以利用的。
如果你不关心当前对象会发生什么,并且你不介意对对象的所有引用都被修改,你只需要深入删除它的所有属性并用深层副本替换它们。新对象。
所以,虽然你做不到:
obj = model;
你可以这样做:
for (var n in obj) {
if (obj.hasOwnProperty(n)) {
delete(obj[n]);
}
}
for (var n in model) {
if (model.hasOwnProperty(n)) {
obj[n] = model[n];
}
}
并且您的代码应该按照您的预期运行。
如果你这么做(或者你只是想让你的代码更具可读性),你可以封装这个逻辑:
function reassignObjRef (ref, new_obj) {
for (var n in ref) {
if (ref.hasOwnProperty(n)) {
delete(ref[n]);
}
}
for (var n in new_obj) {
if (new_obj.hasOwnProperty(n)) {
ref[n] = new_obj[n];
}
}
}
所以你可以这样做:
function watch(event, obj) {
PubSub.on(event, function(model) {
reassignObjRef(obj,model);
}
};
答案 2 :(得分:1)
引用只是变量,就像基元一样。重新分配 更改其值。
你说
并且不重新分配对象,但更新整个引用。
问题在于那些意味着同样的事情。如果您的意思是更新另一个指向此对象的引用以指向其他内容,则只有在其他引用位于您的范围内时才能执行此操作。
没有办法说,给定对特定对象的引用,将对该对象的所有引用更改为指向其他对象。听起来这就是你想要做的事情。对不起,不可能。您需要一个具有属性的中间对象,该属性是您要更改的引用。
//ideally how function would work
function watch(event, obj) {
PubSub.on(event, function(model) {
// I want to update the entire object
// I understand that currently, this is just reassigning
// I know I can do obj.prop = model, but that's not what I want to do
obj.model = model;
}
};
//example usage
var myObj = {model: {"name" : "Tom"}};
watch("anEvent", myObj);
console.log(myObj.model.name); //still "Tom"
// time passes, then somewhere
PubSub.trigger("anEvent", {"name" : "John"})
console.log(myObj.name); // now should read "John"
答案 3 :(得分:0)
无法知道或找到对象的所有引用,因此没有通用的方法可以将所有引用重新分配给其他对象。您可以使用闭包以及get
和set
方法静态执行此操作(请参阅Douglas Crockford的Private Members in Javascript),但这似乎不是您想要的。
此外, bind 特定于函数的 this 变量,该变量是函数execution context的一个参数。它与范围无关。