我们可以把一个方法赋值给类的函数本身,而不是赋给它的 "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 到底做了什么?
当我们使用 extends 来实现继承时,它做了两件事:
- 在构造函数的 "prototype" 之间设置原型(为了获取实例方法)
- 在构造函数之间会设置原型(为了获取静态方法)
让我们来验证一下:
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
推荐阅读 :《现代JavaScript教程》- 静态属性和静态方法