2016-07-28 28 views
1

考慮以下幾點:強迫生活在內存中的對象指向不同的對象?

var obj1 = {"value":"one"}; 
var obj2 = obj1; 
console.log(obj2.value+"\n"); // prints "one" 
obj1 = {"value":"two"}; 
console.log(obj2.value+"\n"); // still prints "one" 

我明白這樣做的原因,在頭兩行,obj1obj2引用這都指向同一個對象,{"value":"one"},地方在內存中。當obj1被分配給不同的對象時,{"value":"two"},obj2仍然指向內存中相同的對象{"value":"one"}

我在尋找的是一種強制內存中的{"value":"one"}對象將其呼叫者重定向到{"value":"two"}對象的方法。換句話說,我正在尋找一種方式來操縱{"value":"one"}對象,以使obj2變量將最終指向{"value":"two"}對象,不重新分配obj2變量:

var obj1 = {"value":"one"}; 
var obj2 = obj1; 
console.log(obj2.value+"\n"); // prints "one" 
// ...some code to manipulate the `{"value":"one"}` object in memory 
// so that *any* references which originally pointed to the 
// `{"value":"one"}` object now point to the `{"value":"two"}` 
// object, like a sort of "redirection". This would be done 
// without ever explicitly reassigning the references. 
console.log(obj2.value+"\n"); // now prints "two" 

有沒有辦法做到這一點?

實際應用涉及到一些非常複雜的Mozilla代碼這將妨礙這個線程嘗試和解釋,所以我問這是一個一般的理論問題。

編輯:結論:

「否」是最正確的答案實際問題,下面狀態torazaburo的評論這一點。不過,我覺得帕特里克的答案,使用代理,最接近完成這一點,所以我接受了他的答案。我會補充一點,雖然代理是非常強大的工具,但它們與實際的目標對象並不相同,並且存在一些限制。

+0

這是對象身份的一個基本問題。一個對象本身就是,而且永遠是。對於您的潛在問題,可能有其他解決方案,但即時更改對象的身份 - 從其下方更換對象 - 不是其中的一個。 – 2016-07-28 19:48:04

+0

很容易獲得'console.log(obj2()。value +「\ n」);'如上所述運作。你可能可以使用getter或者proxy來避免這些parens .... – dandavis

回答

3

退房proxies。您可以使用getset來動態引用您選擇的基礎對象,將代理公開爲想要隱式更新的自由浮動引用。這裏有一個例子:

function Proxyable(target) { 
 
    this.target = target; 
 
    this.proxy = new Proxy(this, Proxyable.handler); 
 
} 
 

 
Proxyable.prototype.getReference = function() { 
 
    return this.proxy; 
 
}; 
 

 
Proxyable.prototype.setReference = function (target) { 
 
    this.target = target; 
 
}; 
 

 
Proxyable.handler = { 
 
    get: function (proxyable, property) { 
 
    return proxyable.target[property]; 
 
    }, 
 
    set: function (proxyable, property, value) { 
 
    return proxyable.target[property] = value; 
 
    } 
 
}; 
 

 
// original object 
 
var original = { value: ['one'] }; 
 
// have to create a namespace unfortunately 
 
var nsp = new Proxyable(original); 
 

 
// reference the ref value of the namespace 
 
var ref1 = nsp.getReference(); 
 
var ref2 = nsp.getReference(); 
 

 
// same references (not just values) 
 
console.log(ref1.value === original.value); 
 
console.log(ref2.value === original.value); 
 

 
// hot-load a replacement object over the original 
 
var replacement = { value: ['two'] }; 
 
// into the namespace 
 
nsp.setReference(replacement); 
 

 
// old references broken 
 
console.log(ref1.value !== original.value); 
 
console.log(ref2.value !== original.value); 
 
// new references in place 
 
console.log(ref1.value === replacement.value); 
 
console.log(ref2.value === replacement.value);

1

我認爲this answer會引導你以最好的方式來處理這種行爲。無法簡單地將一個對象重定向到另一個對象,但可以簡單地修改它的值,使其與您嘗試更改的對象相匹配。

你也可以定義一個全局對象:

var objs = { 
    1: {value: 'test'} 
    2: {value: 'test2'} 
}; 

從那裏,繞過一個對象與你試圖嘲弄鍵的值。只需更改密鑰,然後參考新元素。

一個例子:

var obj = {key: 1}; 
console.log(objs[obj.key]); 
//Outputs: {value: 'test'} 

obj.key = 2; 
console.log(objs[obj.key]); 
//Outputs: {value: 'test2'} 
+0

不會有像'var obj1 = {realObj:{value:'test'}}這樣的對象變得更容易嗎?然後你可以做'var obj2 = obj1; obj2.realObj = {value:'test2'};的console.log(obj1.realObj.value); //輸出:test2' – iamtheib

0

有直接沒有辦法做你想做的。出於你在你的問題中陳述的原因 - 這就是變量和值在javascript中的工作原理。

但是,在您的問題中您自己的單詞暗示了一種實現可能有效的方法。但取決於你處理的代碼,它可能不是你想要的。

您可以簡單地將對象包裝在另一個引用中。所以改變引用的內容會改變共享引用的所有變量指向的對象。您可使用現有的兩個參考容器:對象或數組:

// This works: 
var obj1 = [{value:'one'}]; 
var obj2 = obj1; 

var obj1[0] = {value:'two'}; 

console.log(obj1[0]); // prints {"value":"two"} 
console.log(obj2[0]); // prints {"value":"two"} 

或者:

// This also works: 
var obj1 = {obj:{value:'one'}}; 
var obj2 = obj1; 

var obj1.obj = {value:'two'}; 

console.log(obj1.obj); // prints {"value":"two"} 
console.log(obj2.obj); // prints {"value":"two"} 
相關問題