new 调用 —— 一个函数是怎么变成对象的
new 是 this 四种调用方式 里看起来最不好理解的一种。写下 new Dog() 就拿到一个空对象,中间到底发生了什么?
为啥可以 new 一个 function ?
function Dog(name: string) {
this.name = name;
}
new Dog("大黄") 做了下面的事:
- 创建一个空对象,并把它的
__proto__指向Dog.prototype(关于原型链部分可以看文末的指引) - 把
this绑定到这个空对象,执行构造函数体 - 构造函数里的
this.xxx = ...就挂在了这个对象上 - 返回这个对象(构造函数没返回对象的话)
class 是语法糖
// class 写法:
class Dog {
name: string;
constructor(name: string) {
this.name = name;
}
bark() {
console.log(`${this.name}: 汪!`);
}
}
// 等价的原型写法:
function Dog(this: any, name: string) {
this.name = name;
}
Dog.prototype.bark = function () {
console.log(`${this.name}: 汪!`);
};
验证 class 到底是不是函数:
console.log(typeof Dog); // "function" —— class 就是 function
const d = new Dog("大黄");
console.log(d.bark === Dog.prototype.bark); // true —— 方法在原型上
这也解释了为什么箭头函数作为 class field 不共享:
class Dog {
bark() {} // → Dog.prototype.bark(所有实例共享一份)
run = () => {}; // → this.run = () => {}(每个实例独享一份)
}
run = () => {} 等价于定义一个普通属性,在 constructor 里写 this.run = () => {},挂在了实例身上,绕过了原型共享。
更多
new 回答了”对象怎么来”,但没回答”原型链上的方法怎么被找到”:
__proto__和prototype到底什么关系?- 原型链怎么一层层向上查找?
instanceof和hasOwnProperty的原理?
深入看这篇:原型链 —— 从 new 一个对象到方法共享的本质