【ES6】Class 类的使用与继承方法详解

JavaScript 语言中,生成实例对象的传统方法是通过构造函数。 ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。

基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰更像面向对象编程的语法而已。所以ES6 的类,完全可以看作构造函数的另一种写法。

class Point { 
	//构造函数
	constructor(x, y) {
	    this.x = x; this.y = y;
	} 
	toString() { 
	    console.log('(' + this.x + ', ' + this.y + ')'); 
	} 
}
let p = new Point(1,2)
p.toString()    //(1, 2)

注意:类必须使用new调用,否则会报错。这是它跟普通构造函数的一个主要区别,普通构造函数不用new也可以执行。

实例方法

在类中可以直接定义方法,实际上类的所有方法都定义在类的prototype属性上面。在类的实例上面调用方法,其实就是调用原型上的方法。

class Point { 
	constructor() { // ... } 
	toString() { // ... } 
	toValue() { // ... } 
}

constructor 方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。class Point { }等同于class Point { constructor() {} }

由于类的方法都定义在prototype对象上面,所以类的新方法可以添加在prototype对象上面。Object.assign 方法可以很方便地一次向类添加多个方法。

class Point { 
	constructor(){ // ... }
 } 
Object.assign(Point.prototype, { 
	toString(){}, 
	toValue(){} 
});
静态方法

类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上 static 关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为 “静态方法”

class Foo {
	static classMethod() { 
		return 'hello'; 
	} 
}
Foo.classMethod() // 'hello'

需要注意的是,如果静态方法包含this关键字,这个this指的是类,而不是实例。

实例属性

类的实例属性可以定义在构造函数中。

class Person{ 
	constructor(id,name,age) { 
	    this.id = id;
	    this.name = name;
	    this.age = age;
	} 
}
静态属性

直接在类上定义的属性称为是静态属性,只能通过类来调用。

class Foo { }
Foo.prop = 1; 
Foo.prop // 1

目前,只有这种写法可行,因为 ES6 明确规定,Class 内部只有静态方法,没有静态属性。

对象的继承

我们先来回顾一下 ES5 中对象的原型链继承方法。

function Animal(name,age){
    this.name = name
    this.age = age
}
function Dog(name,age,gender){
    //借用Animal构造函数
    Animal.apply(this,arguments)
    this.gender = gender
}
Dog.prototype = new Animal()
var dog = new Dog('旺财',6,'male')
console.log(dog instanceof Animal)   //true

class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。

class Animal { 
	constructor(name){
        this.name = name
	}
	sayName(){
	    console.log('my name is',this.name);
    }
    static sayHello(){
	    console.log('hello');
	}
}
class Dog extends Animal{
    constructor(name,age){
        //super()代表调用父类的构造函数
        super(name)
        this.age = age
    }
    sayAge(){
        console.log('my age is',this.age)
    }
}
let dog = new Dog('旺财',12)
dog.sayName()
dog.sayAge()
Dog.sayHello()
console.log(dog)

super 这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。

  • 函数:
    子类B的构造函数之中的super(),代表调用父类的构造函数。 super虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super内部的this指的是B,因此super()在这里相当于A.prototype.constructor.call(this)
  • 对象:
    在普通方法中,指向父类的原型对象;在静态方法中,指向父类。由于super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的。

class 作为构造函数的语法糖,同时有 prototype属性和__proto__属性,因此同时存在两条继承链。

class A { } 
class B extends A { } 
B.__proto__ === A // true
B.prototype.__proto__ === A.prototype // true
  • 子类的 __proto__属性,表示构造函数的继承,总是指向父类。
  • 子类 prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ES6中的class可以让我们更方便地定义和面向对象的编程模式。下面是一些关于ES6 class的详细解释: 1. 定义 使用class关键字定义一个名通常首字母大写。例如: ``` class Person { constructor(name, age) { this.name = name; this.age = age; } sayHello() { console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`); } } ``` 上面的代码定义了一个Person,包含一个构造函数和一个sayHello方法。 2. 构造函数 中的构造函数使用constructor关键字定义,用于初始化对象的属性。例如: ``` class Person { constructor(name, age) { this.name = name; this.age = age; } } ``` 上面的代码定义了一个Person,包含一个构造函数,构造函数接收name和age两个参数,并将其分别赋值给对象的name和age属性。 3. 方法 中的方法可以像普通函数一样定义,例如: ``` class Person { constructor(name, age) { this.name = name; this.age = age; } sayHello() { console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`); } } ``` 上面的代码定义了一个Person,包含一个sayHello方法,该方法用于打印对象的name和age属性。 4. 继承 ES6中的class支持继承使用extends关键字实现继承。例如: ``` class Student extends Person { constructor(name, age, grade) { super(name, age); this.grade = grade; } study() { console.log(`${this.name} is studying in grade ${this.grade}.`); } } ``` 上面的代码定义了一个Student,该继承自Person,包含一个构造函数和一个study方法。构造函数接收name、age和grade三个参数,其中name和age由父类的构造函数初始化,grade由子类的构造函数初始化。 5. 静态方法 中的静态方法使用static关键字定义,可以直接通过调用,例如: ``` class MathUtils { static add(x, y) { return x + y; } static subtract(x, y) { return x - y; } } ``` 上面的代码定义了一个MathUtils,包含两个静态方法add和subtract,这两个方法可以直接通过调用。 6. 属性 ES6中的class支持定义属性,可以使用get和set关键字定义属性的读写方法。例如: ``` class Person { constructor(name, age) { this._name = name; this._age = age; } get name() { return this._name; } set name(name) { this._name = name; } get age() { return this._age; } set age(age) { this._age = age; } } ``` 上面的代码定义了一个Person,包含两个属性name和age,这两个属性的读写方法分别由get和set关键字定义。注意,属性名前面加上了一个下划线,这是一种约定俗成的做法,用于表示私有属性,防止属性被直接访问。 7. 静态属性 ES6中的class支持定义静态属性,使用static关键字定义静态属性。例如: ``` class MyClass { static myStaticProperty = 42; } ``` 上面的代码定义了一个MyClass,包含一个静态属性myStaticProperty,该属性的初始值为42。 总结: ES6中的class为JavaScript提供了更加完整和规范的面向对象编程模式,支持继承、静态方法、属性等等。使用class可以让我们更方便地定义和对象,提高代码的可读性和维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值