zoukankan      html  css  js  c++  java
  • javascrip原型模式创建对象

      要实现更高的数据代码共享,则应使用原型模式。

    1.原型对象

      在javascript中,我们创建函数时,都会有一个prototype属性即原型属性。这个属性是一个指针,指向一个对象,这个对象的用途就是实现实例的属性、方法共享。

      在默认情况下,所有的原型对象都会自动获得一个constructor属性即构造函数属性,该属性指向原对象。

      这个神马内存指向的图我是不会画。话说Visio能不能画这种图哇。有木有大神讲解一下~

      反正就是:

    Dog.prototype.constructor==Dog;//true
    dog1.prototype.constructor==Dog;//true

      也可以使用:

    Dog.prototype.isPrototypeOf(dog1);//true
    Object.getPrototypeOf(dog1)==Person.prototype;//true
    

      虽然可以通过对象实例访问保存在原型中的值,但却不能通过实例重写原型中的值,如果我们在实例中添加了一个同名属性,则可以理解为同名覆盖(此处开辟内存)。

    2.原型函数

    function Dog(){}
    Dog.prototype.age=11;
    Dog.prototype.size=22;
    Dog.prototype.toAge=function()
    {
      alert(this.age);
    };
    
    var dog1=new Dog();
    var dog2=new Dog();
    
    dog1.age=20;
    dog1.toAge();//20,来自实例
    dog2.toAge();//11,来自原型
    

      delete操作符可以删除实例属性,从而让我们能够重新访问原型中的属性。

      再提一句,hasOwnProperty()方法只有在实例重写属性之后才能访问。

      而in操作符单独使用时,无论属性存在于实例中还是原型中,都可以访问。

      除此之外,还有hasPrototypeProperty()函数用于访问原型中的属性。

      要取得对象上所有可枚举的实例属性,可以使用Object.keys()方法。例如:

    function Dog(){}
    Dog.prototype.age=11;
    Dog.prototype.size=33;
    Dog.prototype.toAge()
    {
      alert(this.age);
    };
    
    var keys=Object.keys(Dog.prototype);
    alert(keys);//"age,size,toAge"
    
    var p1=new Dog();
    p1.age=10;
    p1.size=44;
    var p1keys=Object.keys(p1);
    alert(p1keys);//"age,size"
    

      如果你想得到所有实例属性可以使用Object.getOwnPropertyNames()方法。用法如下:

    var keys=Object.getOwnPropertyNames(Dog.prototype);
    alert(keys);//"constructor,age,size,toAge"
    

      获取属性的方法就介绍到这里。//都闪开,都闪开,后面这段我要吹牛逼了,大家看看就行......

      其实更简单的原型语法如下:

    function Dog(){}
    Dog.prototype={
      age:12,
      size:44,
      toAge:function(){
      alert(this.age);
      }
    };
    
    var dog=new Dog;
    

      但是这里实际上,完全重写了prototype对象,所以此时的原型对象的constructor属性已经不指向Dog函数了。例如:

    alert(dog instanceof Object);//true
    alert(dog instanceof Dog);//true
    alert(dog.constructor==Object);//true
    alert(dog.constructor==Dog);//false
    

      虽然使用instanceof还能返回正确结果,但是constructor已经无法确定对象的类型。但是依然可以为constructor设置为Dog。例如这样编写:

    Dog.prototype={
      constructor:Dog
    };

      注意,重设构造函数只适用于ECMAScript5兼容浏览器。并且重设构造函数 会使默认的constructor变为可枚举的,您可以使用Object.defineProterty()函数改变。

    Object.defineProterty(Dog.prototype,"constructor",{
        enumerable:false;//设置为不可枚举
        value:Dog
    });
    

      在重写原型对象后,在重写之前的实例,属性即不可访问。

      仔细理解:实例中的指针,仅指向原型,而不指向构造函数。重写了原型,则切断了函数与初始原型间的联系。实例依然指向初始原型,实例不可访问重写后原型的属性。

      我这还有个问题,有木有大神帮忙解答,就是我能否访问实例的原型。为什么我是用dog1.prototype输出undefined。

      顺便说一句,原生对象的方法也是在原型中定义的,如(Object,Array,String,等)。

      原型对象的问题:对于包含引用类型值的属性来说,修改其属性值会导致,所有实例的值发生变化。所以很少有人单独使用原型模式。

      引用类型值:指的是那些保存在堆内存中的对象,意思是,变量中保存的实际上只是一个指针,这个指针执行内存中的另一个位置,由该位置保存对象。

    后记:上面的问题“为什么我是用dog1.prototype输出undefined”已经在知乎解决:使用dog1.__proto__访问。下面有附图我觉得很高大上的样子,可惜不太搞得懂。详情见知乎:

      

  • 相关阅读:
    [Linux] Chmod 改变权限
    [linux命令]基本命令
    [Linux命令] 查看目录大小du
    [Linux命令]格式化mkfs
    在VMWare下的Linux切换
    .net的MSMQ异步调用
    CASSINI源代码分析
    [Wix] RadioButton与ListItem的属性要改掉了
    如何快速生成Insert数据插入语句?
    撕纸
  • 原文地址:https://www.cnblogs.com/stonl/p/4260702.html
Copyright © 2011-2022 走看看