JavaScript:原型链继承与对象冒充继承及ES6语法的解决

JavaScript:原型链继承与对象冒充继承及ES6语法的解决

  • 在ES5语法中,没有类这种概念,只能通过特殊的方式来实现继承;
  • 在学习原生js继承的过程中,遇到了两种继承模式的特点,特此记录下来以便下次复习。

1.原型链继承

  • 原型链继承可以继承构造函数以及原型链上的属性和方法,但实例化子类的时候,无法给父类传参;

    function Father(name,age){
        this.name = name;
        this.age = age;
        this.info = function(){
            console.log(this.name + ',' + this.age);
        }
    }
    // 静态方法
    Father.prototype.work = function(){
        console.log('work');
    }
    
    function Son(){
      // 属性和方法  
    }
    
    Son.prototype = new Father();
    
    // 实例化子类
    let son = new Son('张三',18);
    son.info();	// undefined,undefined
    son.work();	// work
    

2.对象冒充继承

  • 对象冒充继承可以继承构造函数的方法,但是无法继承原型链上的方法

    function Father(name,age){
        this.name = name;
        this.age = age;
        this.info = function(){
            console.log(this.name + ',' + this.age);
        }
    }
    Father.prototype.work = function(){
        console.log('work');
    }
    
    function Son(name,age){
        // 对象冒充继承
      Father.call(this,name,age)
    }
    
    
    // 实例化子类
    let son = new Son('张三',18);
    son.info();	// 张三,18
    son.work();	// Uncaught TypeError: son.work is not a function
    

3.ES6语法的类

  • 在ES6语法中,添加类的概念——class,类的引入使得js面向对象开发更为简便;

    // 定义父类
    class Father{
        // 构造函数
        constructor(name,age){
            this._name = name;
            this._age = age;
        }
        getName(){
            console.log(this._name);
        }
        setName(name){
            this._name = name;
        }
        // 静态方法
        static work(){
            console.log('work');
        }
    }
    
    // 静态方法和属性
    Father.sleep = function(){
        console.log('sleep');
    }
    
    let f = new Father('马云',50);
    f.getName();	// 马云
    f.setName('马化腾');
    f.getName();	// 马化腾
    
  • 而ES6的继承方式也与java类似——extends;这种继承方式可以兼顾以上两种继承方法的优点:即既可以继承静态方法和构造函数上的属性和方法,实例化子类时也可以给父类传参。

    // 定义父类
    class Father{
        // 构造函数
        constructor(name,age){
            this._name = name;
            this._age = age;
        }
        getName(){
            console.log(this._name);
        }
        setName(name){
            this._name = name;
        }
        // 静态方法
        static work(){
            console.log('work');
        }
    }
    
    // 静态方法和属性
    Father.sleep = function(){
        console.log('sleep');
    }
    
    // 子类继承父类
    class Son extends Father{
        constructor(name,age,sex){
            super(name,age);
            this._sex = sex;
        }
        getSex(){
            console.log(this._sex);
        }
    }
    
    // 实例化
    let s = new Son('allen',19,'male');
    s.getName();	// allen
    s.getSex();	// male
    Son.work();	// work
    Son.sleep(); // sleep
    

4.ES6中的单例

  • 在实际应用场景中,我们有时在多次实例化中只需执行一次特定的操作,如数据库的操作;

  • 让我们看看非单例情况下实例化会发生什么:

    class Db{
        constructor(){
            this.connect();
        }
        connect(){
            console.log('连接数据库');
        }
        find(){
            console.log('查询数据库');
        }
    }
    
    let db1 = new Db();
    let db2 = new Db();
    
    // 执行结果
    连接数据库
    连接数据库
    
  • 上面的例子很明确指出,非单例情况下实例化多次,会执行多次连接数据库的方法,这样造成了大量的时间和空间资源;

  • 单例的实现方式很简单,只需构造一个静态方法即可:

    class Db{
        static getInstance(){
            if(!Db.instance){
                Db.instance = new Db();
            }
            return Db.instance;
        }
        constructor(){
            this.connect();
        }
        connect(){
            console.log('连接数据库');
        }
        find(){
            console.log('查询数据库');
        }
    }
    
    let db1 = Db.getInstance();
    let db2 = Db.getInstance();
    let db3 = Db.getInstance();
    
    db3.find();
    db2.find();
    
    // 执行结果
    连接数据库
    查询数据库
    查询数据库
    
  • 所有实例都共享一个实例,称为 单例。运用好单例模式,在特定场景中可以节省不必要的资源浪费,十分推荐。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页