7

我确定这一定存在于某个地方,但我一直无法找到它......

我正在尝试编写一个将对象作为参数并更新其引用的函数。不是引用的属性,也不是重新分配对象,而是更新整个引用。

请注意,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”?

4

4 回答 4

8

这是不可能的。

让您感到困惑的是,在 js 运行时您无法管理实际的引用值,而只能将一些引用值分配给变量。

就是这样 - 您可以将另一个引用“附加”到给定的变量名称,但您不能修改引用值。

为了清楚我上面所说的:对象的内存是在其初始化时分配的

var o = {};

之后,对未命名对象(对象没有名称,变量有)的引用被分配给一个o变量。之后,您不能将另一个对象重新分配到内存中的同一位置。

于 2013-05-13T01:17:08.677 回答
3

我假设您已经阅读了我的解释:为什么在函数调用中捕获对象的值?.

如果你明白发生了什么。而且你想得够辛苦。你会看到一个明显的解决方法。

因此,与其他所有人的回答相反,我要说:是的,这是可能的(在限制范围内)。


解决方法

首先,回顾一下。你意识到你所拥有的实际上是对同一个对象的两个不同的引用?分配一个引用不会导致另一个引用被重新分配:

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);
    }
};
于 2013-05-13T02:46:37.323 回答
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"
于 2013-05-13T01:20:44.210 回答
0

没有办法知道或找到对一个对象的所有引用,因此没有通用的方法来重新分配对某个其他对象的所有引用。您可以使用闭包和方法静态地执行此get操作set(请参阅 Douglas Crockford 的Private Members in Javascript),但这似乎不是您想要的。

此外,bind特定于函数的this变量,它是函数执行上下文的一个参数。它与范围无关。

于 2013-05-13T01:42:13.963 回答