类和构造函数的区别
ES6 之前可以通过构造函数来创建对象实例,而 ES6 提供了类来创建实例。其实,类可以看作是函数的语法糖,使用 typeof 返回的类型是 function 。类的方法都是在类的原型上,而且都是不可枚举的,构造函数中只有 constructor 函数是不可枚举的,其他都是可枚举的。
<script>
/** @name 构造函数创建对象实例 **/
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.print = function () {
console.log(`{${this.x},${this.y}}`);
};
const p = new Point(3, 4);
p.print();
console.log("🚀 ~ file: test.html:11 ~ Point:", Object.keys(Point.prototype));
console.log("🚀 ~ file: test.html:11 ~ Point:", Object.getOwnPropertyNames(Point.prototype));
/** @name 类创建对象实例 **/
class Point2 {
name = "leon";
constructor(x, y) {
this.x = x;
this.y = y;
}
print() {
console.log(`{${this.x},${this.y}}`);
}
}
const p2 = new Point2(4, 5);
p2.print();
console.log("🚀 ~ file: test.js:22 ~ Point2:", typeof Point2);
console.log("🚀 ~ file: test.js:22 ~ Point2:", Object.keys(Point2.prototype));
console.log("🚀 ~ file: test.js:22 ~ Point2:", Object.getOwnPropertyNames(Point2.prototype));
</script>
从上面可以看出,构造函数 Point 和类 Point2 都可以创建实例对象,typeof Point2 得到的结果是 function。构造函数原型的 constructor 是不可枚举的,其他新增的方法是枚举的,而类的所有方法都是不可枚举的。
constructor
constructor 方法是类的默认方法,该方法默认返回实例对象(即this),如果选择返回一个新的对象,则该类的实例化对象就是这个新对象。
<script>
class Test1 {
constructor(x) {
this.x = x;
}
}
const t1 = new Test1(1);
console.log("🚀 ~ file: test.html:9 ~ t:", t1); // Test1 {x: 1}
class Test2 {
constructor(x) {
this.x = x;
return { name: "leon" };
}
}
const t2 = new Test2(2);
console.log("🚀 ~ file: test.html:9 ~ t:", t2); // {name: 'leon'}
</script>
上面的例子中, Test1 的 constructor 方法没有修改 return 值,得到默认的实例对象。Test2 的 constructor 方法返回 { name: "leon" },导致创建实例的时候都会返回 { name: "leon" }
实例属性
除了可以在 constructor 方法中通过 this 进行定义,还可以在类的内部最顶层
<script>
class Test1 {
_count = 1;
constructor(x) {
this.x = x;
}
}
const t1 = new Test1(1);
console.log("🚀 ~ file: test.html:9 ~ t:", t1); // Test1 {_count: 1, x: 1}
</script>
从上面的例子可以看出,相比在 constructor 方法中创建的额 x 属性,类内部顶层定义的 _count 属性更加简洁,结构更加清晰。
小结
本文介绍了类和构造函数的区别,constructor 方法和实例属性。总体来说,类和构造函数在功能设计上有很多相似的地方,constructor 方法返回的内容会影响创建的对象实例,在类的内部顶层可以创建更简洁的实例属性。