es5继承和es6类和继承
es6新增关键字class,代表类,其实相当于代替了es5的构造函数
通过构造函数可以创建一个对象实例,那么通过class也可以创建一个对象实列
/* es5 创建一个person 构造函数 */ function person (name,age) { this.name = name this.age = age } /* 定义原型链上的方法sayholle */ /* 为什么要将方法定义在原型上,定义在原型上的方法,所有的实例对象都共享 不会出现没实列一个对象都重新创建一个这个方法 */ person.prototype.sayholle = function () { console.log(this.name+' holle'+ this.age) } let person1 = new person('czcz','23') person1.sayholle() // czcz holle23 /* es6 使用class创建一个对象 */ class personclass { /* 实列对象时默认调用的方法 */ constructor (name,age) { this.name = name this.age = age } /* 定义一个方法,相对构造上述原型链上的方法 */ sayholle () { console.log(this.name+' holle'+ this.age) } } let person2 = new personclass('czcz','26') person2.sayholle() // czcz holle23
es5中继承的方式
1原型链继承
/* es5原型链继承 */ function person (name,age) { this.name = name this.age = age } person.prototype.sayholle = function () { console.log(this.name+' holle'+ this.age) } function child (sex) { this.sex = sex; } child.prototype = new person(); child.prototype.hh = 'ddd' let p = new child('man') console.log(p) // console.log(new person()); let p2 = new child('man') p2.__proto__.age = '36' /* 给p2原型上的age赋值,则导致p上的age也改变,父类构造函数上的属性被所有子类共享 */ console.log(p) // 36 /* 缺点,child 新增的属性只能在new person 以后,创建实列时无法向 父类的构造函数传送参数,因为直接是指定了原型,所有也不能实现多继承 父类构造函数上的属性被所有子类共享 */
2.构造函数继承
/* es5构造函数继承 */ function person (name,age) { this.name = name this.age = age } person.prototype.sayholle = function () { console.log(this.name+' holle'+ this.age) } function child (sex,name,age) { this.sex = sex person.call(this,name,age) } let p = new child('man','czklove','13') console.log(p); /* 可以是先多继承,只要执行多个call 创建实列时能像父类构造函数船体参数 不会出现父类属性,所有子类构造函数共享 缺点, 不能继承父类原型链上的方法,如上面不能掉用sayholle方法 子类构造函数的实列,原型链上并不存在父类构造函数, 因为不能继承父类原型链上的函数,所有要继承函数只能定义在父类构造函数上, 不能达到函数复用 */
3.组合继承,融合了上面两种方式
/* es5组合继承 */ function person (name,age) { this.name = name this.age = age } person.prototype.sayholle = function () { console.log(this.name+' holle'+ this.age) } function child (sex,name,age) { this.sex = sex person.call(this,name,age) } child.prototype = new person(); /* 重新设置一下constructor 不设置也没有影响,严谨的角度上来说还是设置一下*/ /* 不设置的话,__proto__ 上时没有 constructor */ /* 正常来讲constructor是指向自身的 */ child.prototype.constructor = child; let p = new child('man','czklove','13') let p1 = new child('man','czklove1','16') p.sayholle(); // czklove holle13 console.log(p);
console.log(p.__proto__ === child.prototype) //true
4.优化版的组合继承(寄生组合继承)
/* es5寄生组合继承 */ function person (name,age) { this.name = name this.age = age } person.prototype.sayholle = function () { console.log(this.name+' holle'+ this.age) } function child (sex,name,age) { this.sex = sex person.call(this,name,age) } child.prototype = Object.create(person.prototype); child.prototype.constructor = child let p = new child('man','czklove','13') p.sayholle(); // czklove holle13 console.log(p); /* child {sex: "man", name: "czklove", age: "13"} age: "13" name: "czklove" sex: "man" __proto__: person constructor: ƒ child(sex,name,age) __proto__: sayholle: ƒ () constructor: ƒ person(name,age) __proto__: Object */
es6 class
1.1class 内部都是严格模式
1.2class 不存在变量提升
1.3 class 的 name属性
1.4 实现symbol.iterator 接口,可以使用for of 遍历属性
1.5this 指向实例内部
关于class的基本介绍,去阮一峰老师的es6入门看就行 http://es6.ruanyifeng.com/#docs/class
es6 class的继承
/* esl class */ class person { constructor (name,age) { this.name = name this.age = age } syaholle () { console.log(this.name+ ' holle '+this.age) } } class child extends person { constructor (name,age,sex) { /* 执行父类的构造函数 子类必须在构造函数中掉用super */ super(name,age) /* 使用this一定要在super 之后 */ this.sex = sex } } let p = new child('czklove','23','man') console.log(p) /* child {name: "czklove", age: "23", sex: "man"} age: "23" name: "czklove" sex: "man" __proto__: person constructor: class child __proto__: constructor: class person syaholle: ƒ syaholle() __proto__: Object */
/* esl class */ class person { constructor (name,age) { this.name = name this.age = age } syaholle () { console.log(this.name+ ' holle '+this.age) } } class child extends person { constructor (name,age,sex) { /* 执行父类的构造函数 子类必须在构造函数中掉用super */ super(name,age) /* 使用this一定要在super 之后 */ this.sex = sex } } let p = new child('czklove','23','man') console.log(p) /* child {name: "czklove", age: "23", sex: "man"} age: "23" name: "czklove" sex: "man" __proto__: person constructor: class child __proto__: constructor: class person syaholle: ƒ syaholle() __proto__: Object */
es6 class 还涉及到很多东西,
1.静态方法
2.this指向
3.super 关键字的具体使用
4.类的prototype属性,构造函数的__proto__
5.原生构造函数的继承,如Array的继承,Boolean,Number,String Date...
基础简单的这里就不说了
我们再看以下原生构造函数的继承
es5中是不允许原生构造函数的继承的
/* es5为什么不能对原生构造函数的继承 通过es5继承我们知道,继承父类构造属性是通过person.call(this,argument) (es6) 是因为子类无法获得原生构造函数的内部属性, 通过Array.apply()或者分配给原型对象都不行。 原生构造函数会忽略apply方法传入的this,也就是说, 原生构造函数的this无法绑定,导致拿不到内部属性 */ /* es6 使用class继承原生 */ class myarray extends Array { constructor(...argus) { super(...argus) } } let arrays = new myarray(); arrays[0] = 'czklove'; console.log(arrays); arrays.length = 0 console.log(arrays); /* 输出 myarray ["czklove"] myarray [] */
注,es6对object构造函数的继承,不能传参,传参数无效
class newobjext extends Object { constructor() { super(...arguments) } } let o = new newobjext({name: 'czklove'}) console.log(o.name); // undefined
总结,
es5的继承
1.1原型链继承
1.2 构造函数继承
1.3组合继承
1.4寄生组合继承
es6 的 extends 继承
super 关键字的使用,新增的静态字段使用,支持对原生构造函数的继承,对object继承的差异