es5继承和es6类和继承

Posted czkolve

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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);
  1. child {sex: "man", name: "czklove", age: "13"}
    1. age: "13"
    2. name: "czklove"
    3. sex: "man"
    4. __proto__: person
      1. age: undefined
      2. constructor: ƒ child(sex,name,age)
      3. name: undefined
      4. __proto__: Object

    /*
    组合继承,既能达到对父类属性的继承,也能继承父类原型上的方法
    父类属性继承也不会在所有子类的实列上共享
    唯一缺点,子类原型上有父类构造函数的属性,也就是多了一份属性
    */

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继承的差异

以上是关于es5继承和es6类和继承的主要内容,如果未能解决你的问题,请参考以下文章

How Javascript works (Javascript工作原理) (十五) 类和继承及 Babel 和 TypeScript 代码转换探秘

ES5和ES6中的继承 图解

ES5 和ES6 继承的区别

es6继承 vs js原生继承(es5)

js类的继承,es5和es6的方法

ES5和es6的封装继承