关于构造器constructor
在function
定义的构造函数中,其prototype.constructor
属性指向构造器自身
在class
定义的类中,constructor
其实也相当于定义在prototype
属性上
class Point {
constructor() {
// ...这了可以定义实例属性
this.a = 1;
}
toString() {
// ...
}
toValue() {
// ...
}
}
// 等同于
Point.prototype = {
constructor() {},
toString() {},
toValue() {},
};
重复定义
- function会覆盖之前定义的方法
- class会报错
原型或者类中方法的枚举
class
中定义的方法不可用Object.keys(Point.prototype)
枚举到function
构造器原型方法可被Object.keys(Point.prototype)
枚举到,除过constructor
- 所有原型方法属性都可用
Object.getOwnPropertyNames(Point.prototype)
访问到
class Point {
constructor(x, y) {
// ...
}
toString() {
// ...
}
}
Object.keys(Point.prototype)
// []
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString"]
var Point = function (x, y) {
// ...
};
Point.prototype.toString = function() {
// ...
};
Object.keys(Point.prototype)
// ["toString"]
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString"]
不管是class
还是function,constructor
属性默认不可枚举
都可通过实例的__proto__属性向原型添加方法
推荐使用Object.getPrototypeOf()获取实例原型后再添加方法
class没有变量提升
new Foo();
class Foo {}
VM21735:1 Uncaught ReferenceError: Foo is not defined
at <anonymous>:1:1
class定义的类没有私有方法和私有属性
可以用symbol模拟
const bar = Symbol('bar');
const snaf = Symbol('snaf');
export default class myClass{
// 公有方法
foo(baz) {
this[bar](baz);
}
// 私有方法
[bar](baz) {//[bar]用方括号代表从表达式获取的属性名
return this[snaf] = baz;
}
// ...
};
由于bar为symbol值,因此在外面不能当做函数使用。
this指向
class用类似于解构的方式获取原型上的方法
class Logger {
constructor(){}
printName(name = 'there') {
this.print(`Hello ${name}`);
}
print(text) {
console.log(text);
}
}
const logger = new Logger();
const { constructor,print,printName } = logger;
但是执行printName()时,他的this并不是指向当前实例,可在constructor中重新绑定:
constructor() {
this.printName = this.printName.bind(this);
}
class静态方法与静态属性
- class定义的静态方法前加static关键字
- 只能通过类名调用
- 不能通过实例调用
- 可与实例方法重名
- 静态方法中的this指向类而非实例
- 静态方法可被继承
- 在子类中可通过super方法调用父类的静态方法
class内部没有静态属性,只能在外面通过类名定义。
new.target
- new target属性指向当前的构造函数,不能在构造函数外部调用会报错,
function Person(name) {
console.log(new.target);
if (new.target !== undefined) {
this.name = name;
} else {
throw new Error('必须使用new生成实例');
}
}
测试:
Person(123)
undefined
Uncaught Error: 必须使用new生成实例
2.继承时new.target返回子类
class Rectangle {
constructor(length, width) {
console.log(new.target === Rectangle);
// ...
}
}
class Square extends Rectangle {
constructor(length) {
super(length, length);
}
}
var obj = new Square(3); // 输出 false
可构造不能被实例化的类,只能通过继承发挥作用:
class Shape {
constructor() {
if (new.target === Shape) {
throw new Error('本类不能实例化');
}
}
}
class Rectangle extends Shape {
constructor(length, width) {
super();
// ...
}
}
var x = new Shape(); // 报错
var y = new Rectangle(3, 4); // 正确