class的基本语法 class的继承

本文详细讲解了ES6中的Class语法及其继承机制,包括Class表达式、构造函数、super关键字的使用、静态方法与属性、原型链继承、Mixin模式的实现,并通过实例分析了Class的内部工作原理和最佳实践。
摘要由CSDN通过智能技术生成

实质: class只是一个语法糖,类的所有方法都定义在类的prototype属性上,本质是通过ES5的原型链继承实现的。使用: class Point{ constructor(){ //… } toValue(){ //… } } //等同于 Point.prototype = { constructor(){}, toValue(){}, }; prototype对象的constructor属性直接指向’类’本身,这与ES5的行为是一致的: Point.prototype.constructor = Point; 可以使用Object.assign方法方便的向一个类添加多个方法: Object.assign(Point.prototype,{ toValue(){} });//ES6中对象函数的简洁表示 类内部定义的所有方法都是不可枚举的,这一点和ES5的行为不一致。constructor方法: 是类的默认方法,通过new命令生成对象实例时自动调用该方法,没有显式定义时会默认添加一个空的无参构造方法。 构造方法默认返回实例对象,不过可以指定返回另外一个对象。 类必须使用new来调用。类的实例对象: 实例的属性除非显式定义在其本身(this对象),否则都是定义在原型上。 所有的实例共享一个原型对象,__proto__属性都是相等的,因此可以通过实例的__proto__属性为“类”添加方法(不建议使用)。在生产环境中,一般通过Object.getPrototypeOf方法来获取实例对象的原型,再为原型添加方法/属性。Class表达式: const MyClass = class Me{ //… }; 类的名字是MyClass而不是Me,Me只能在Class内部使用,用来指代当前类,因此可以省略Me。 采用Class表达式,可以写出立即执行的Class:不存在变量提升严格模式: 类和模块的内部默认使用严格模式,所以不需要显示声明。私有方法: ES6未提供,通过变通方法来模拟实现: 1.将私有方法移除模块,因为模块内部的所有方法都是对外可见的。 2.利用Symbol值得唯一性将私有方法得名字命名为一个Symbol值。私有属性: ES6不支持私有属性,目前有一个提案是在私有属性名前加上#来表示,也可以用来编写私有方法。this的指向: 类的方法内部如果含有this,默认指向类的实例,但是一旦单独使用该方法,很有可能会报错。 解决方法: 1.在构造方法中绑定this:this.printName = this.printName.bind(this); 2.使用箭头函数: this.printName = (name = ‘there’) => { this.print(hello ${name}); } 3.使用Proxy,在获取方法的时候自动绑定thisname的属性: 本质上,ES6的类只是ES5的构造函数的一层包装,所以函数的许多特性都被Class继承,包括name属性。 name属性总是返回紧跟在Class关键字后的类名。Class的取值函数和存值函数: 使用get和set关键字对某个属性设置存值函数和取值函数,拦截该属性的存取行为。 eg. get prop(){ return this.prop; } set prop(vale){ this.prop = value; }Class的Generator方法: 在某个方法之前加上星号,就表示该方法是一个Generator函数。Class的静态方法: 类相当于实例的原型,所有在类中定义的方法都会被实例继承,在方法前加上staic关键字,表示该方法不会被实例继承,而是直接通过类调用,被称为静态方法。 父类的静态方法可以被子类继承。Class的静态属性和实例属性: ES6中明确规定,Class内部只有静态方法没有静态属性。 只能写成: class Foo{//…}; Foo.prop = 1; 目前有一个新提案,其中对实例属性和静态属性都规定了新的写法: 实例属性: 以前定义实例属性时只能写在构造函数里。,现在可以用等式写进类的定义中:myProp = 42; 为了获得更强的可读性,对于已经在构造函数中定义的实例属性,新写法允许将其直接列出。 静态属性: 只要在上边的实例属性写法前加上static关键字即可。new.target属性: new是从构造函数生成实例的命令。ES6为new命令引入了new.target属 性 在构造函数里),返回new命令所作用的构造函数,如果构造函数不是通过new命令调用的,new.target会返回undefined,因此这个属性可以用于确定构造函数是怎么调用的。 子类继承父类时,new.target会返回子类,利用这个特点可以写出不能独立使用必须继承后才能使用的类: if(new.target === super){ throw new Error(‘本类不能实例化’); }

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

class Point {

}class ColorPoint extends Point {

}

上面代码定义了一个ColorPoint类,该类通过extends关键字,继承了Point类的所有属性和方法。但是由于没有部署任何代码,所以这两个类完全一样,等于复制了一个Point类。下面,我们在ColorPoint内部加上代码。

class ColorPoint extends Point {

constructor(x, y, color) {

super(x, y); // 调用父类的constructor(x, y)this.color = color;

}

toString() {

returnthis.color +''+ super.toString();// 调用父类的toString()  }

}

上面代码中,constructor方法和toString方法之中,都出现了super关键字,它在这里表示父类的构造函数,用来新建父类的this对象。

子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。

classPoint {/* … */ }class ColorPoint extends Point {

constructor() {

}

}

let cp =newColorPoint();// ReferenceError

上面代码中,ColorPoint继承了父类Point,但是它的构造函数没有调用super方法,导致新建实例时报错。

ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this。

如果子类没有定义constructor方法,这个方法会被默认添加,代码如下。也就是说,不管有没有显式定义,任何一个子类都有constructor方法。

class ColorPoint extends Point { </

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值