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__访问。下面有附图我觉得很高大上的样子,可惜不太搞得懂。详情见知乎:

  

 

posted @ 2015-01-29 19:16  小北先森  阅读(251)  评论(0编辑  收藏  举报