Это 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 aFunctionobjectFis 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 originalObjectprototype object as described in 15.2.3.1.- Invoke the
[[Call]]property ofF, providingResult(1)as thethisvalue and providing the argument list passed into[[Construct]]as the argument values.- If
Type(Result(6))isObjectthen returnResult(6).- Return
Result(1).
Подвести итог:
- Создайте новый объект в памяти.
- внутри этого нового объекта
[[Prototype]]Атрибут присваивается конструкторуprototypeАтрибуты. - внутри конструктора
thisприсваивается этому новому объекту (т.е.thisуказать на новый объект). - Выполнить код внутри конструктора (добавить свойства в новый объект).
- Если конструктор возвращает объект, верните этот объект, в противном случае верните только что созданный новый объект (пустой объект).
Пятый шаг уже объяснил, что разные конструкторы вызываютnewПричина разных результатов.
Следующее взято изMDNобъяснение:
При выполнении кода new Foo(…) происходит следующее:
- Создается новый объект, наследуемый от Foo.prototype.
- Указанные параметры вызывают конструктор Foo, который привязывается к вновь созданному объекту. новый Foo эквивалентен новому Foo(), то есть не указан список аргументов, ситуация Foo без параметров вызова.
- 由构造函数返回的对象就是 new 表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤1创建的对象。 (В обычных условиях конструктор не возвращает значение, но пользователь может активно возвращать объект, чтобы переопределить обычные шаги создания объекта.)
prototypeconstructor
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Он принадлежит оператору, а базовая реализация более сложна.