zoukankan      html  css  js  c++  java
  • js 原型链,继承,闭包,内存,泄露

    var A = function(){ this.name="xiaoming"; }
    A.prototype.age=9;
    var a = new A();
    console.log(a.age); //9
    
    图中长方形代表实例对象a,圆形代表原型,三角形代表构造函数。由图可知:
    a.__proto__ === A.prototype; //true
    A.prototype.constructor===A; //true
    A.prototype.__proto__===Object.prototype; //true
    Object.prototype.__proto__===null; //true
    复制代码
    实例和原型之间是通过__proto__属性连接,且是单向的,从实例指向原型;原型和构造函数之间连接是双向的,通过constructor和prototype连接,具体见图;原型链上的属性是所有实例共享的,看下面的例子:
    
    var A = function(){
        this.name="xiaoming";
    }
    var a = new A();
    A.prototype.age=9;
    var b = new A();
    console.log(a.age); //9
    console.log(b.age); //9
    复制代码
    a、b都可以访问A原型链上的属性age。
    
    Function和Object比较特殊,他们既是对象又是函数,两者内部同时含有proto和prototype属性,可看下面代码:
    
    Object.__proto__ === Function.prototype //true
    Object.__proto__ === Function.__proto__//true
    Object.prototype === Function.prototype.__proto__ // true
    Function instanceof Object //true
    Object instanceof Function //true
    复制代码
    至此,原型链的知识差不多可以理解了,后面介绍继承的几种方式。
    
    原型链继承
    既然可以访问原型链的所有属性,那么就可以用原型链的原理实现继承。原型链继承用new的方式(实现A继承B):
    A.prototype=new B();关于new可以看下我另一篇文章this那些事。
    
    代码:
    
    function B(){
        this.nameB='B';
    }
    B.prototype.nameProto="PROTO";
    function A(){
        this.nameA="A";
    }
    A.prototype=new B(); //原型链继承:A继承B
    var a=new A();
    console.log(a);
    复制代码
    打印结果:
    
    
    上段代码A继承B,通过A构造函数new的示例a不仅可以继承B(可访问nameB),而且可以继承B原型上的属性(nameProto),且是所有实例共享的。
    好处:可以继承原型链的属性。
    缺点:无法实现多继承,A继承了B,就无法再继承C。
    
    构造继承
    构造继承就是利用构造函数继承,即改变this指向的方式(call/apply/bind)执行一次构造函数B,具体可我另一篇文章this那些事。废话不多说,上例子:
    
    function B(){
        this.nameB='B';
    }
    B.prototype.nameProto="PROTO";
    function A(){
        B.call(this); //A继承B,只举了call的例子,apply、bind类似
        this.nameA="A";
    }
    var a=new A();
    console.log(a);
    复制代码
    打印结果:
    
     
    
    
    根据a的打印结果,我们看到nameB和nameA是同一层级,虽然实现了A继承B,但是通过a的结构看不出来,而且无法继承B原型链上的属性nameProto,不过它的好处是可以多继承,可以通过C.call(this)继承C。
     
    
    好处:可以多继承。
    缺点:无法继承原型链上的属性。
    
    组合继承
    组合继承就是为了解决原型链继承无法多继承、构造继承无法继承原型链上的属性的问题而诞生的,将两种方式结合。
    
    function B(){
        this.nameB='B';
    }
    B.prototype.nameProto="PROTO";
    function A(){
        B.call(this); //构造继承
        this.nameA="A";
    }
    A.prototype=new B(); //原型链继承:A继承B
    var a=new A();
    console.log(a);
    复制代码
    打印结果:
    
    
    观察a的打印结果,似乎真的解决了上述两个问题,它也引入了一个新的问题:nameB属性有两个,这样造成了资源浪费(存储占用内存)。
     
    
    原型式继承
    先看下面的示例:
    
    function objectCreate(obj){
      function F(){};
      F.prototype = obj;
      return new F();
    }
    var a=objectCreate(A.prototype);
    
     闭包,函数内部引用外部变量,可以进行数据保持,防止变量污染。 内存泄露:浏览器主要的垃圾回收机制是利用标记清除法,计数法用的不多。 哪些变量不会被清除,1 : 全局变量不会被清除,因为全局变量不确定什么时候会使用,一旦清除。影响很大。 2 局部变量,如果没有形成闭包会在使用结束后清除,如果形成闭包,变量不会被释放,因为可能会被引用。
    
    
    
    
     
     
    

      

  • 相关阅读:
    SQL 多组数据中取每一组最新的数据
    HTML 滚动显示数据
    EasyUI datagrid-export 将datagrid的数据导出至Excel-解决科学计数法
    C#连接SAP并下载工单资料【生产系统与ERP对接】
    BAPI_TRANSACTION_COMMIT
    生产追溯系统-Raspberry Pi帮助我们节省大量硬件成本,助力信息化建设
    YII2 使用phpexcel(干货)
    ThinkPHP 文件上传到阿里云OSS上(干货)
    mysql与mycat搭建实现集群与读写分离
    mysql 表分区技术
  • 原文地址:https://www.cnblogs.com/tiangeng/p/10096275.html
Copyright © 2011-2022 走看看