jQuery 将一个变量的值复制到另一个
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18829099/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Copy a variable's value into another
提问by Rutwick Gangurde
I have a variable which has a JSON object as its value. I directly assign this variable to some other variable so that they share the same value. This is how it works:
我有一个变量,它有一个 JSON 对象作为它的值。我直接将此变量分配给其他变量,以便它们共享相同的值。这是它的工作原理:
var a = $('#some_hidden_var').val(),
b = a;
This works and both have the same value. I use a mousemove
event handler to update b
through out my app. On a button click, I want to revert b
to the original value, meaning the value stored in a
.
这有效并且两者具有相同的价值。我使用mousemove
事件处理程序来更新b
我的应用程序。单击按钮时,我想恢复b
到原始值,即存储在a
.
$('#revert').on('click', function(e){
b = a;
});
After this if I use the same mousemove
event handler, it updates both a
and b
, when earlier it was updating only b
as expected.
在此之后,如果我使用相同的mousemove
事件处理程序,它会同时更新a
和b
,而早些时候它仅b
按预期更新。
I'm stumped over this issue! What is wrong here?
我被这个问题难住了!这里有什么问题?
回答by Michael Geary
It's important to understand what the =
operator in JavaScript does and does not do.
了解=
JavaScript 中的运算符做什么和不做什么很重要。
The =
operator does not make a copyof the data.
该=
运营商不会使拷贝数据。
The =
operator creates a new referenceto the samedata.
在=
操作创建一个新的参考到相同的数据。
After you run your original code:
运行原始代码后:
var a = $('#some_hidden_var').val(),
b = a;
a
and b
are now two different names for the same object.
a
并且b
现在是同一个对象的两个不同名称。
Any change you make to the contents of this object will be seen identically whether you reference it through the a
variable or the b
variable. They are the same object.
无论您是通过a
变量还是通过变量引用它,您对该对象的内容所做的任何更改都将被相同地看到b
。它们是同一个对象。
So, when you later try to "revert" b
to the original a
object with this code:
因此,当您稍后尝试使用以下代码“恢复”b
到原始a
对象时:
b = a;
The code actually does nothing at all, because a
and b
are the exact same thing. The code is the same as if you'd written:
代码实际上什么都不做,因为a
和b
是完全相同的东西。代码与您编写的代码相同:
b = b;
which obviously won't do anything.
这显然不会做任何事情。
Why does your new code work?
为什么你的新代码有效?
b = { key1: a.key1, key2: a.key2 };
Here you are creating a brand new object with the {...}
object literal. This new object is not the same as your old object. So you are now setting b
as a reference to this new object, which does what you want.
在这里,您将使用{...}
对象字面量创建一个全新的对象。这个新对象与您的旧对象不同。因此,您现在将设置b
为对这个新对象的引用,它可以执行您想要的操作。
To handle any arbitrary object, you can use an object cloning function such as the one listed in Armand's answer, or since you're using jQuery just use the $.extend()
function. This function will make either a shallow copy or a deep copy of an object. (Don't confuse this with the $().clone()
methodwhich is for copying DOM elements, not objects.)
要处理任何任意对象,您可以使用对象克隆函数,例如 Armand 的答案中列出的函数,或者因为您使用的是 jQuery,所以只需使用该$.extend()
函数。此函数将制作对象的浅拷贝或深拷贝。(不要将此与用于复制 DOM 元素而非对象的$().clone()
方法混淆。)
For a shallow copy:
对于浅拷贝:
b = $.extend( {}, a );
Or a deep copy:
或深拷贝:
b = $.extend( true, {}, a );
What's the difference between a shallow copy and a deep copy? A shallow copy is similar to your code that creates a new object with an object literal. It creates a new top-level object containing references to the same properties as the original object.
浅拷贝和深拷贝有什么区别?浅拷贝类似于使用对象字面量创建新对象的代码。它创建一个新的顶级对象,其中包含对与原始对象相同的属性的引用。
If your object contains only primitive types like numbers and strings, a deep copy and shallow copy will do exactly the same thing. But if your object contains other objects or arrays nested inside it, then a shallow copy doesn't copythose nested objects, it merely creates references to them. So you could have the same problem with nested objects that you had with your top-level object. For example, given this object:
如果你的对象只包含像数字和字符串这样的原始类型,深拷贝和浅拷贝将做完全相同的事情。但是,如果您的对象包含嵌套在其中的其他对象或数组,那么浅拷贝不会复制这些嵌套对象,它只会创建对它们的引用。因此,嵌套对象可能会遇到与顶级对象相同的问题。例如,给定这个对象:
var obj = {
w: 123,
x: {
y: 456,
z: 789
}
};
If you do a shallow copy of that object, then the x
property of your new object is the same x
object from the original:
如果您对该对象进行浅拷贝,则x
新对象的属性x
与原始对象相同:
var copy = $.extend( {}, obj );
copy.w = 321;
copy.x.y = 654;
Now your objects will look like this:
现在您的对象将如下所示:
// copy looks as expected
var copy = {
w: 321,
x: {
y: 654,
z: 789
}
};
// But changing copy.x.y also changed obj.x.y!
var obj = {
w: 123, // changing copy.w didn't affect obj.w
x: {
y: 654, // changing copy.x.y also changed obj.x.y
z: 789
}
};
You can avoid this with a deep copy. The deep copy recurses into every nested object and array (and Date in Armand's code) to make copies of those objects in the same way it made a copy of the top-level object. So changing copy.x.y
wouldn't affect obj.x.y
.
您可以通过深拷贝来避免这种情况。深层复制递归到每个嵌套对象和数组(以及 Armand 代码中的 Date)中,以与制作顶级对象副本相同的方式制作这些对象的副本。所以改变copy.x.y
不会影响obj.x.y
.
Short answer: If in doubt, you probably want a deep copy.
简短回答:如果有疑问,您可能需要深拷贝。
回答by kernowcode
I found using JSON works but watch our for circular references
我发现使用 JSON 有效,但请注意我们的循环引用
var newInstance = JSON.parse(JSON.stringify(firstInstance));
回答by marcosh
the question is already solved since quite a long time, but for future reference a possible solution is
这个问题已经解决了很长时间,但为了将来参考,一个可能的解决方案是
b = a.slice(0);
Be careful, this works correctly only if a is a non-nested array of numbers and strings
请注意,只有当 a 是数字和字符串的非嵌套数组时,它才能正常工作
回答by Kishor Patil
newVariable = originalVariable.valueOf();
newVariable = originalVariable.valueOf();
for objects you can use,
b = Object.assign({},a);
对于您可以使用的对象,
b = Object.assign({},a);
回答by Armand
The reason for this is simple. JavaScript uses refereces, so when you assign b = a
you are assigning a reference to b
thus when updating a
you are also updating b
这样做的原因是简单的。JavaScript 使用b = a
引用,因此当您分配时,您正在分配一个引用,b
因此更新时a
您也在更新b
I found thison stackoverflow and will help prevent things like this in the future by just calling this method if you want to do a deep copy of an object.
我在 stackoverflow 上发现了这个,如果你想对一个对象进行深度复制,只需调用这个方法就可以帮助防止将来发生类似的事情。
function clone(obj) {
// Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
// Handle Date
if (obj instanceof Date) {
var copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Handle Array
if (obj instanceof Array) {
var copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = clone(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
var copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
}
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}
回答by Trenton D. Adams
I do not understand why the answers are so complex. In Javascript, primitives (strings, numbers, etc) are passed by value, and copied. Objects, including arrays, are passed by reference. In any case, assignment of a new value or object reference to 'a' will not change 'b'. But changing the contents of 'a' will change the contents of 'b'.
我不明白为什么答案如此复杂。在 Javascript 中,原语(字符串、数字等)是按值传递和复制的。对象(包括数组)通过引用传递。在任何情况下,将新值或对象引用分配给“a”都不会改变“b”。但是改变'a'的内容会改变'b'的内容。
var a = 'a'; var b = a; a = 'c'; // b === 'a'
var a = {a:'a'}; var b = a; a = {c:'c'}; // b === {a:'a'} and a = {c:'c'}
var a = {a:'a'}; var b = a; a.a = 'c'; // b.a === 'c' and a.a === 'c'
Paste any of the above lines (one at a time) into node or any browser javascript console. Then type any variable and the console will show it's value.
将上述任何一行(一次一行)粘贴到节点或任何浏览器 javascript 控制台中。然后输入任何变量,控制台将显示它的值。
回答by Tim
For strings or input values you could simply use this:
对于字符串或输入值,您可以简单地使用这个:
var a = $('#some_hidden_var').val(),
b = a.substr(0);
回答by Lasse Brustad
Most of the answers here are using built-in methods or using libraries/frameworks. This simple method should work fine:
这里的大多数答案都使用内置方法或使用库/框架。这个简单的方法应该可以正常工作:
function copy(x) {
return JSON.parse( JSON.stringify(x) );
}
// Usage
var a = 'some';
var b = copy(a);
a += 'thing';
console.log(b); // "some"
var c = { x: 1 };
var d = copy(c);
c.x = 2;
console.log(d); // { x: 1 }
回答by Tony Sepia
回答by Rutwick Gangurde
I solved it myself for the time being. The original value has only 2 sub-properties. I reformed a new object with the properties from a
and then assigned it to b
. Now my event handler updates only b
, and my original a
stays as it is.
我暂时自己解决了。原始值只有 2 个子属性。我使用 from 的属性重新创建了一个新对象,a
然后将其分配给b
. 现在我的事件处理程序只更新b
,而我的原始事件a
保持原样。
var a = { key1: 'value1', key2: 'value2' },
b = a;
$('#revert').on('click', function(e){
//FAIL!
b = a;
//WIN
b = { key1: a.key1, key2: a.key2 };
});
This works fine. I have not changed a single line anywhere in my code except for the above, and it works just how I wanted it to. So, trust me, nothing else was updating a
.
这工作正常。除了上面的代码之外,我没有在代码中的任何地方更改任何一行,它的工作方式正是我想要的。所以,相信我,没有其他更新a
。