JavaScript中class的静态属性和静态⽅法我们可以把⼀个⽅法赋值给类的函数本⾝,⽽不是赋给它的 "prototype" 。这样的⽅法被称为静态的(static)。例如这样:
class Animal {
static staticProperty = 'staticProperty'
static staticMethod() {
console.log('staticMethod');
}
}
它们等价于这样:
class Animal {}
Animal.staticProperty = 'staticProperty';
Animal.staticMethod = function() {
console.log('staticMethod')
}
在静态⽅法中 this 指向当前类
class Animal {
static staticProperty = 'staticProperty'
static staticMethod() {
console.log(this === Animal);
}
}
Animal.staticMethod();//true
静态属性和⽅法是可被继承的
class People {
static homeland = '中国';
static staticMethod() {
console.log(`${this.homeland}-${this.name}`);
}
}
class Peng extends People {
static name = '谢展鹏';
}
Peng.staticMethod();//中国-谢展鹏
为什么静态属性是可继承的,extends 到底做了什么?
函数prototype
当我们使⽤ extends 来实现继承时,它做了两件事:
1. 在构造函数的 "prototype" 之间设置原型(为了获取实例⽅法)
2. 在构造函数之间会设置原型(为了获取静态⽅法)
让我们来验证⼀下:
class Animal{
static staticProperty = 'static Property';
static staticMethod() {
console.log('staticMethod');
}
run() {
console.log('I\'m running!');
}
}
class Rabbit extends Animal{}
console.log(Rabbit.__proto__ === Animal);// true
Object.keys(Rabbit.__proto__).forEach(k=>console.log(k)); //staticPropert
new Rabbit().run(); //I'm running!
console.log(Rabbit.prototype.__proto__ === Animal.prototype);//true
//解释⼀下: 因为 const rabbit = new Rabbit() 实例并没有run⽅法,所以实例在原型链上查,⼤概顺序是这样的
// rabbit -> rabbit.__proto__(Rabbit.prototype) -> rabbit.__proto__.proto__(Animal.prototype)
在JS中所有函数的默认__proto__都是Function.prototype,对于内建的 Object 构造函数⽽⾔,Object.__proto__ === Function.prototype