【问题标题】:Object literal vs constructor+prototype对象字面量与构造函数+原型
【发布时间】:2013-06-20 01:58:03
【问题描述】:

对象字面量=用大括号括起来的名称值对。

构造函数=用于使用关键字 new 创建多个实例的函数。

原型=用于文字的扩展。

这是我到目前为止所了解的。但是我研究得越多,我就越对它们每个的意义感到困惑。 我已经在我的代码中使用了几次构造函数、原型和文字。但每次我使用它们时,我都觉得我仍然没有意识到它的全部潜力。我现在想比初学者领先一步。我希望*的人们帮助我实现它

  1. 哪一种是最佳首选的编程方式(object 文字 vs 构造函数 vs 原型)

  2. 可以只使用对象字面量来编写带有构造函数和原型的代码吗 不使用构造函数和原型。

  3. 匿名函数有什么意义。

一个非常简单的例子也可以证明它们的重要性。我知道它们是什么,但我不知道它们可以发挥什么魔力。

【问题讨论】:

  • :很好的框架问题
  • “所需功能”是什么意思?
  • 任何想要的功能......我的意思是说

标签: javascript constructor prototype object-literal


【解决方案1】:

对象字面量和函数之间存在(在我看来是根本的)差异,即“私有”变量。由于一个对象不能被实例化(因为它已经是Object 的一个实例)它不可能拥有自己的(新的)作用域。它是高级 JS 编程的基本概念。拥有一个新的作用域可以让你做几乎所有事情(你可以声明你自己的windowdocument 或者你想要的任何东西,除了你自己的作用域内的 JS keywords)。现在,一些简单的例子:

假设您要创建同一对象的大量实例(使用尽可能少的行):

function MyObj(i) {
    var privateCounter = "I am the instantiated object " + i + " .";
    this.counter = function() {
        return privateCounter;
    };
}

var MyObjList = [],
    ObjLitList = [];
for (var i = 0; i < 100; i++) {
    MyObjList.push(new MyObj(i));
    ObjLitList.push({counter: "I am the literal object number " + i + "."});
}

现在您有 200 个对象,几乎,但不是精确,相同的东西。您可以随意扩展它们,因为函数 对象,但对于函数,您不能直接访问 private 变量。让我们看看函数有哪些优点:

  • 它被视为Object
  • 它有自己的Prototype
  • 它有私有变量

Objects 呢?

  • Object
  • 它没有自己的Prototype,但您可以声明函数并扩展对象本身
  • 它没有私有变量

除了私有变量之外,它们彼此没有太大区别。

让我们看看一个函数的原型能做什么:

MyObj.prototype.setX = function(x) {
    this.x = x;
}

使用原型允许您创建一个匿名函数(也可以命名然后分配)的唯一实例,该实例将在实例之间共享。你怎么能用对象字面量做同样的事情呢?

function setX(x) {
    this.x = x;
}
var obj = {
    setX: setX
};

如您所见,您必须创建定义每次属性为setX 的对象。否则,您可以扩展 Object.prototype 本身(但关于扩展原生 JS 对象的原型存在长期争论)。

那么最佳方法是什么?没有一个,这取决于你必须做什么,你需要从你的脚本中得到什么,这两者中的哪一个你觉得更舒服。

我更喜欢编写自己的函数并将它们视为类,因为它们更具可读性并且我能够使用“私有”变量。我不知道有人使用文字而不是函数。

至于问题:

哪种是最好的编程方式(对象文字 vs 构造函数 vs 原型)

已回答。

是否可以仅使用对象文字而不使用构造函数和原型来编写具有构造函数和原型的代码。

是的,如果你不需要私有变量(如果脚本不是太大的话,你可以。想象一下 jQuery 写成一个对象文字 :D)。

匿名函数的意义是什么。

好吧,我可以举个例子来回答:

//code
myNamedFunction();
//code
function myNamedFunction() {
    alert("I'm defined everywhere! :)");
}

这有效,不会生成TypeError

myAnonymousFunction();
var myAnonymousFunction = function() {
    alert("I'm defined after this declaration :(");
}
myAnonymousFunction(); // works!

这将导致Uncaught TypeError: undefined is not a function,因为myAnonymousFunction 只是对有效函数的引用(未命名,因此无法从脚本调用)。

关于这个论点有很多话要说,开始高级编程的好点是Javascript Garden。其他好的阅读是Basics of OOP in JS - NetTutsPlusWorking with Objects - MDNOOP in JS - Phrogz

希望这会有所帮助!

旁注:函数也有一个很好的优势,因为它们可以仅使用函数(例如call)来更改其上下文(this),而对象则不能。

【讨论】:

  • 它是私有的,不能从函数外部访问
  • MyObjList.push(new MyObj(i));--------------------1 ObjLitList.push({counter: "我是.......})----------2 1和2有什么区别。这个实例化就像构造函数使用new关键字一样吗?
  • 是的,第一个是使用 MyObj 函数实例化的,第二个是通过 JS 的编译器实例化的({} 计算为 new Object() 和属性的设置)。正如我所说,除了私有变量之外,函数(它本身是一个对象)和对象文字之间没有真正的区别。 JS 中的所有内容都在“已实现”!如果你做 var n = 2 它是一个数字!
  • 如果我理解正确的话,第二个例子中匿名函数中产生的TypeError是由于变量myAnonymousFunction已经在脚本顶部声明和未定义,因此TypeError undefined is not a function。跟js有关hoisting.
  • 是的。但是当时我写的答案我对JS的吊装还不太了解,所以我试图在没有任何证据的情况下自己证明它的合理性。该变量在脚本的顶部被提升,但具有未定义的值,这不是一个函数,因此是 TypeError。事实上,如果你尝试调用一个甚至没有声明的函数,你会得到一个 ReferenceError,告诉“x 未定义”,这与“未定义”有很大不同 :) 感谢您指出,希望已经清楚!