ES5 中创建类的方法:新建一个构造函数,定义一个方法并且赋值给构造函数的原型
'use strict';function Person(name) {this.name = name;}Person.prototype.sayName = function () {return this.name;};const uzi = new Person('Uzi');console.log(uzi.sayName());// Uzi
ES6 实现类非常简单,只需要类声明。
class Person {// 新建构造函数constructor(name) {// 私有属性this.name = name;}// 定义一个方法并且赋值给构造函数的原型sayName() {return this.name}}const uzi = new Person('Uzi');console.log(uzi.sayName());// Uzi
和 ES5 中使用构造函数不同的是,在 ES6 中,我们将原型的实现写在类中,但本质上还是一样的,都是需要新建一个类名,然后实现构造函数,再实现原型方法。
私有属性是实例中的属性,不会出现在原型上,且只能在类的构造函数或方法中创建,此例的 name
就是一个私有属性。这里建议你在构造函数中创建所有私有属性,从而只通过一处就可以控制所有的私有属性。
定义私有属性,只需要在构造方法中定义 this.xx = xx
。
值得注意的是:typeof Person
最终返回的结果是 "function"
类声明和函数声明的区别和特点:
let
声明类似)Object.defineProperty()
手工指定不可枚举属性[[constructor]]
方法new
来调用类的构造函数类有两种表现形式:
// 声明式class Person {constructor(){}}// 匿名表达式const Car = class {constructor(){}}// 命名表达式,Order 可以在外部使用,而 Order1 只能在内部使用const Order = class Order1 {constructor(){}}
// 新建一个类let Person = class {sayName(){return 'Uzi'}}// 该函数返回一个类的实例function fn(Person) {return new Person();}// 给 fn 函数传入 Personconst uzi = fn(Person);console.log(uzi.sayName());// Uzi
用 new
调用类的表达式,紧接着通过一对小括号调用这个表达式。
const uzi = new class {constructor(name) {this.name = name;}sayName(){return this.name}}('Uzi')console.log(uzi.sayName());// Uzi
类支持在原型上定义访问器属性。
尽管应该在类的构造函数中创建自己属性,但是类也支持直接在原型上定义访问器属性。创建 getter
时,需要在关键字 get
后紧跟一个空格和响应的标识符;创建 setter
时,只需把关键字 get
替换为 set
即可。
class Person {constructor(state) {this.state = state}// 创建 getterget myName() {return this.state.name}// 创建 setterset myName(name) {this.state.name = name}}// 获取指定对象的自身属性描述符。自身属性描述符是指直接在对象上定义(而非从对象的原型即成)的描述符。let descriptor = Object.getOwnPropertyDescriptor(Person.prototype, 'myName');console.log('get' in descriptor);// trueconsole.log(descriptor.enumerable);// false 不可枚举
可计算成员时指使用方括号包裹一个表达式,如下面定义了一个变量 methodName
,然后使用 [methodName]
设置为类 Person 的原型方法。
const methodName = 'sayName';class Person {constructor(name) {this.name = name;}[methodName]() {return this.name}}const uzi = new Person('Uzi')uzi.sayName();//
生成器是一个返回迭代器的函数。在类中,我们也可以使用生成器方法。
class Person {*sayNum() {yield 1;yield 2;yield 3;}}const uzi = new Person();console.log(uzi.sayNum().next());// {done: false, value: 1}console.log(uzi.sayNum().next());// {done: false, value: 1}console.log(uzi.sayNum().next());// {done: false, value: 1}
这个写法很有趣,我们新增一个原型方法稍微改动一下。
class Person {*sayNum() {yield 1;yield 2;yield 3;}render(){// 从 render 方法返回 sayNum,类似于 React 中经常用到的写法return this.sayNum()}}let uzi = new Person();console.log(uzi.render().next());// {done: false, value: 1}
静态成员是指在方法名或属性名前面加上 static
关键字,和普通方法不一样的是,static
修饰的方法不能在实例中访问,只能用类名直接访问。
class Person {constructor(name) {this.name = name;}static create(name) {return new Person(name)}}const uzi = Person.create('Uzi');console.log(uzi.name);// Uzilet ben = new Person();console.log(ben.create('Ben'));// ben.create is not a function
我们在写 React 的时候,自定义的组件汇集成 React.Component。
class Person extends Component {constructor(props) {super(props)}}
Person 叫做派生类,在派生类中,如果使用了构造方法,就必须使用 super()
。
class Person {constructor([name, age] = props){this.name = name;this.age = age;}sayHi() {return `Hi, my name is ${this.name}, and I'm ${this.age} years old.`;}}class Player extends Person {constructor(props) {super(props)}}let uzi = new Player(['Uzi', 22]);console.log(uzi.sayHi());// Hi, my name is Uzi, and I'm 22 years old.
关于 super
使用的几点要求:
super
,派生类是指继承自其他类的新类this
之前要调用 super()
,负责初始化 this
。// Badclass Player extends Person {constructor(props) {this.name = 1// 必须先写 super()super(props)}}
super
,可以让类的构造函数返回一个对象。我们可以在继承的类中重写父类的方法。
class Person {constructor([name, age] = props){this.name = name;this.age = age;}sayHi() {return `Hi, my name is ${this.name}, and I'm ${this.age} years old.`;}}class Player extends Person {constructor(props) {super(props)}// 重写add方法,求积sayHi() {return `Hi, my name is ${this.name}, ${this.age}.`}}let uzi = new Player(['Uzi', 22]);console.log(uzi.sayName());// Hi, my name is Uzi, 22.`
父类中静态成员,也可以继承到派生类中。静态成员继承只能通过派生类访问,不能通过派生类的实例访问。
class Person {constructor([name, age] = props) {this.name = name;this.age = age}static say([name, age] = props) {return `${name}, ${age}`;}}class Player extends Person {constructor(props) {super(props)}}const uzi = new Play(['Uzi', 22])console.log(uzi.say([2, 3]));// 5
很好理解,就是指父类可以是一个表达式。
function Rectangle(length, ){// do something}class Square extends Rectangle {// do something}
参考资料: