Разница между конструктором и объектом - PullRequest
2 голосов
/ 30 декабря 2010

Мне определенно нужен свет.

Какая разница между:

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

и

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

Помимо очевидного факта, что один является Функцией, а другой Объектом , каковы различия в потоке кода, прототипах, шаблонах ... независимо от того, и когда мы должны использовать первый или второй

Я так разнесен в этой области, что не уверен, правильно ли я объясняю сомнение, но если вы спросите, можно дать дополнительную информацию.

Ответы [ 4 ]

5 голосов
/ 30 декабря 2010

Основное различие между ними заключается в том, как они предназначены для использования.Конструктор, как следует из его названия, предназначен для создания и настройки нескольких экземпляров объекта.С другой стороны, литерал объекта одноразовый , как строковые и числовые литералы, и чаще используется в качестве объектов конфигурации или глобальных одиночных кодов (например, для пространств имен).

Существует несколькотонкости первого примера:

  1. Когда код выполняется, анонимная функция создается и присваивается MY_APP, но больше ничего не происходит.firstMethod и secondMethod не существуют до тех пор, пока не будет явно вызван MY_APP.
  2. В зависимости от того, как вызывается MY_APP, методы firstMethod и secondMethod окажутся в разных местах:
    1. MY_APP(): поскольку контекст не указан, this по умолчанию window и методы станут глобальными.
    2. var app1 = new MY_APP(): из-за ключевого слова new новый объектсоздается и становится контекстом по умолчанию.this относится к новому объекту, и методы будут назначены новому объекту, который впоследствии будет присвоен app1.Однако MY_APP.firstMethod остается неопределенным.
    3. MY_APP.call(YOUR_APP): Это вызывает my MY_APP, но устанавливает контекст для другого объекта, YOUR_APP.Методы будут присвоены YOUR_APP, переопределяя любые свойства YOUR_APP с одинаковыми именами.Это действительно гибкий метод, который допускает множественное наследование или смешивание в Javascript.

Конструкторы также обеспечивают другой уровень гибкости, поскольку функции обеспечивают замыкания, а литералы объектов - нет.Если, например, firstMethod и secondMethod полагаются на общую переменную password, которая является частной для объекта (недоступен вне конструктора), это можно сделать очень просто, выполнив:

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 голосов
/ 30 декабря 2010

Конструктор может быть повторно использован как есть, литерал объекта должен быть повторен или включен в функцию для повторного использования.

Пример переноса литерала объекта в функцию:

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

Объекту, созданному с помощью конструктора, будет присвоено свойство конструктора функции конструктора. Однако, поскольку вы использовали анонимную функцию, назначенную переменной вместо именованной функции, конструктор все равно останется безымянным.

Кроме этого, нет никаких различий. Оба создают анонимные функции, которые назначаются свойствам объекта, поэтому результирующие объекты одинаковы. Это можно сравнить с назначением именованных функций свойствам или использованием функций-прототипов, причем обе имеют различие в том, что каждая функция существует только один раз, а не создается снова и снова для каждого объекта.

2 голосов
/ 30 декабря 2010

Первый - это функция, второй - литерал объекта.Поскольку функции в JS являются объектами первого класса, функция может иметь свойства, как и любой другой объект.

Как правило, если вы хотите создать «класс», с которым вы, возможно, знакомы по классическому наследованиюязыки, вы должны сделать что-то вроде

function MyClass() {...}

, как описано здесь http://www.crockford.com/javascript/inheritance.html

Чтобы ответить на вопрос, заданный в ваших изменениях, вы должны использовать их оба в разных ситуациях.Объектные литералы используются для передачи конфигураций.Типичным шаблоном использования может быть метод, который принимает литерал объекта, например,

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

и так далее.

Вы можете использовать что-то похожее на ваш первый пример при создании пространства имен.В Javascript есть несколько интересных языковых особенностей: у вас могут быть так называемые «самопризывающие функции», которые имеют вид:

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

мотивы, стоящие за чем-то подобным, подробно описаны здесь
http://sparecycles.wordpress.com/2008/06/29/advanced-javascript/

Вы также можете исследовать различия с помощью вашей любимой консоли отладки JavaScript.В Firebug и Chrome я сделал следующее:

var ol = {};ol.prototype;

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

первая строка печатает неопределенное значение, вторая возвращает прототип с конструктором 'function'

1 голос
/ 30 декабря 2010

Существует некоторая путаница в JavaScript относительно разницы между функцией и объектом.

В первом случае ,

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

или

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

функция объявлена, не объект. В MY_APP this относится к глобальному объекту.
Это означает, что вызов функции 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

Чтобы использовать MY_APP в качестве объекта, его необходимо создать, например,

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

будет иметь obj1.v, равное 3, и obj2.v, равное 4.

Обратите внимание, что вы также можете добавлять методы, используя ключевое слово prototype (вместо this.firstMethod ...)

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

Во втором случае

  var MY_APP = { ... };

объект, один объект, создан и его имя MY_APP. Ключевые слова this относятся к этому объекту MY_APP.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...