用简短语言讲明白一个知识点,带着问题学习。每日一问,聚沙成塔!
结论
-
创建一个空对象
js 引擎首先创建一个空的新对象({}
) -
将空对象的
__proto__
指向构造函数的prototype
将新对象的[[Prototype]]
(即__proto__
属性)指向构造函数的prototype
属性,建立原型继承关系 -
执行构造函数,并绑定
this
调用构造函数,将新对象作为this
的上下文,并传入参数。此时构造函数内部的代码(如属性赋值、方法定义等)会作用于新对象 -
处理返回值
若构造函数未显示返回对象(或返回基本类型值),则默认返回新对象;若构造函数返回一个对象,则代替默认对象成为结果
手写 new
function myNew(constructor, ...args) {
// 1.创建空对象&2.将空对象的__proto__指向构造函数的prototype
const obj = Object.create(constructor.prototype);
// 3. 执行构造函数,并绑定this
const result = constructor.apply(obj, args);
// 4. 处理返回值
// 处理构造函数返回非对象值和对象值的情况
return (typeof result === "object" && result !== null) ||
typeof result === "function"
? result
: obj;
}
Object.create()方法用于创建一个新对象,并将对象的原型指向第一个参数。
验证
1.正常用法
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function () {
console.log(`Hello, my name is ${this.name}, I am ${this.age} years old.`);
};
// new 方法
const person1 = new Person("Alice", 25);
person1.sayHello(); // Hello, my name is Alice, I am 25 years old
// 手写 myNew方法
const person2 = myNew(Person, "Bob", 30);
person2.sayHello(); // Hello, my name is Bob, I am 30 years old
2.构造函数返回对象
function Person(name, age) {
this.name = name;
this.age = age;
return {
name: "newName",
age: 18,
};
}
Person.prototype.sayHello = function () {
console.log(`Hello, my name is ${this.name}, I am ${this.age} years old.`);
};
// new 方法
const person1 = new Person("Alice", 25);
console.log(person1); // {name: "newName", age: 18}
person1.sayHello(); // p1.sayHello is not a function
// 手写 myNew方法
const person2 = myNew(Person, "Bob", 30);
console.log(person2); // {name: "newName", age: 18}
person2.sayHello(); // p2.sayHello is not a function
注意:当构造函数返回一个对象时:
- 返回对象的
__proto__
指向Object.prototype
(除非手动修改原型) - instanceof 运算符会失效:
result instanceof 原构造函数
返回 false - 无法通过原型链访问构造函数原型上的方法
验证及修复
console.log(person1.__proto__ === Object.prototype); // true
Object.prototype.sayHello = function () {
console.log(`Hello, my name is ${this.name}, I am ${this.age} years old.`);
};
person1.sayHello(); // Hello, my name is newName, I am 18 years old.
person2.sayHello(); // Hello, my name is newName, I am 18 years old.
3.构造函数返回基本类型值
function Animal(name) {
this.name = name;
return 123; // 返回数字
}
const a1 = new Animal("Mia");
const a2 = myNew(Animal, "Mia");
console.log(a1); // Animal {name: 'Mia'}
console.log(a2); // Animal {name: 'Mia'}
console.log(a1 instanceof Animal); // true
console.log(a2 instanceof Animal); // true
总结:
new
过程中,创建一个空对象,将空对象的__proto__
指向构造函数的prototype
,执行构造函数,并绑定this
,处理返回值。new
利用原型继承的方式,实现了构造函数的复用,避免了重复的代码。