对象字面量 vs 构造函数+原型

38

对象字面量=包含名称和值的花括号封装。

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

原型=用于扩展字面量。

这是我目前了解到的。但是,我越是研究,就越感到混乱,不知道每一个的重要性是什么。 我在我的代码中有时使用构造函数、原型和字面量。但每次使用它们时,我觉得我仍然不知道它们的全部潜力。我希望现在能够迈出成为初学者之外的一步。我希望stackoverflow的伙伴们能够帮助我实现这一点。

  1. 哪种编程方式(对象字面量 vs 构造函数 vs 原型)是最佳首选?

  2. 是否可以使用只有对象字面量而没有使用构造函数和原型的代码来编写具有构造函数和原型的代码。

  3. 匿名函数的意义是什么。

一个简单的演示它们重要性的例子也可以。我知道它们是什么,但不知道它们能够产生什么神奇的效果


优美的问题陈述 - user2412575
"Desired functionality" 的意思是什么? - Niccolò Campolungo
任何所需的功能...我的意思是 - HIRA THAKUR
1个回答

29

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

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

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。其他好的阅读材料包括JS面向对象基础 - NetTutsPlus操作对象 - MDN以及JS中的面向对象编程 - Phrogz
希望这有所帮助!
附注:函数还有一个很好的优势,它们可以通过函数(例如call)轻松更改上下文(this),而对象则不能。

MyObjList.push(new MyObj(i));--------------------1ObjLitList.push({counter: "I am.......})----------2这两行代码有何不同? 这种实例化方式类似于使用new关键字的构造函数吗? - HIRA THAKUR
1
如果我理解正确的话,第二个例子中匿名函数生成的 TypeError 是由于变量 myAnonymousFunction 在脚本顶部被声明但未定义,因此出现了 TypeError undefined is not a function。这与 JavaScript 的“提升”有关。 - snw
是的,没错。但是当我写答案时,我对JS的变量提升还不是很了解,所以我试图在没有任何证据的情况下自己证明它。变量被提升到脚本的顶部,但其值为undefined,这不是一个函数,因此会出现TypeError错误。实际上,如果您尝试调用甚至未声明的函数,则会出现ReferenceError,告诉您“x未定义”,这与“undefined”非常不同 :) 感谢您指出这一点,希望我已经讲清楚了! - Niccolò Campolungo
感谢您的分享。如果我可以为“Uncaught TypeError”示例中调用myAnonymousFunction()提供一个更正的建议,那么这个错误的原因是只有变量_声明_被提升(例如var a;),而不是赋值(例如a ='foo';),这意味着在那一点上甚至不是对函数的引用。这就是为什么您没有ReferenceError,在这种情况下,这意味着变量在执行或嵌套范围中没有被_声明_。 - gmsecrieru
这个答案让我的生活重新有了价值。谢谢Nico。 - Amin Mohamed Ajani
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接