【问题标题】:creating multiple instances of a object property创建对象属性的多个实例
【发布时间】:2013-10-15 02:21:53
【问题描述】:

我正在尝试创建具有 init 函数的对象的多个版本。我曾尝试使用 javascript 'new' 函数,但在这种情况下不起作用,控制台会通知我这是因为它不是函数。 请参阅代码以更清楚地描述我正在尝试做的事情。 我理解为什么这段代码会提醒项目二而不是项目一,但我不知道如何获得正确的行为。

var myApp = {
menu: {
        init: function (name) {
            this.name = name;
        },
        alertName: function () {
            alert(this.name);
        }
    }
}

$(document).ready(function () {
    var first = myApp.menu;
    var second = myApp.menu;
    first.init('item one');
    second.init('item two');
    first.alertName();
}); 

【问题讨论】:

    标签: javascript jquery oop object


    【解决方案1】:

    你可以使用javascript的构造函数,调用new来实例化不同的对象:

    var myApp = {
        menu: function(name){
            // if menu is called as a constructor function, `this` will refer
            // to the object being built
            this.name = name;
        }
    }
    
    myApp.menu.prototype.alertName = function(){
        alert(this.name);
    }
    
    $(document).ready(function () {
        var first = new myApp.menu('item one');
        var second = new myApp.menu('item two');
        first.alertName();
    });
    

    fiddle

    【讨论】:

    • 我正在寻找不使用构造函数创建对象的副本。主要是因为我可以使用我已经创建的大量代码。
    • Corum 和 Tibos 的回答也是有效的。
    【解决方案2】:

    只有'item two' 被提醒的原因是因为当您执行first = myApp.menusecond=myApp.menu 时,firstsecond 都指的是同一个对象。当您设置该对象的name 属性(init 中的this.name = name)时,两个引用都指向具有更改属性的同一个对象。

    最简单的方法是这样的:

    var myApp = {
      menu : {
        init: function (name) {
           this.name = name;
        },
        alertName: function () {
          alert(this.name);
        }
      }
    }
    
    var first = Object.create(myApp.menu);
    var second = Object.create(myApp.menu);
    first.init('item one');
    second.init('item two');
    first.alertName();
    

    演示:http://jsbin.com/OrEkaPe/1/edit

    Object.create 创建一个新对象 (duh) 并将参数设置为新对象的原型。当您访问新对象上的属性但它不存在时,它将改为从原型中访问,从而为您提供所需的继承。

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create

    【讨论】:

      【解决方案3】:

      你必须克隆你的对象。在javascript中,你的变量firstsecond是对同一个对象的两个引用:当修改first时,你也修改了second

      您可以使用jQuery.extend() 克隆您的对象。

      var first = jQuery.extend(true, {}, myApp.menu);
      var second = jQuery.extend(true, {}, myApp.menu);
      

      【讨论】:

      • 这里使用 jquery 而不是 Tibos 回答中的 Object.create 选项的主要原因是什么
      • @彼得萨克斯顿。有两个原因:首先,他已经使用过 jQuery,所以使用 jQuery 函数对他来说不是问题。其次,Object.create 功能在 IE 9 之前不可用(MDN Object.create page)。当有选择时,我会选择提供最大兼容性的解决方案。
      • 需要提到一些注意事项:1)这个解决方案在处理许多对象时会影响性能,因为它是克隆对象而不是使用 JS 的原型继承。 2)在兼容性表下方的 MDN 页面上,如果 OP 想要支持古老的浏览器,可以使用这个确切用例的 polyfill。
      • JQuery 往往有很多很好用的方法,但代价是什么?想象一下,为了将对象扩展到深度,JQuery 将不得不递归地遍历所有属性并一一复制它们。很明显,它会引发原生对象实例化的性能问题。
      【解决方案4】:

      使用 {} 声明对象实际上是内联初始化,已经是一个实例而不是构造函数,解决您的问题的一种方法是创建一个声明性对象。

      有关更多信息,请参阅此参考:

      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects

      您的问题的快速实现在这里:

      http://jsbin.com/OsoWECA/1/edit

      var myApp = {
      menu: function () {
              this.init = function (name) {
                  this.name = name;
              };
              this.alertName = function () {
                  alert(this.name);
              };
              return this;
          }
      };
      
      $(document).ready(function () {
          var first = new myApp.menu();
          var second = new myApp.menu();
          first.init('item one');
          second.init('item two');
          first.alertName();
          second.alertName();
      }); 
      

      【讨论】:

        【解决方案5】:

        如果需要,您可以实现自己的 new,这应该可以:

        var myApp = {
        menu: {
                init: function (name) {
                    this.name = name;
                },
                alertName: function () {
                    alert(this.name);
                },
                new: function () {
                    var func = function () {}
                    func.prototype = this
                    return new func;
                }
            }
        }
        
        $(document).ready(function () {
            var first = myApp.menu.new();
            var second = myApp.menu.new();
            first.init('item one');
            second.init('item two');
            first.alertName();
        }); 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-20
          • 2018-10-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多