在JavaScript中,这些不同的对象创建方法的正确应用是什么?

What are the proper applications of these different methods of object creation in JavaScript

本文关键字:方法 创建 应用 是什么 对象 JavaScript      更新时间:2023-09-26

我更喜欢后端而不是前端,但是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做了一点挖掘,发现JavaScript .prototype是如何工作的?第二个答案尤其具有启发性,因为我来自类概念背景,而不是原型概念背景。我还浏览了一些幻灯片:http://ejohn.org/apps/learn/#65,这也很有帮助。事实证明,我所要做的就是创建TicketForm的实例,此时它的方法对我可用:

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

我有三个问题:

  1. 为什么,除了个人的编码风格,一个人会选择上面的方法之一,而不是另一个?
  2. 为什么我必须用第二个方法声明对象的实例,而我不用第一个方法?
  3. 这些编码风格都有合适的名称吗?

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

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

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

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

var myForm = new TicketForm();

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