欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

es5继承和es6类和继承

程序员文章站 2022-07-01 23:16:24
es6新增关键字class,代表类,其实相当于代替了es5的构造函数 通过构造函数可以创建一个对象实例,那么通过class也可以创建一个对象实列 es5中继承的方式 1原型链继承 2.构造函数继承 3.组合继承,融合了上面两种方式 /* 组合继承,既能达到对父类属性的继承,也能继承父类原型上的方法 ......

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