Javascript继承(上)——对象构建

系统 1927 0

 

Javascript继承(下)——干嘛要继承

 

Quiz1

 

Javascript中存在“类”么?

 

万物皆对象

Javascript中除了基本数据(Undefined、Null、Boolean、Number、String),其他都是对象(Object)。

实际上,Javascript中的对象是数据与功能的集合。例如我们知道:

      
        var
      
       foo = 
      
        new
      
       Function("alert('hello world!')"
      
        );
foo();
      
    

可见foo是一个函数,也是一种对象。再比如说:

      
        function
      
      
         foo(){
    
      
      
        //
      
      
        do something
      
      
        }

foo.data 
      
      = 123
      
        ;
foo[
      
      "data2"] = "hello"
      
        ;

alert(foo.data);
alert(foo.data2);
      
    

函数也可以像对象一样添加属性。

 

对象的构建

一般我们用构造函数来构建对象,但如果没有构造函数,我们也有办法构建我们想要的对象:

      
        function
      
      
         creatPerson(__name, __sex, __age){
    
      
      
        return
      
      
         {
        name: __name,
        sex: __sex,
        age: __age,
        get: 
      
      
        function
      
      
        (__key){
            alert(
      
      
        this
      
      
        [__key]);
        }    
    };
}


      
      
        var
      
       Bob = creatPerson("Bob", "male", 18
      
        );
Bob.get(
      
      "name");    
      
        //
      
      
        Bob
      
      
Bob.get("sex");        
      
        //
      
      
        male
      
      
Bob.get("age");        
      
        //
      
      
        18
      
    

但是这不够,我希望方法是可以共享的。比如我再用该函数创建一个Tom对象,get函数就又被创建了一次,这明显地浪费了我的内存。

 

导入共享资源

因为我们知道函数也是对象,所以我们可以把需要共享的方法或属性放在放在他“身上”:

      
        function
      
      
         creatPerson(__name, __sex, __age){
    
      
      
        var
      
       common =
      
         arguments.callee.common;
    
      
      
        return
      
      
         {
        
      
      
        //
      
      
        自身的属性
      
      
                name: __name,
        sex: __sex,
        age: __age,
        
      
      
        //
      
      
        自身的方法
      
      
        sayhi: 
      
        function
      
      (){alert("hi"
      
        );},
        
      
      
        //
      
      
        共享的方法
      
      
                get: common.get,
        getType: common.getType,
        
      
      
        //
      
      
        共享的属性
      
      
                type: common.type
    };
}
creatPerson.common 
      
      =
      
         {
    get:
      
      
        function
      
      
        (__key){
        alert(
      
      
        this
      
      
        [__key]);
    },
    getType: 
      
      
        function
      
      
        (){
        alert(
      
      
        this
      
      
        .type);
    },
    type: 
      
      "Person"
      
        
};


      
      
        var
      
       Bob = creatPerson("Bob", "male", 18
      
        );
Bob.get(
      
      "name");    
      
        //
      
      
        Bob
      
      
Bob.get("sex");        
      
        //
      
      
        male
      
      
Bob.getType();        
      
        //
      
      
        Person
      
    

于是我们就用蹩脚的方法,成功的创建了一个拥有自有属性方法和共享属性方法的对象。但实际上,Javascript就是这么蹩脚地创建对象的。

其实共享属性没有真正实现,因为这个共享属性,依然只是一个副本。这并不是我们真正希望的共享属性。

 

new关键字

和上面的“对象的构建”相同,new的目的是创建对象的自有属性和方法。例如:

      
        function
      
      
         Person(__name, __sex, __age){
    
      
      
        this
      
      .name =
      
         __name;
    
      
      
        this
      
      .sex =
      
         __sex;
    
      
      
        this
      
      .age =
      
         __age;
    
      
      
        this
      
      .get = 
      
        function
      
      
        (__key){
        alert(
      
      
        this
      
      
        [__key]);
    };
}


      
      
        var
      
       Bob = 
      
        new
      
       Person("Bob", "male", 18
      
        );
Bob.get(
      
      "name");    
      
        //
      
      
        Bob
      
      
Bob.get("sex");        
      
        //
      
      
        male
      
      
Bob.get("age");        
      
        //
      
      
        18
      
    

 

原型(Prototype)

Javascript的作者用了和上面“导入共享资源”的方法差不多。既然函数也是对象,那么把需要共享的“东东”放在他“身上”吧:

      
        function
      
      
         Person(__name, __sex, __age){
    
      
      
        this
      
      .name =
      
         __name;
    
      
      
        this
      
      .sex =
      
         __sex;
    
      
      
        this
      
      .age =
      
         __age;
    
      
      
        this
      
      .sayhi = 
      
        function
      
      
        (__key){
        alert(
      
      "hi"
      
        );
    };
}
Person.prototype 
      
      =
      
         {
    constructor: Person,
    get: 
      
      
        function
      
      
        (__key){
        alert(
      
      
        this
      
      
        [__key]);
    }
};


      
      
        var
      
       Bob = 
      
        new
      
       Person("Bob", "male", 18
      
        );
Bob.get(
      
      "name");    
      
        //
      
      
        Bob
      
      
Bob.get("sex");        
      
        //
      
      
        male
      
      
alert(Bob.constructor);    
      
        //
      
      
        function Person
      
    

Javascript创建对象的模型是简洁的,new来处理自身问题,prototype来处理共享问题。

如果说Java的对象(实例)产生方式是将原材料丢到模子里(类)熔炼而成;那么Javascript的对象产生方式就是给材料给建筑工(构造函数)让他按图纸搭建而成。

 

实际流程

当然实际流程并稍稍有些变化,新建一个对象先做的是处理共享资源,例如:

      
        function
      
      
         A(){
    console.dir(
      
      
        this
      
      
        );
    alert(
      
      
        this
      
      .type);    
      
        //
      
      
        A
      
      
        }
A.prototype.type 
      
      = "A"
      
        ;


      
      
        var
      
       a = 
      
        new
      
       A();
    

通过console.dir将a打印出来我们可以看到:

type "A"
__proto__ A {type = "A"}
  type "A"
  constructor A()

 

 

 

构造函数新建一个对象以后,立刻将其prototype的引用赋给新建对象的内部属性__proto__,然后再运行构造函数里面的构造语句。

 

并没有覆盖

      
        function
      
      
         A(){
    
      
      
        this
      
      .type = "B"
      
        
}
A.prototype.type 
      
      = "A"
      
        ;


      
      
        var
      
       a = 
      
        new
      
      
         A();
alert(a.type);    
      
      
        //
      
      
        B
      
    

当我们想得到a.type时,引擎会先去在a对象中查看是否有属性type,如果有则返回该属性,没有则试图在__proto__中查找是否有type属性,如果有则返回该属性。

__proto__并不是标准的,比如IE上没有,但IE上也有类似的内部属性,但我们也无法使用它。

基于这个原因,我们删掉a.type时依然可以返回a.type:

      
        function
      
      
         A(){
    
      
      
        this
      
      .type = "B"
      
        
}
A.prototype.type 
      
      = "A"
      
        ;


      
      
        var
      
       a = 
      
        new
      
      
         A();
alert(a.type);    
      
      
        //
      
      
        B
      
      
        delete
      
      
         a.type;
alert(a.type);    
      
      
        //
      
      
        A
      
    

 

到底有没有类?

  • 严格地讲,Javascript并没有类(class)这种东西。
  • 但有时候我们会用构造函数的名字作为利用该构造函数创建的对象们的“类型(type not class)名”,以方便我们用Javascript进行面向对象编程时的交流。

名字只是一个代号,一个方便理解的工具罢了。

 

 

参考文献

Javascript继承机制的设计思想 . 阮一峰 . 2011年6月5日

 

补充阅读

Javascript的声明

Javascript引用  

Javascript中this关键字详解

Javascript继承(上)——对象构建


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论