【问题标题】:What are the proper applications of these different methods of object creation in JavaScriptJavaScript中这些不同的对象创建方法的正确应用是什么
【发布时间】:2013-06-19 20:40:15
【问题描述】:

我更喜欢后端而不是前端,但是 JavaScript 让我很感兴趣。我正试图围绕在我看来是多种不同的对象建模方法。

在过去的几年里,我主要是在编写看起来与此类似的代码(假设已加载 jQuery):

var TicketForm = {

    elements: ['input', 'textarea', 'select', 'checkbox'],

    enable: function(form) {
        this.elements.forEach( function(el) {
            form.find(el).prop('disabled', false);
        });
    },

    disable: function(form) {
        this.element.forEach( function(el) {
            form.find(el).prop('disabled', true);
        });
    }
};

这样我可以简单地调用TicketForm.enable($('#whatever')); 来启用特定的表单,非常类似于 PHP 中的静态方法调用。

我最近一直在使用 PHP 中的闭包,并且我知道它们在 JavaScript 中也存在(并且我正在使用它们)。我正在尝试更彻底地真正掌握这个概念。在遇到这个惊人的脚本:http://codepen.io/stuffit/pen/KrAwx 后,我决定努力模仿该作者的编码风格。只是试图复制他的风格,我重写了我的代码:

var TicketForm = function() {
    this.elements = ['input', 'textarea', 'select', 'checkbox'];
};

TicketForm.prototype.enable = function(form) {
    this.elements.forEach( function(el) {
        form.find(el).prop('disabled', false);
    });
};

TicketForm.prototype.disable = function(form) {
    this.elements.forEach( function(el) {
        form.find(el).prop('disabled', true);
    });
};

但是,在这种情况下,当我调用 TicketForm.enable($('#whatever')); 时,我得到了错误

Uncaught TypeError: Object function () {
    this.elements = ['input', 'textarea', 'select', 'checkbox'];
} has no method 'enable'

所以我对 SO 进行了一些挖掘,并找到了 How does JavaScript .prototype work?。特别是第二个答案非常有启发性,因为我来自类概念背景而不是原型概念背景。我还翻阅了其中一些幻灯片:http://ejohn.org/apps/learn/#65,这也很有帮助。事实证明,我所要做的就是创建一个 TicketForm 实例,此时它的方法对我可用:

var myForm = new TicketForm();
myForm.enable(form); // works as expected

我有三个问题:

  1. 除了个人编码风格之外,为什么有人会选择上述方法中的一种而不是另一种?
  2. 为什么必须用第二种方法声明对象的实例,而第一种方法不用?
  3. 这些编码风格是否有专有名称?

【问题讨论】:

标签: javascript oop


【解决方案1】:

您的第一个方法定义了一个对象字面量,基本上是创建一个“单例”。如果您需要同一“类”的多个实例,则需要一个构造函数(或Object.create)。

【讨论】:

  • 我相信这回答了你所有的 3 个问题,如果没有,请告诉我。
  • 另外,也许我刚刚写的这个其他答案可能会有所帮助:stackoverflow.com/questions/17200558/…
  • Object.create 的 MDN 页面。
  • @PaulS。添加到答案中,我很懒!
  • 啊……我想我明白了。第一种方法我定义一个特定对象,有点像我在 PHP 中说的$var = new \stdclass;,而第二种方法更类似于在 PHP 中编写一个类。
【解决方案2】:

在 JavaScript 中,对象默认是可变的。这意味着除非您使用现代 JavaScript 引擎并且有人故意阻止修改对象,否则您始终可以添加、删除和修改对象中的属性。

在第一种情况下,您使用的是简化对象创建的特殊语法。 {} 语法创建一个简单的对象,它只不过是Object 的一个实例。这与 JS 中对象的可变性相结合,意味着以下 sn-ps 都是等价的:

var TicketForm = {
  elements: ['input', 'textarea', 'select', 'checkbox']
};

var TicketForm = {};
TicketForm.elements = ['input', 'textarea', 'select', 'checkbox'];

var TicketForm = new Object();
TicketForm.elements = ['input', 'textarea', 'select', 'checkbox'];

本质上使用{}类似于在经典OOP语言中创建对象的实例,而创建构造函数类似于使用类。在构造函数及其原型中,您定义了该构造函数的所有实例(共享该原型的所有对象)都将采用的蓝图。

所以这不是关于风格,而是关于你需要创造什么。如果您需要同一事物的多个副本,则使用构造函数。如果您只需要一个,只需创建一个普通对象,无需遵循礼节,制作单例并一式三份签署所有内容;)

【讨论】:

    【解决方案3】:

    第一个方法是一个“litteral object”,很像一个静态类,“this”指的是父对象“TicketForm”,你可以把它理解为一个“self”。在第二种方法中“this”指的是窗口,它不是oo,除非你做:

    var myForm = new TicketForm();
    

    这里的“this”指的是实例 myForm。这个方法是“构造函数”方法(TicketForm是构造函数)

    【讨论】:

      猜你喜欢
      • 2015-05-22
      • 2012-06-01
      • 2010-10-03
      • 1970-01-01
      • 1970-01-01
      • 2013-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多