Как новый оператор работает в JavaScript? - PullRequest
38 голосов
/ 19 июля 2011

Вероятно, наименее понятная часть JavaScript, стоящая рядом с цепочкой прототипов.

Итак, вопрос в том, как ...

new dataObj(args); 

... фактически создать объект и определить его цепочку прототипов / конструкторы / etc?

Лучше всего показать альтернативу, чтобы полностью понять это ключевое слово.

Ответы [ 2 ]

50 голосов
/ 19 июля 2011

Оператор new использует внутренний метод [[Construct]] и в основном выполняет следующие действия:

  • Инициализирует новый собственный объект
  • Устанавливаетвнутренний [[Prototype]] этого объекта, указывающий на свойство Function prototype.
    • Если свойство prototype функции не является объектом (примитивные значения, такие как Number, String, Boolean, Undefined или Null), вместо него используется Object.prototype.
  • После создания объекта он вызывает функцию, предоставляя объект в качестве значения this.
  • Если возвращаемое значение вызываемой функции является примитивом, возвращается созданный внутри объект.
  • В противном случае, если объект возвращается, созданный внутри объект теряется.

Эквивалентная реализация того, что делает оператор new, может быть выражена следующим образом (вчто доступен метод ECMAScript 5 Object.create):

function NEW(f) {
  var obj, ret, proto;

  // Check if `f.prototype` is an object, not a primitive
  proto = Object(f.prototype) === f.prototype ? f.prototype : Object.prototype;

  // Create an object that inherits from `proto`
  obj = Object.create(proto);

  // Apply the function setting `obj` as the `this` value
  ret = f.apply(obj, Array.prototype.slice.call(arguments, 1));

  if (Object(ret) === ret) { // the result is an object?
    return ret;
  }
  return obj;
}

// Example usage:
function Foo (arg) {
  this.prop = arg;
}
Foo.prototype.inherited = 'baz';

var obj = NEW(Foo, 'bar');
obj.prop;          // 'bar'
obj.inherited;     // 'baz'
obj instanceof Foo // true
8 голосов
/ 19 июля 2011

Выражение new C(arg1, arg2):

Предполагается, что C является функцией JavaScript (в противном случае вы получаете сообщение об ошибке):

  1. Создает новый пустой объект (без свойств)
  2. Устанавливает прототип нового объекта в значение свойства "prototype" C.
    • Примечание. Значением по умолчанию prototype для функции является объект (автоматически создаваемый при объявлении функции) с его прототипом, установленным на Object.prototype, и свойством constructor, указывающим обратно на функцию C.
    • Примечание. Терминология может вводить в заблуждение.Свойство с именем «prototype» является , а не таким же, как и прототип объекта.Только функции имеют свойство с именем «prototype», но все объекты имеют прототип.
  3. Вызывает функцию C с 'this', установленным для нового объекта, и спредоставленные аргументы.
  4. Если вызов функции C возвращает объект, этот объект является результатом выражения.В противном случае вновь созданный объект является результатом выражения.

Альтернативой new в ECMAScript 5 будет использование встроенного метода Object.createObject.

new C(arg1, arg2)будет эквивалентно:

var obj = Object.createObject(C.prototype);
C.apply(obj, [arg1, arg2]);

Стандартный JavaScript не позволяет вам явно установить прототип объекта, поэтому Object.createObject не может быть реализовано в самом языке.Некоторые реализации позволяют это через нестандартное свойство __proto__.В этом случае new C можно смоделировать так:

var obj = {};
obj.__proto__ = C.prototype;
C.apply(obj, [arg1, arg2]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...