【问题标题】:Javascript assignment operator weird behaviourJavascript赋值运算符奇怪的行为
【发布时间】:2016-09-01 15:33:36
【问题描述】:

我正在研究一个事件小部件并发现奇怪的行为,这可能是菜鸟问题。

下面是我正在处理的代码块

var event={0:{competition:{like:false}}}
console.log(event[0].competition.like);   //returns false
var cmpt=event[0].competition;
cmpt.like=true;
console.log(event[0].competition.like) //returns true

您能帮我理解一下,为什么事件对象内的竞争的 属性 [like] 的值会更新。 以及如何防止这种情况而不是更新事件对象?

我尝试调查 google/so,但这些问题解决了不同的问题。

【问题讨论】:

  • 你只是在复制一个引用,而不是对象。
  • 这是因为在 javascript 中对象是通过引用传递的,为了使其按照您希望的方式工作,您需要克隆竞争对象。
  • 如果它不是字符串或数字,那么它是一个引用(指针)。要复制一个对象(而不是指向它),请执行 Object.create(event[0].competition)
  • @jcubic:虽然Object.create() 的实现细节严格继承自给定对象,但语义完全等同于深度克隆。更改父对象不会更改子对象,更改子对象不会更改父对象。这就是为什么Object.create() 被认为是现代 js 环境中的标准深拷贝技术。
  • @slebetman 看看这个jsfiddle.net/yfyv74nm/1

标签: javascript variable-assignment assignment-operator


【解决方案1】:

您正在分配对

的引用
    event[0].competition

到变量cmpt,然后修改它的值——无论你对原始实例做什么都会影响cmpt变量

【讨论】:

    【解决方案2】:

    在 JavaScript 中,对象总是通过引用传递。这意味着当您将一个对象分配给另一个变量时,它仍然指向同一个对象。如果你想拥有两个独立的对象,你必须克隆它。例如,您可以使用_.clone() method from lodash library

    var cmpt = _.clone(event[0].competition);
    

    【讨论】:

      【解决方案3】:

      你能帮我理解,为什么属性 [like] 的值 事件对象内部的竞争正在更新

      您通过执行此作业将event[0].competition 的引用复制到cmpt

      现在cmpt 指向event[0].competition 指向的同一个对象。因此,如果您更新该值,它基本上会在两个变量指向的同一个对象中进行更改。

      如何防止这种情况发生而不更新事件对象?

      如果您想确保不更新旧值,则需要在分配时深度克隆对象

      替换

      var cmpt=event[0].competition;
      

      var cmpt=JSON.parse( JSON.stringify( event[0].competition ) );
      

      【讨论】:

      • 非常感谢。我使用 jQuery.clone 将对象复制到新变量中。
      【解决方案4】:

      当你有一个对象时,你就像你做的那样将它“复制”到一个新对象中,并更改新对象旧对象被更新。

      这是因为您实际上并没有复制它,您只是对该原始对象有另一个引用,因此您在“副本”上所做的任何更改都会反映在原始对象中...

      【讨论】:

        【解决方案5】:

        这是因为在 JavaScript 中,当您将一个对象值分配给另一个变量时,您实际上是在为它分配一个值(它不会像原始值那样被复制)。

        所以ˋcmptˋ和ˋevent[0].competitionˋ指的是同一个对象。

        如果你需要克隆对象,它只包含原始值、数组和简单对象(没有函数),你可以使用ˋJSON.stringifyˋ和ˋJSON.parseˋ。

        var event={0:{competition:{like:false}}}
        console.log(event[0].competition.like);       //returns false
        var cmpt=JSON.parse(JSON.stringify(event[0].competition));
        cmpt.like=true;
        console.log(event[0].competition.like)
        //returns false
        

        【讨论】:

          【解决方案6】:

          这就是为什么你只是“重命名”事件,你可以这样做。

          var event={0:{competition:{like:false}}}
          console.log(event[0].competition.like);   //returns false
          var cmpt = {};
          cmpt.like = event[0].competition.like;
          cmpt.like = true;
          console.log(event[0].competition.like) //returns false
          

          【讨论】:

            【解决方案7】:

            您可以使用以下内容:

            var event={0:{competition:{like:false}}}
            console.log(event[0].competition.like);   //returns false
            var cmpt=jQuery.extend({}, event[0].competition);
            cmpt.like=true;
            console.log(event[0].competition.like) //returns false (changed) 
            

            【讨论】:

              【解决方案8】:

              如何防止这种情况发生而不更新事件对象?

              您可以使用Object.create(),第一个参数设置为null;在第二个参数的属性描述符的value 处迭代event[0].competition 属性为Object.create(),将每个属性的值设置为null,返回新创建的对象,其属性为event[0].competition 设置为null

              var event = {
                0: {
                  competition: {
                    like: false
                  }
                }
              }
              
              console.log(event[0].competition.like); //returns false
              
              var cmpt = Object.create(null, {
                competition: {
                  value: (function(obj) {
                    var _obj = {};
                    for (var prop in obj) {
                      _obj[prop] = null
                    };
                    return _obj
                  }(event[0].competition)),
                  writable: true,
                  enumerable: true,
                  configurable: true
                }
              });
              cmpt.competition.like = true;
              console.log(event[0].competition.like, cmpt.competition.like
                         , event[0], cmpt) //`false, `true`

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2012-01-22
                • 2023-04-03
                • 2012-12-17
                • 1970-01-01
                • 1970-01-01
                • 2020-06-18
                • 2012-02-29
                • 1970-01-01
                相关资源
                最近更新 更多