1.静态方法
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来嗲用,这就称为静态方法。
class P { static show() { console.log('这是类的静态方法') } } const p1 = new P() P.show() // 这是类的静态方法 p1.show() // p1.show is not a function
上面代码中,P类有个静态方法,可以直接通过P类调用该方法,但是如果通过P类的实例来调用该方法,则会抛出一个错误,表示不存在该方法。
且,如果静态方法上包含this关键字,这个this指的是类,而不是实例。
class P { static show() { this.foo() } static foo() { console.log('hello') } foo() { console.log('world') } } P.show() // hello
上面代码中,P类的静态方法show调用了this.foo。这里的this值得是P类,而不是foo的实例,等同于调用了P.foo。另外还可以看出,静态方法可以与非静态方法重名。
父类的静态方法是可以被子类继承的:
class P { static show() { console.log('这是类的静态方法') } } class Bar extends P {} Bar.show() // 这是类的静态方法
静态方法也是可以从super对象上调用的:
class P { static show() { console.log('这是P类的静态方法') } } class Bar extends P { static show() { super.show() console.log('这时Bar类的静态方法') } } Bar.show() // 这是类的静态方法 // 这时Bar类的静态方法
2.静态属性
静态属性指的是Class本身的属性,而不是定义在实例对象上的属性。
class Foo{ } Foo.prop = 1 Foo.prop // 1
上面的写法为Foo类定义了一个静态属性prop。
目前,只有这种写法可行,因为ES6明确规定,Class内部只有静态方法,没有静态属性。现在有一个提案提供了类的静态属性,写法是在实例属性的前面,加上static关键字。
class P { static myStaticProp = 12 constructor() { console.log(P.myStaticProp) } }
这个写法大大方便了静态属性的表达
// 老写法 class Foo { // ... } Foo.prop = 1; // 新写法 class Foo { static prop = 1; }
3.私有方法和私有属性
私有方法和私有属性,是只能在类的内部访问的方法和属性,外部不能访问。这是常见需求,有利于代码的封装,但是ES6不提供,只能通过变通方法实现
方法一:
在命名上加以区别。
class P { // 公有方法 foo(bar) { this._bar(baz) } // 私有方法 _bar(baz) { return (this.snaf = baz) } }
上面代码中_baz方法前面的下划线,表示这是一个只限于内部使用的私有方法。但是这样处理,在类的外部还是可以调用到这个方法。
方法二:
索性将私有方法移出类,因为类内部的所有方法都是对外可见的。
class P { foo(bar) { bar.call(this, bar) } } function bar(baz) { return (this.snaf = baz) }
上面代码中,foo是公开方法,内部调用了bar.call(this,baz)。这使得bar()实际上成为了当前类的私有方法。