Javascript 复制一个变量';把一个人的价值转换成另一个人的价值

Javascript 复制一个变量';把一个人的价值转换成另一个人的价值,javascript,jquery,Javascript,Jquery,我有一个变量,它的值是JSON对象。我直接将这个变量分配给其他变量,这样它们就共享相同的值。这就是它的工作原理: var a = $('#some_hidden_var').val(), b = a; 这是可行的,两者都有相同的价值。我使用mousemove事件处理程序在整个应用程序中更新b。单击按钮后,我想将b还原为原始值,即存储在a中的值 $('#revert').on('click', function(e){ b = a; }); 在此之后,如果我使用相同的mouse

我有一个变量,它的值是JSON对象。我直接将这个变量分配给其他变量,这样它们就共享相同的值。这就是它的工作原理:

var a = $('#some_hidden_var').val(),
    b = a;
这是可行的,两者都有相同的价值。我使用
mousemove
事件处理程序在整个应用程序中更新
b
。单击按钮后,我想将
b
还原为原始值,即存储在
a
中的值

$('#revert').on('click', function(e){
    b = a;
});
在此之后,如果我使用相同的
mousemove
事件处理程序,它将同时更新
a
b
,而之前它只按预期更新
b


我被这个问题难住了!这里怎么了?

我暂时自己解决了。原始值只有2个子属性。我用
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 };
});

这个很好用。除了上面的代码,我没有在代码的任何地方更改任何一行,它的工作方式正是我想要的。因此,相信我,没有其他东西在更新
a

原因很简单。JavaScript使用refereces,因此当您分配
b=a
时,您将引用分配给
b
,因此当更新
a
时,您也在更新
b

$('#revert').on('click', function(e){
    b = a;
});
我在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.");
}
功能克隆(obj){
//处理3个简单类型,以及null或undefined
如果(null==obj | |“object”!=typeof obj)返回obj;
//处理日期
if(obj实例截止日期){
var copy=新日期();
copy.setTime(obj.getTime());
返回副本;
}
//句柄数组
if(阵列的obj实例){
var copy=[];
对于(变量i=0,len=obj.length;i
了解JavaScript中的
=
操作符的作用和不作用非常重要

操作员不复制数据。

=
操作符创建对相同数据的新引用。

运行原始代码后:

var a = $('#some_hidden_var').val(),
    b = a;
a
b
现在是同一对象的两个不同名称

无论您是通过
a
变量还是
b
变量引用此对象,您对此对象内容所做的任何更改都将以相同的方式显示。它们是同一个物体

因此,当您稍后尝试使用此代码将
b
还原为原始
a
对象时:

b = a;
代码实际上什么都不做,因为
a
b
是完全相同的东西。代码与您编写的代码相同:

b = b;
这显然不会起任何作用

你的新代码为什么有效

b = { key1: a.key1, key2: a.key2 };
在这里,您正在使用
{…}
对象文字创建一个全新的对象。此新对象与旧对象不同。因此,您现在将
b
设置为对这个新对象的引用,它可以满足您的需要

要处理任意对象,可以使用对象克隆函数,如Armand的答案中列出的函数,或者因为您使用的是jQuery,所以只需使用。此函数将创建对象的浅拷贝或深拷贝。(不要将其和用于复制DOM元素而不是对象的对象混淆。)

对于浅拷贝:

b = $.extend( {}, a );
或深度副本:

b = $.extend( true, {}, a );
浅拷贝和深拷贝有什么区别?浅层副本类似于使用对象文字创建新对象的代码。它创建一个新的顶级对象,其中包含对与原始对象相同属性的引用

如果对象仅包含数字和字符串等基本类型,则深度副本和浅层副本将执行完全相同的操作。但如果对象包含嵌套在其中的其他对象或数组,则浅层副本不会复制这些嵌套对象,它只会创建对它们的引用。因此,嵌套对象的问题可能与顶级对象的问题相同。例如,给定此对象:

var obj = {
    w: 123,
    x: {
        y: 456,
        z: 789
    }
};
如果对该对象进行浅层复制,则新对象的
x
属性与原始对象的
x
属性相同:

var copy = $.extend( {}, obj );
copy.w = 321;
copy.x.y = 654;
现在,您的对象将如下所示:

// 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
    }
};
您可以通过深度复制来避免这种情况。深度复制递归到每个嵌套对象和数组(以及Armand代码中的日期)中,以与复制顶级对象相同的方式复制这些对象。因此更改
copy.x.y
不会影响
obj.x.y


简短回答:如果有疑问,您可能需要一份深度副本。

这个问题已经解决了很久,但为了将来参考,可能的解决方案是

b = a.slice(0);

请注意,只有当a是一个非嵌套的数字和字符串数组时,这种方法才能正常工作。我在使用JSON时发现它是有效的,但请注意我们的循环引用

var newInstance = JSON.parse(JSON.stringify(firstInstance));

对于字符串或输入值,您可以简单地使用:

var a = $('#some_hidden_var').val(),
b = a.substr(0);

我不明白为什么答案如此复杂。在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'
将上述任何一行(一次一行)粘贴到节点或任何浏览器javascript控制台中。然后键入任何变量并
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 }