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

原文地址:https://www.cnblogs.com/czkolve/p/10849226.html

时间: 2024-10-08 00:09:17

es5继承和es6类和继承的相关文章

typescript - 4.es5与typescript的类与继承

ES5中的类与类的继承 (1)简单的类 function Person() { this.name = '张三'; this.age = 20; } var p = new Person(); alert(p.name); (2)构造函数和原型链里面增加方法 function Person() { this.name = '张三'; /*属性*/ this.age = 20; this.run = function () { alert(this.name + '在运动'); } } //原型链

04面向对象编程-02-原型继承 和 ES6的class继承

1.原型继承 在上一篇中,我们提到,JS中原型继承的本质,实际上就是 "将构造函数的原型对象,指向由另一个构造函数创建的实例". 这里,我们就原型继承的概念,再进行详细的理解.首先回顾一下之前的一个示例,Student构造函数 和 原型链: function Student(props) { this.name = props.name || 'Unnamed'; } Student.prototype.hello = function () { alert('Hello, ' + t

ES5中的继承和ES6中的继承

在JavaScript中,prototype.constructor.__proto__.构造函数.原型.实例这些概念已经很让人头疼,再加上ES6的class .extends已经乱成一锅粥了,平时对这些用的少写的少,是得好好捋清楚.看了几篇文章有了自己的理解,理解如下: 构造函数.prototype = 原型: 构造函数.prototype.constructor = 原型.constructor = 构造函数: new 构造函数 = 实例: 实例.constructor = 构造函数: 实例

第10章 接口、继承与多态 类的继承

1Test2类继承Test类,在子类中可以连同初始化父类构造方法来完成子类初始化操作,既可以在子类的构造方法中使用super()语句调用父类的构造方法,也可以在子类中使用super关键字调用父类的成员方法等,但是子类没有权限调用父类中被修饰为private的方法,只可以调用父类中修饰为public或protected的成员方法等. 2继承并不只是扩展父类的功能,还可以重写父类的成员方法.重写(还可以称为覆盖)就是在子类中将父类的成员方法的名称保留,重写成员方法的实现内容,更改成员方法的存储权限,

第10章 接口、继承与多态 类的继承3

尝试创建一个父类,在父类中创建两个方法,在子类中创建覆盖第二个方法,为子类创建一个对象,将向上转型到基类并调用这个方法 class Testmain{ public static void method1(Testmain q){ System.out.println(1); } public static void method2(){ System.out.println(2); } } public class Test extends Testmain { public static v

第10章 接口、继承与多态 类的继承2

在Java中一切都以对象的形式进行处理. 1)实例化子类对象时首先要实例化父类对象,然后再实例化子类对象,所以在子类构造方法访问父类的构造方法之前,父类已经完成实例化操作: 2)在实例化子类对象时,父类无参构造方法将被自动调用,但有参构造方法并不能被自动调用,只能依赖于super关键字显式地调用父类的构造方法. package ten; class Parent { Parent(){ System.out.println("调用父类的parent()构造方法"); } } class

类Exception_A继承Exception,类Exception_B继承Exception_A,请问执行此段代码的输出是什么?

1 @Test 2 public void Test_Exception() { 3 try { 4 throw new ExceptionB("A"); 5 } catch (ExceptionA e) { 6 System.out.println("ExceptionA"); //true 7 } catch (Exception e) { 8 System.out.println("Exception"); //false 9 } /*ca

类ExampleA继承Exception,类ExampleB继承ExampleA

现有如下的代码-------输出结果是什么?try { throw new ExampleB("b") } catch(ExampleA e){ System.out.println("ExampleA"); } catch(Exception e){ System.out.println("Exception"); }答案:ExampleA 解析: 根据里氏代换原则 能够使用父类型的地方一定可以使用子类型,抓取ExampleA类型异常的catc

精读JavaScript模式(八),JS类式继承

一.前言 这篇开始主要介绍代码复用模式(原书中的第六章),任何一位有理想的开发者都不愿意将同样的逻辑代码重写多次,复用也是提升自己开发能力中重要的一环,所以本篇也将从“继承”开始,聊聊开发中的各种代码复用模式. 其实在上一章,我感觉这本书后面很多东西是我不太理解的,但我还是想坚持读完,在以后知识逐渐积累,我会回头来完善这些概念,算是给以前的自己答疑解惑. 二.类式继承VS现代继承模式 1.什么是类式继承 谈到类式继承或者类classical,大家都有所耳闻,例如在java中,每个对象都是一个指定