zoukankan      html  css  js  c++  java
  • JavaScript的闭包与继承

    全局变量所有函数都能调用,容易对其造成污染(改变其值造成逻辑混乱),局部变量又只能在函数体里使用,不能为全局服务重复使用,要想解决此类问题闭包是个不错的选择。

    对闭包的理解:闭包能在全局函数里面操控另一个作用域的局部变量

    完成闭包的三步

    1.外层函数嵌套内层函数

    2.内层函数使用外层函数的局部变量

    3.把内层函数作为外层函数的返回值

    function numCompany(){
    var n=1;
    function getNum(){
    return n++;
    };
    return getNum;
    }
    var fn=numCompany();
    console.log(fn());

     以上是闭包的全部过程!!!

    继承

    继承通俗来说就是子承父业,为什么要使用继承,一个字就是懒,能继承父业还奋斗个啥?

    当然面向对象的语言都有继承的方法,像强语言类型的Java,C++等,但是JavaScript的面向对象是通过构造函数来实现的,所以有些许不同,但是目的都是一样的,继承父类的属性和方法。

    JavaScript也有封装和多态(重写和重载),JavaScript本来就是弱语言类型,不像java那样严格,所以重写和重载会相当方便,这里不再赘述。

    那么JavaScript是怎么实现继承的呢?     子类共享父类的属性和方法,js的继承都是基于原型实现的!!!!

    JavaScript实现继承的方法有有六种 以下面的例子介绍!

    //定义一个动物类

    function Animal (name) {
        // 属性
        this.name = name;
        // 实例方法
        this.say= function(){
          console.log("My name is "+this.name);
        }
    }
    // 原型方法
    Animal.prototype.eat = function(food) {
        console.log(this.name + '正在吃:' + food);
    };

    1.原型链继承:子类的原型指向父类的实例

    function Cat(){
    }
    Cat.prototype = new Animal();
    Cat.prototype.name = 'cat';
    
    
    var cat = new Cat();
    console.log(cat.name);
    cat.say();
    cat.eat('fish');
    console.log(cat instanceof Animal); //true
    console.log(cat instanceof Cat); //true

    结论:能较好的继承,实例是子类的实例也是父类的实例,父类新增的原型方法属性子类都能访问到,但是必须要在new Animal()这样的语句之后执行,不能放到构造器中,不能实现多继承,来自原型对象的引用属性是所有实例共享的,创建子类实例时无法向构造函数传参

    2.构造继承(call,apply继承)

    function Cat(name){
        Animal.call(this,name);
    }
    
    var cat = new Cat("Tom");
    console.log(cat.name);
    cat.say();
    console.log(cat instanceof Animal); // false
    console.log(cat instanceof Cat); // true

    结论:解决1中子类实例共享父类引用属性的问题,可以向父类传递参数,可以实现多继承(call多个父类对象),但是并不是父类的实例,而是子类的实例,只能继承父类的实例属性和方法不能继承原型上的属性和方法,无法实现函数的复用,每个子类都有父类实例函数的副本,影响性能

    3.拷贝继承

     

    function Cat(name){
        var animal = new Animal(name);
        for(var key in animal){
            Cat.prototype[key] = animal[key];
        }
    }
    // Test Code
    var cat = new Cat("Tom");
    console.log(cat.name);
    cat.say();
    console.log(cat instanceof Animal); // false
    console.log(cat instanceof Cat); // true

    结论:支持多继承,但是这相当于直接复制的父类的属性,效率低,内存占用高,无法获取父类的不可枚举方法(不可枚举方法,不能使用for  in访问到) 

    4.组合继承(原型链和构造函数的组合)

    function Cat(name){
        Animal.call(this,name);
    }
    
    Cat.prototype = new Animal();
    Cat.prototype.constructor = Cat;
    
    // Test Code
    var cat = new Cat();
    console.log(cat.name);
    cat.say();
    console.log(cat instanceof Animal); // true
    console.log(cat instanceof Cat); // true

    结论:弥补2的缺陷,实例和原型都能继承,不存在引用属性共享问题,可传参,函数可复用,唯一不足就是调用了两次构造函数,生成了两份实例(子类实例将子类原型上那一份屏蔽了)

    5.寄生组合继承

    function Cat(name){
        Animal.call(this);
        this.name = name;
    }
    (function(){
        // 创建一个没有实例方法的类
        var Super = function(){};
        Super.prototype = Animal.prototype;
        //将实例作为子类的原型
        Cat.prototype = new Super();
    })();
    
    // Test Code
    var cat = new Cat();
    console.log(cat.name);
    cat.say();
    console.log(cat instanceof Animal); // true
    console.log(cat instanceof Cat); //true

    结论:就很完美,看起来比较复杂,实际也复杂

    6.ES6继承(语法糖)

    class Animal{
        constructor(name){
            this.name = name;
        }
        say(){
            alert("My name is "+this.name);
        }
        eat(food){
            alert(this.name+" is eating "+food);
        }
    }
    class Cat extends Animal{
        constructor(name){
            super(name);
        }
    }
    
    var  tom = new Cat("Tom");
    tom.say();
    tom.eat("apple");
    console.log(cat instanceof Animal); // true
    console.log(cat instanceof Cat); //true

    结论:就用这个!!!

     学习一门语言就要熟悉它的底层原理,到时候使用岂不是信手拈来?

    tips:你我山巅自相逢  

  • 相关阅读:
    实时获取阿里旺旺聊天记录,实时获取千牛聊天记录
    千牛hook 旺旺hook,旺旺发消息call,千牛发消息call,千牛机器人,破解旺旺发消息代码,破解千牛发消息代码,反汇编旺旺发消息,反汇编千牛发消息,旺旺发消息组件,千牛发消息组件
    hook千牛 千牛破解发消息 千牛机器人 千牛发消息组件 调用千牛发消息 实时获取千牛聊天记录 可以提供代码
    [转发]分布式事务,这一篇就够了
    C++之throw以及try{}...catch{}【转载】
    C++之Effective C++学习-条款2
    c++中为什么析构函数要被设置为虚函数(virtual)
    c++中在声明静态变量时,使用const可直接初始化,不在需要定义式
    js检测浏览器类型_js检测是否为火狐浏览器
    PHP8.0 JIT 配置
  • 原文地址:https://www.cnblogs.com/dabfranklin/p/13557296.html
Copyright © 2011-2022 走看看