实现javaScript对象的"继承"的两种方法(prototype与闭包)

javaScript的prototype属性:

什么是prototype:

javaScript的方法分为三类:

  • 类方法

  • 对象方法

  • 原型方法

function People(name)
{
  this.name=name;
  //对象方法
  this.Introduce=function(){
    alert("My name is "+this.name);
  }
}
//类方法
People.Run=function(){
  alert("I can run");
}
//原型方法
People.prototype.IntroduceChinese=function(){
  alert("我的名字是"+this.name);
}



//测试

var p1=new People("Windking");

p1.Introduce();

People.Run();

p1.IntroduceChinese();

javascript中的每个对象都有prototype属性,Javascript中对象的prototype属性的解释是:返回对象类型原型的引用。

定义:原型就是一个函数对象的属性。
作用:

  • 利用原型为函数对象增加属性和方法
  • 函数对象的属性或方法与原型的属性或方法同名时:
  • 函数对象本身的属性和方法的优先级要高于原型上的熟悉感和方法
  • 利用函数对象的属性和方法重写原型上的属性和方法
  • 内建对象(应该都是函数对象):都有prototype属性
  • 可以扩展内建对象的属性和方法
  • 实现继承

在简单了解了prototype的作用后,我们来使用prototype来实现继承。

利用prototype来实现继承

定义一个Person类

function  Person(){
   this.sayHello = function(){
      alert("helloworld");
     }
}
Person.prototype.setName=function(name){
  this.name = name;
}
Person.prototype.getName=function(){
  return this.name;
}
var p = new Person();
p.sayHello();
p.setName("wang");
alert(p.getName());

现在我们定义一个Student类来继续Person类:

function Student(){

}
Student.prototype = new Person();
var s = new Student();
s.sayHello();
s.setName("xi");
alert(s.getName());

这样Student类即继承了Person类。

使用javaScript的闭包来完成继承:

1.什么是js的闭包

js闭包Demo:

    function A(){ 

    function B(){
     alert("Hello Closure!"); 
} 
 return B; 
} 
  var b = A(); 
   b();//Hello Closure! 

这是史上最简单的闭包,不能再简单了,再简单就不是闭包了!B为在函数内部定义的函数,用A函数返回,并用b来接收,也就是说在函数内部定义的函数,在外部使用,这种现象为闭包,所以继承的封装是闭包的一种应用。

2.闭包的作用

avascript中的GC机制:在javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收,否则这个对象一直会保存在内存中。

在上述例子中,B定义在A中,因此B依赖于A,而外部变量b又引用了B, 所以A间接的被b引用,也就是说,A不会被GC回收,会一直保存在内存中。
这就是闭包的作用,有时候我们需要一个模块中定义这样一个变量:希望这个变量一直保存在内存中但又不会“污染”全局的变量,这个时候,我们就可以用闭包来定义这个模块。

闭包无处不在,比如:jQuery、zepto的主要代码都包含在一个大的闭包中,上面的写法其实是最简单最原始的写法,而在实际应用中,没人这么玩,特别是在一些大型JS框架中更不会这么写。现在我们来写一个闭包的高端用法:

    (function(document){ 

        var viewport; 

        var obj = { 
           init:function(id)
           {         
           viewport = document.querySelector("#"+id);   
           },          
           addChild:function(child){ 
           viewport.appendChild(child); 
           }, 
           removeChild:function(child){
            viewport.removeChild(child); 
           } } 
        window.jView = obj; 

    })(document); 

这个组件的作用是:初始化一个容器,然后可以给这个容器添加子容器,也可以移除一个容器。功能很简单,但这里涉及到了另外一个概念:立即执行函数。 简单了解一下就行。主要是要理解这种写法是怎么实现闭包功能的。

(function(){})() 红色部分是一个表达式,而这个表达式本身是一个匿名函数,所以在这个表达式后面加()就表示执行这个匿名函数。

因此这段代码执行执行过程可以分解如下:

    var f = function(document){

        var viewport; 

        var obj = { 

         init:function(id){ 
            viewport = document.querySelector("#"+id);
         },
        addChild:function(child){        
             viewport.appendChild(child); 
         }, 
         removeChild:function(child){               
            viewport.removeChild(child);
          } }

 window.jView = obj; 

    }; 

    f(document); 

在这段代码中似乎看到了闭包的影子,但 f 中没有任何返回值,似乎不具备闭包的条件,注意这句代码:

    window.jView = obj;

obj 是在 f 中定义的一个对象,这个对象中定义了一系列方法, 执行window.jView = obj 就是在 window 全局对象定义了一个变量 jView,并将这个变量指向 obj 对象,即全局变量 jView 引用了 obj . 而 obj 对象中的函数又引用了 f 中的变量 viewport ,因此 f 中的 viewport 不会被GC回收,会一直保存到内存中,所以这种写法满足闭包的条件。

了解了js的闭包之后使用闭包来实现继承

function extend(obj1){
    function F(){ }
   //判断传递进行的是一个new出来的对象
   if(typeof obj1 == "object"){
        for(var i in obj1){
        //直接调用对象的属性来获取,调用方法的prototype来接受
          F.prototype[i] = obj1[i];
         }
    }
    //返回函数
    return  F;
}
var person_son = extend(new Person());
var p = new person_son();
p.sayHello();
p.setName("abc");
alert(p.getName());

如上使用闭包也可以完成继承。

你可能感兴趣的:(javaScript)