JS闭包与继承

来源:互联网 发布:ubuntu 切换系统语言 编辑:程序博客网 时间:2024/05/20 03:47

1、什么叫js闭包?
       首先要知道js的特性:函数内部可以直接读取全局变量,但是函数的外部无法直接读取函数的内部变量。
ps:注意点:在函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明的是一个全局变量!
      “闭包”就是我们在函数内的私有属性能够在外部访问,闭包可以简单理解成“定义在一个函数内部的函数“。
       JS中,提供了一种”闭包”的概念:在函数内部,定义一个子函数,可以用子函数访问父函数的私有变量。执行完操作以后,将子函数通过return返回。
代码:

function f1(){var n=999;function f2(){alert(n);}return f2;}

2、“闭包”的作用:
(1)、访问函数的私有变量
(2)、让函数的变量始终存在于内存中而不被释放

3、使用“闭包”的注意点
(1)、闭包有一个非常严重的问题,那就是内存浪费问题,这个内存浪费不仅仅因为它常驻内存,更重要的是,对闭包的使用不当会造成无效内存的产生
解决方法是,在退出函数之前,将不使用的局部变量全部删除。
(2)、闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

4、什么叫js继承?
       一般OOP语言都支持俩种继承方式:接口继承和实现继承。
Javascript是只支持实现继承,主要依靠原型链来实现的,一般实现的方法都是通过写prototype的方式,继承后的子对象会拥有父对象的属性和方法。
构造函数,原型和实例的关系:每一个函数都有一个原型对象, 每一个原型对象都有一个指向构造函数的指针,而实例包含了一个指向原型对象的内部(不可见的)指针

5、如何实现js继承?
第一种:prototype方法

//父类function person(){    this.hair='black';    this.eye='black';    this.skin='yellow';    this.view=function(){    return this.hair+','+this.eye+','+this.skin;    }    }//子类    function man(){    this.feature=['bread','strong'];    }//继承man.prototype=new person();var one=new man();document.write(one.feature);    document.write(one.hair);document.write(one.eye);document.write(one.skin);document.write(one.view());

第二种:aaply方法

//父类function person(){    this.hair='black';    this.eye='black';    this.skin='yellow';    this.view=function(){    return this.hair+','+this.eye+','+this.skin;    }    }//子类    function man(){    // person.apply(this,new Array());   person.apply(this,[]);   this.feature=['bread','strong'];    }//继承var one=new man();document.write(one.feature);    document.write(one.hair);document.write(one.eye);document.write(one.skin);document.write(one.view());

注意:如果apply参数为空,即没有参数传递,则通过 new Array() 、[] 来传递,null 无效。

第三种:call+prototype的方法

//父类function person(){    this.hair='black';    this.eye='black';    this.skin='yellow';    this.view=function(){    return this.hair+','+this.eye+','+this.skin;    }    }//子类    function man(){    // person.apply(this,new Array());   person.call(this,[]);   this.feature=['bread','strong'];    }//继承man.prototype=new person();var one=new man();document.write(one.feature);    document.write(one.hair);document.write(one.eye);document.write(one.skin);document.write(one.view());

ps:call方式的实现机制却要多一条 man.prototype = new person(); 为啥呢?
因为call方法只实现了方法的替换而没有作对象属性的复制操作。

6、三种继承方法的优缺点:
如果构造函数带有参数,比如说function person(hair,eye,skin){…}
那么就只能用apply方法或call方法了

//apply方法function man(hair,eye,skin){  person.apply(this,[hair,eye,skin]);   this.feature=['bread','strong'];}
//call方法function man(hair,eye,skin){  person.apply(this,hair,eye,skin);   this.feature=['bread','strong'];}

apply的缺点:在apply方法继承后,上述中的one实例就不属于person函数了,即(one instanceof person)的值为false。
第三种继承方式也有缺陷:子类new对象时要传一遍父类所需的参数,而且会重现父类中的属性和方法
最好的方法:

function Person(name){     this.name = name; } Person.prototype.getName = function() {   return this.name; } function Chinese(name, nation) {   Person.call(this, name);   this.nation = nation; } //继承方法 function inherit(subClass, superClass) {   function F() {}   F.prototype = superClass.prototype;   subClass.prototype = new F();   subClass.prototype.constructor = subClass.constructor; } inherit(Chinese, Person); Chinese.prototype.getNation = function() {   return this.nation; }; var p = new Person('shijun'); var c = new Chinese("liyatang", "China"); console.log(p); // Person {name: "shijun", getName: function} console.log(c); // Chinese {name: "liyatang", nation: "China", constructor: function, getNation: function, getName: function} console.log(p.constructor); // function Person(name){} console.log(c.constructor); // function Chinese(){} console.log(c instanceof Chinese); // true console.log(c instanceof Person); // true
原创粉丝点击