Это 8-й день моего участия в августовском испытании обновлений.Подробности о событии:Испытание августовского обновления
определение
new
Примеры примера Оператор для создания пользовательского типа объекта или встроенные объекты, имеющие конструктор.
использоватьnew [constructor]
new
Вызов оператора является конструктором, а неnew
Функция, вызываемая оператором, является нормальной функцией.
Таким образом, конструкторы также могут иметь возвращаемые значения, но это приводит кnew
результаты разные.
Нет возвращаемого значения
function Person(name) {
this.name = name;
}
let obj = new Person("Jalenl");
console.log(obj);
Видимо, что печатает{name:'Jalenl'}
возвращаемый объект
function Person(age) {
this.age = age;
return { name: "Jalenl" };
}
let obj = new Person(18);
console.log(obj);
печать{name:'Jalenl'}
, то естьreturn
Все предыдущие определения перезаписываются. здесьreturn
является объектом, что, если он возвращает примитивный тип?
Вернуть не объект
function Person(age) {
this.age = age;
return 1;
}
let obj = new Person(18);
console.log(obj);
вернуть{age:21}
,такreturn
Неудача, следующаяreturn
тот же результат, если неthis
Привязать внутренние свойства, вернуться к базовому типу данных?
function Person(){
return 1
}
new Person()
{}
, Ожидал.
Таким образом, только конструкторreturn
Возвращение - это тип объекта, чтобы изменить начальные результаты.
Различные типы конструкторов
Конструктор — это обычная функция
ECMA-262 3rd. Edition Specification
Создание экземпляра объекта описано в:
13.2.2
[[Construct]]
When the
[[Construct]]
property for aFunction
objectF
is called, the following steps are taken:
- Create a new native ECMAScript object.
- Set the
[[Class]]
property ofResult(1)
to"Object"
.- Get the value of the prototype property of
F
.- If
Result(3)
is an object, set the[[Prototype]]
property ofResult(1)
toResult(3)
.- If
Result(3)
is not an object, set the[[Prototype]]
property ofResult(1)
to the originalObject
prototype object as described in 15.2.3.1.- Invoke the
[[Call]]
property ofF
, providingResult(1)
as thethis
value and providing the argument list passed into[[Construct]]
as the argument values.- If
Type(Result(6))
isObject
then returnResult(6)
.- Return
Result(1)
.
Подвести итог:
- Создайте новый объект в памяти.
- внутри этого нового объекта
[[Prototype]]
Атрибут присваивается конструкторуprototype
Атрибуты. - внутри конструктора
this
присваивается этому новому объекту (т.е.this
указать на новый объект). - Выполнить код внутри конструктора (добавить свойства в новый объект).
- Если конструктор возвращает объект, верните этот объект, в противном случае верните только что созданный новый объект (пустой объект).
Пятый шаг уже объяснил, что разные конструкторы вызываютnew
Причина разных результатов.
Следующее взято изMDN
объяснение:
При выполнении кода new Foo(…) происходит следующее:
- Создается новый объект, наследуемый от Foo.prototype.
- Указанные параметры вызывают конструктор Foo, который привязывается к вновь созданному объекту. новый Foo эквивалентен новому Foo(), то есть не указан список аргументов, ситуация Foo без параметров вызова.
- 由构造函数返回的对象就是 new 表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤1创建的对象。 (В обычных условиях конструктор не возвращает значение, но пользователь может активно возвращать объект, чтобы переопределить обычные шаги создания объекта.)
prototype
constructor
function Person(){
this.age = 18;
}
Person.prototype
/**
{
constructor: ƒ Foo()
__proto__: Object
}
**/
Когда вы создаете стрелочную функцию, движок ее не создаст.prototype
свойства, стрелочные функции неconstructor
дляnew
Звоните, так что используйтеnew
Вызов стрелочной функции вызовет ошибку!
const Person = ()=>{}
new Person()//TypeError: Foo is not a constructor
рукописный новый
В общем, знакомоnew
После принципа работы мы можем реализовать низкопрофильную версию самостоятельно.new
, ключ к достижению:
- Разрешить экземпляру иметь доступ к закрытым свойствам;
- Сделать экземпляр доступным для конструктора-прототипа (
constructor.prototype
function _new(constructor, ...args) {
// 构造函数类型合法判断
if(typeof constructor !== 'function') {
throw new Error('constructor must be a function');
}
// 新建空对象实例
let obj = new Object();
// 将构造函数的原型绑定到新创的对象实例上
obj.__proto__ = Object.create(constructor.prototype);
// 调用构造函数并判断返回值
let res = constructor.apply(obj, args);
let isObject = typeof res === 'object' && res !== null;
let isFunction = typeof res === 'function';
// 如果有返回值且返回值是对象类型,那么就将它作为返回值,否则就返回之前新建的对象
return isObject || isFunction ? res : obj;
};
new
Реализация может использоваться для создания экземпляра пользовательского класса, но не поддерживает встроенные объекты, в конце концовnew
Он принадлежит оператору, а базовая реализация более сложна.