这些不同的对象创建方法在JavaScript中的适当应用是什么

时间:2013-06-19 20:40:15

标签: javascript oop

我更像是一个后端人而不是前端人,但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. 这些编码样式中是否有正确的名称?

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:2)

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

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

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语言中创建对象的实例,而创建构造函数类似于使用类。在构造函数及其原型中,您定义了一个蓝图,该构造函数的所有实例(共享该原型的所有对象)都将采用。

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

答案 2 :(得分:0)

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

var myForm = new TicketForm();

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