构造函数和对象之间的区别

时间:2021-01-05 16:34:25

I definitely need some light on this.

我确实需要了解一下。

What's the diference between:

有什么不同:

var MY_APP = function(){
    this.firstMethod = function(){
       //something
    };
    this.secondMethod = function(){
       //something
    };
};

and

var MY_APP = {
    firstKey: function(){
       //something
    },
    secondKey: function(){
       //something
    }
};

besides the obvious fact that one is a Function and the other an Object, what are the differences in code flow, prototypes, patterns... whatever, and when should we use the first or the second?

除了一个是函数,另一个是对象这一明显事实之外,代码流、原型、模式的区别是什么……无论如何,我们应该在什么时候使用第一个还是第二个?

I'm so spaced out in this area that i'm not sure if i'm correctly explaining the doubt, but further info can be given if you ask.

我在这一领域很分散,我不确定我是否正确地解释了疑问,但如果你问的话,可以提供更多的信息。

4 个解决方案

#1


5  

The key difference between the two is in how they are intended to be used. A constructor, as its name suggests, is designed to create and set up multiple instances of an object. An object literal on the other hand is one-off, like string and number literals, and used more often as configuration objects or global singletons (e.g. for namespacing).

两者之间的关键区别在于如何使用它们。顾名思义,构造函数是用来创建和设置一个对象的多个实例的。另一方面,对象文字是一次性的,比如字符串和数字文字,更经常用作配置对象或全局单例(例如,命名空间)。

There are a few subtleties about the first example to note:

关于第一个要注意的例子有一些微妙之处:

  1. When the code is executed, an anonymous function is created and assigned to MY_APP, but nothing else happens. firstMethod and secondMethod don't exist until MY_APP is explicitly called.
  2. 当执行代码时,会创建一个匿名函数并分配给MY_APP,但不会发生其他事情。firstMethod和secondMethod在MY_APP被明确调用之前不存在。
  3. Depending on how MY_APP is called, the methods firstMethod and secondMethod will end up in different places:
    1. MY_APP(): Since no context is supplied, the this defaults to window and the methods will become global.
    2. MY_APP():由于没有提供上下文,所以默认为window,方法将变为全局。
    3. var app1 = new MY_APP(): Due to the new keyword, a new object is created and becomes the default context. this refers to the new object, and the methods will get assigned to the new object, which subsequently gets assigned to app1. However, MY_APP.firstMethod remains undefined.
    4. var app1 = new MY_APP():由于new关键字,一个新对象被创建并成为默认上下文。这指的是新对象,方法将被分配给新对象,新对象随后被分配给app1。然而,MY_APP。firstMethod仍是未定义的。
    5. MY_APP.call(YOUR_APP): This calls my MY_APP but sets the context to be another object, YOUR_APP. The methods will get assigned to YOUR_APP, overriding any properties of YOUR_APP with the same names. This is a really flexible method that allows multiple inheritance or mixins in Javascript.
    6. 调用(YOUR_APP):它调用我的MY_APP,但将上下文设置为另一个对象YOUR_APP。这些方法将被分配给YOUR_APP,用相同的名字覆盖YOUR_APP的所有属性。这是一个非常灵活的方法,允许在Javascript中进行多重继承或混合。
  4. 根据调用MY_APP的方式,方法firstMethod和secondMethod将在不同的地方结束:MY_APP():由于没有提供上下文,因此默认为窗口,这些方法将成为全局的。var app1 = new MY_APP():由于new关键字,一个新对象被创建并成为默认上下文。这指的是新对象,方法将被分配给新对象,新对象随后被分配给app1。然而,MY_APP。firstMethod仍是未定义的。调用(YOUR_APP):它调用我的MY_APP,但将上下文设置为另一个对象YOUR_APP。这些方法将被分配给YOUR_APP,用相同的名字覆盖YOUR_APP的所有属性。这是一个非常灵活的方法,允许在Javascript中进行多重继承或混合。

Constructors also allow another level of flexibility since functions provide closures, while object literals do not. If for example firstMethod and secondMethod rely on a common variable password that is private to the object (cannot be accessed outside the constructor), this can be achieved very simply by doing:

构造函数还允许另一种灵活性,因为函数提供闭包,而对象文字则没有。例如,如果firstMethod和secondMethod依赖于对象私有的通用变量密码(不能在构造函数之外访问),可以通过以下操作来实现:

var MY_APP = function(){
    var password = "GFHSFG";

    this.firstMethod = function(){
       // Do something with password
       alert(password); // Woops!
    };
    this.secondMethod = function(){
       // Do something else with password
    };
};

MY_APP();

alert(password); // undefined
alert(MY_APP.password); // undefined

#2


2  

The first is a function, the second is an object literal. Since Functions in JS are first class objects, a function can have properties on it, just like any other object can.

第一个是函数,第二个是对象文字。由于JS中的函数是第一类对象,所以函数可以像其他对象一样在其上具有属性。

Typically, if you want to create a "class" that you might be familiar with from classical inheritance languages, you would do something like

通常,如果您想要创建一个您可能从经典继承语言中熟悉的“类”,您可以执行以下操作

function MyClass() {...}

as is documented here http://www.crockford.com/javascript/inheritance.html

如下所示:http://www.crockford.com/javascript/inheritance.html。

To answer the question posed in your edits, you would use them both in different situations. Object literals are used to pass configurations around. A typical usage pattern would be a method that accepts an object literal like so

要回答编辑所提出的问题,您可以在不同的情况下使用它们。对象常量用于传递配置。一个典型的使用模式是一个方法,它接受一个像so这样的对象

 something.init({
      length: 10,
      height: 10,
      text: 'some text'
 });

and so on.

等等。

You could use something similar to your first example when creating a namespace. Javascript has some interesting language features in that you can have so-called "self-invoking functions" that are of the form:

您可以在创建名称空间时使用与第一个示例类似的东西。Javascript有一些有趣的语言特性,您可以拥有所谓的“自调用函数”,其形式如下:

var myApp = (function(){
    var firstMethod = function() {...}
    ...
})();

the motivations behind doing something like this are detailed here
http://sparecycles.wordpress.com/2008/06/29/advanced-javascript/

这样做的动机在http://sparecycles.wordpress.com/2008/06/29/advanced-javascript/中有详细说明

You can also investigate the differences via your favorite javascript debugging console. In firebug and chrome, I did the following:

您还可以通过您最喜欢的javascript调试控制台来研究差异。在firebug和chrome中,我做了以下工作:

var ol = {}; ol.prototype;

var ol = { };ol.prototype;

var fn = function(){}; fn.prototype;

var fn = function(){ };fn.prototype;

the first line prints undefined, the second returns a prototype with a constructor of 'function'

第一行打印未定义,第二行返回带有“function”构造函数的原型

#3


2  

The constructor can be reused as is, the object literal would need to be repeated or wrapped in a function to be reused.

构造函数可以按原样重用,对象文本需要重复或包装在函数中才能重用。

Example of wrapping the object literal in a function:

在函数中包装对象文字的示例:

function MY_APP() {
  return {
    firstKey: function(){
       //something
    },
    secondKey: function(){
       //something
    }
  };
}

The object created using the constructor will have it's constructor property set to the constructor function. However, as you used an anonymous function assigned to a variable instead of a named function, the constructor will still be nameless.

使用构造函数创建的对象将其构造函数属性设置为构造函数。但是,当您使用一个匿名函数而不是命名函数时,构造函数仍然是匿名的。

Other than that, there isn't really any differences. Both create anonymous functions that are assigned to the properties of the object, so the resulting objects are the same. You can compare this to assigning named functions to the properties, or using prototype functions, both having the difference that each function only exists once instead of being created over and over for each object.

除此之外,没有什么区别。两者都创建分配给对象属性的匿名函数,因此结果对象是相同的。您可以将其与为属性分配命名函数或使用原型函数进行比较,两者的区别在于每个函数只存在一次,而不是为每个对象创建一次又一次的函数。

#4


1  

There is some confusion in JavaScript regarding the difference between a function and an object.

关于函数和对象之间的区别,JavaScript中存在一些混乱。

In the first case,

在第一种情况下,

  var MY_APP = function() { this.v = 7; ... }

or

  function MY_APP(x) { this.v = x; ... }

a function is declared, not an object. In MY_APP, this refers to the global object.
Meaning that calling the function MY_APP(7) will assign v globally to the value of 7. (and in your case the function firstMethod would be declared globally).

函数被声明,而不是对象。在MY_APP中,这指的是全局对象。这意味着调用函数MY_APP(7)会将v全局赋值为7。(在您的情况下,函数firstMethod将在全局声明)。

  MY_APP(3);  // The global variable v is set to 3
  MY_APP(4);  // The global variable v is overwritten and set to 4

To use MY_APP as an object, it needs to be instantiated, for instance

要使用MY_APP作为对象,需要实例化它,例如

  var obj1 = new MY_APP(3);
  var obj2 = new MY_APP(4);

will have obj1.v to be 3, and obj2.v to be 4.

其中obj1。v等于3,而obj2。4 v。

Note you can also add methods using the prototype keyword (instead of this.firstMethod...)

注意,您还可以使用prototype关键字添加方法(而不是this.firstMethod…)

  MY_APP.prototype.firstMethod = function () { ... }

In the second case

在第二种情况下

  var MY_APP = { ... };

an object, one object, is created and its name is MY_APP. The this keywords refers to that object, MY_APP.

一个对象,一个对象,被创建,它的名字是MY_APP。这个关键字指的是这个对象MY_APP。

#1


5  

The key difference between the two is in how they are intended to be used. A constructor, as its name suggests, is designed to create and set up multiple instances of an object. An object literal on the other hand is one-off, like string and number literals, and used more often as configuration objects or global singletons (e.g. for namespacing).

两者之间的关键区别在于如何使用它们。顾名思义,构造函数是用来创建和设置一个对象的多个实例的。另一方面,对象文字是一次性的,比如字符串和数字文字,更经常用作配置对象或全局单例(例如,命名空间)。

There are a few subtleties about the first example to note:

关于第一个要注意的例子有一些微妙之处:

  1. When the code is executed, an anonymous function is created and assigned to MY_APP, but nothing else happens. firstMethod and secondMethod don't exist until MY_APP is explicitly called.
  2. 当执行代码时,会创建一个匿名函数并分配给MY_APP,但不会发生其他事情。firstMethod和secondMethod在MY_APP被明确调用之前不存在。
  3. Depending on how MY_APP is called, the methods firstMethod and secondMethod will end up in different places:
    1. MY_APP(): Since no context is supplied, the this defaults to window and the methods will become global.
    2. MY_APP():由于没有提供上下文,所以默认为window,方法将变为全局。
    3. var app1 = new MY_APP(): Due to the new keyword, a new object is created and becomes the default context. this refers to the new object, and the methods will get assigned to the new object, which subsequently gets assigned to app1. However, MY_APP.firstMethod remains undefined.
    4. var app1 = new MY_APP():由于new关键字,一个新对象被创建并成为默认上下文。这指的是新对象,方法将被分配给新对象,新对象随后被分配给app1。然而,MY_APP。firstMethod仍是未定义的。
    5. MY_APP.call(YOUR_APP): This calls my MY_APP but sets the context to be another object, YOUR_APP. The methods will get assigned to YOUR_APP, overriding any properties of YOUR_APP with the same names. This is a really flexible method that allows multiple inheritance or mixins in Javascript.
    6. 调用(YOUR_APP):它调用我的MY_APP,但将上下文设置为另一个对象YOUR_APP。这些方法将被分配给YOUR_APP,用相同的名字覆盖YOUR_APP的所有属性。这是一个非常灵活的方法,允许在Javascript中进行多重继承或混合。
  4. 根据调用MY_APP的方式,方法firstMethod和secondMethod将在不同的地方结束:MY_APP():由于没有提供上下文,因此默认为窗口,这些方法将成为全局的。var app1 = new MY_APP():由于new关键字,一个新对象被创建并成为默认上下文。这指的是新对象,方法将被分配给新对象,新对象随后被分配给app1。然而,MY_APP。firstMethod仍是未定义的。调用(YOUR_APP):它调用我的MY_APP,但将上下文设置为另一个对象YOUR_APP。这些方法将被分配给YOUR_APP,用相同的名字覆盖YOUR_APP的所有属性。这是一个非常灵活的方法,允许在Javascript中进行多重继承或混合。

Constructors also allow another level of flexibility since functions provide closures, while object literals do not. If for example firstMethod and secondMethod rely on a common variable password that is private to the object (cannot be accessed outside the constructor), this can be achieved very simply by doing:

构造函数还允许另一种灵活性,因为函数提供闭包,而对象文字则没有。例如,如果firstMethod和secondMethod依赖于对象私有的通用变量密码(不能在构造函数之外访问),可以通过以下操作来实现:

var MY_APP = function(){
    var password = "GFHSFG";

    this.firstMethod = function(){
       // Do something with password
       alert(password); // Woops!
    };
    this.secondMethod = function(){
       // Do something else with password
    };
};

MY_APP();

alert(password); // undefined
alert(MY_APP.password); // undefined

#2


2  

The first is a function, the second is an object literal. Since Functions in JS are first class objects, a function can have properties on it, just like any other object can.

第一个是函数,第二个是对象文字。由于JS中的函数是第一类对象,所以函数可以像其他对象一样在其上具有属性。

Typically, if you want to create a "class" that you might be familiar with from classical inheritance languages, you would do something like

通常,如果您想要创建一个您可能从经典继承语言中熟悉的“类”,您可以执行以下操作

function MyClass() {...}

as is documented here http://www.crockford.com/javascript/inheritance.html

如下所示:http://www.crockford.com/javascript/inheritance.html。

To answer the question posed in your edits, you would use them both in different situations. Object literals are used to pass configurations around. A typical usage pattern would be a method that accepts an object literal like so

要回答编辑所提出的问题,您可以在不同的情况下使用它们。对象常量用于传递配置。一个典型的使用模式是一个方法,它接受一个像so这样的对象

 something.init({
      length: 10,
      height: 10,
      text: 'some text'
 });

and so on.

等等。

You could use something similar to your first example when creating a namespace. Javascript has some interesting language features in that you can have so-called "self-invoking functions" that are of the form:

您可以在创建名称空间时使用与第一个示例类似的东西。Javascript有一些有趣的语言特性,您可以拥有所谓的“自调用函数”,其形式如下:

var myApp = (function(){
    var firstMethod = function() {...}
    ...
})();

the motivations behind doing something like this are detailed here
http://sparecycles.wordpress.com/2008/06/29/advanced-javascript/

这样做的动机在http://sparecycles.wordpress.com/2008/06/29/advanced-javascript/中有详细说明

You can also investigate the differences via your favorite javascript debugging console. In firebug and chrome, I did the following:

您还可以通过您最喜欢的javascript调试控制台来研究差异。在firebug和chrome中,我做了以下工作:

var ol = {}; ol.prototype;

var ol = { };ol.prototype;

var fn = function(){}; fn.prototype;

var fn = function(){ };fn.prototype;

the first line prints undefined, the second returns a prototype with a constructor of 'function'

第一行打印未定义,第二行返回带有“function”构造函数的原型

#3


2  

The constructor can be reused as is, the object literal would need to be repeated or wrapped in a function to be reused.

构造函数可以按原样重用,对象文本需要重复或包装在函数中才能重用。

Example of wrapping the object literal in a function:

在函数中包装对象文字的示例:

function MY_APP() {
  return {
    firstKey: function(){
       //something
    },
    secondKey: function(){
       //something
    }
  };
}

The object created using the constructor will have it's constructor property set to the constructor function. However, as you used an anonymous function assigned to a variable instead of a named function, the constructor will still be nameless.

使用构造函数创建的对象将其构造函数属性设置为构造函数。但是,当您使用一个匿名函数而不是命名函数时,构造函数仍然是匿名的。

Other than that, there isn't really any differences. Both create anonymous functions that are assigned to the properties of the object, so the resulting objects are the same. You can compare this to assigning named functions to the properties, or using prototype functions, both having the difference that each function only exists once instead of being created over and over for each object.

除此之外,没有什么区别。两者都创建分配给对象属性的匿名函数,因此结果对象是相同的。您可以将其与为属性分配命名函数或使用原型函数进行比较,两者的区别在于每个函数只存在一次,而不是为每个对象创建一次又一次的函数。

#4


1  

There is some confusion in JavaScript regarding the difference between a function and an object.

关于函数和对象之间的区别,JavaScript中存在一些混乱。

In the first case,

在第一种情况下,

  var MY_APP = function() { this.v = 7; ... }

or

  function MY_APP(x) { this.v = x; ... }

a function is declared, not an object. In MY_APP, this refers to the global object.
Meaning that calling the function MY_APP(7) will assign v globally to the value of 7. (and in your case the function firstMethod would be declared globally).

函数被声明,而不是对象。在MY_APP中,这指的是全局对象。这意味着调用函数MY_APP(7)会将v全局赋值为7。(在您的情况下,函数firstMethod将在全局声明)。

  MY_APP(3);  // The global variable v is set to 3
  MY_APP(4);  // The global variable v is overwritten and set to 4

To use MY_APP as an object, it needs to be instantiated, for instance

要使用MY_APP作为对象,需要实例化它,例如

  var obj1 = new MY_APP(3);
  var obj2 = new MY_APP(4);

will have obj1.v to be 3, and obj2.v to be 4.

其中obj1。v等于3,而obj2。4 v。

Note you can also add methods using the prototype keyword (instead of this.firstMethod...)

注意,您还可以使用prototype关键字添加方法(而不是this.firstMethod…)

  MY_APP.prototype.firstMethod = function () { ... }

In the second case

在第二种情况下

  var MY_APP = { ... };

an object, one object, is created and its name is MY_APP. The this keywords refers to that object, MY_APP.

一个对象,一个对象,被创建,它的名字是MY_APP。这个关键字指的是这个对象MY_APP。