Как новый оператор работает в JavaScript?
Вероятно, наименее понятная часть JavaScript, стоящая рядом с цепочкой прототипов.
Итак, вопрос: как...
new dataObj(args);
... на самом деле создать объект и определить его прототип chain/constructors/etc?
Лучше всего показать альтернативу, чтобы полностью понять это ключевое слово.
Ответы
Ответ 1
Оператор 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
Ответ 2
Выражение new C(arg1, arg2)
:
Предполагая, что C является функцией JavaScript (иначе вы получите сообщение об ошибке):
- Создает новый пустой объект (без свойств)
- Устанавливает прототип нового объекта в значение
"
prototype
" свойство C
.
- Примечание. Значение по умолчанию для
prototype
для функции - это объект (автоматически созданный при объявлении функции), с его прототипом, установленным на Object.prototype
и a constructor
свойство, возвращающее функцию C
.
- Примечание. Терминология может вводить в заблуждение. Свойство с именем "prototype" не совпадает с прототипом объекта. Только функции имеют свойство с именем "prototype", но все объекты имеют прототип.
- Вызывает функцию
C
с 'this
', установленную для нового объекта, и с прилагаемыми аргументами.
- Если вызов функции
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]);