面向对象的JavaScript 三 ----- prototype

本文主要介绍javascript中另文容易产生误解和误用的prototype属性。

prototype是functions对象的属性,也是在javascript中实现继承的面向对象机制的关键,所以有必要弄懂prototype属性。
首先看看一个普通对象的prototype属性是什么:
>>> typeof foo.prototype
       "object"
看来所有对象最终都是继承object的,这和java等语言一样。
通过prototype可以给function加上函数和属性。
Gadget.prototype.price = 100;
Gadget.prototype.rating = 3;
Gadget.prototype.getInfo = function() {
  return 'Rating: ' + this.rating + ', price: ' + this.price;
};
或者,用下面这种写法:
Gadget.prototype = {
  price: 100,
  rating: 3,
  getInfo: function() {
    return 'Rating: ' + this.rating + ', price: ' + this.price;
  }
};
使用prototype增加属性,该属性是不会拷贝到每个function实例的.这个表示,你可以修改一个function实例的prototype属性,这个修改会作用到所有实例上.这有点类似java中的类的static成员变量。

接下来看一个实例,让你理解js engine在查找prototype属性的方法:
function Gadget(name) {
  this.name = name;
}
Gadget.prototype.name = 'foo';    
>>> var toy = new Gadget('camera');
>>> toy.name;
       "camera"

>>> delete toy.name;
     true
>>> toy.name;
     "foo"
如果访问的是prototype 属性,js 回找不到,然后会找到constructor的prototype。所以在delete后,第二次调用name返回的是“foo”

那么如何遍历得到一个对象的prototype属性呢?可以这样:
for (var prop in newtoy) {
  console.log(prop + ' = ' + newtoy[prop]);
}
如果你想区分prototype属性,可以这样写:
如果你想区分,可以使用:
>>> newtoy.hasOwnProperty('name')
     true
>>> newtoy.hasOwnProperty('price')
     false
或者合在一起:
for (var prop in newtoy) {
  if (newtoy.hasOwnProperty(prop)) {
    console.log(prop + '=' + newtoy[prop]);
  }
}

每个对象还有isPrototypeOf方法,作用如下:
var monkey = {  
  hair: true,  
  feeds: 'bananas', 
  breathes: 'air'
};
function Human(name) {  
  this.name = name;
}
Human.prototype = monkey;
>>> var george = new Human('George');
>>> monkey.isPrototypeOf(george)
      true
这个是不是让你想到继承。在之后的文章里我会详细讲解继承部分。

最后介绍一个很有趣的东西,看看下面的代码:
>>> function Dog(){this.tail = true;}
>>> var benji = new Dog();
>>> var rusty = new Dog();

>>> Dog.prototype.say = function(){return 'Woof!';}

>>> benji.say();
     "Woof!"
>>> benji.constructor;
   Dog()
现在一切都很正常。

但是我们在做一点试验
>>> benji.constructor.prototype.constructor
       Dog()
现在让我们覆盖prototype
>>> Dog.prototype = {paws: 4, hair: true};
然后调用试试
>>> typeof benji.paws
     "undefned"
>>> benji.say()
     "Woof!"
>>> typeof benji.__proto__.say
       "function"
>>> typeof benji.__proto__.paws
       "undefned"
发现仍旧是旧的prototype,我们新赋值的prototype没有起到任何作用

现在我们在实例化一个Dog
>>> var lucy = new Dog();
>>> lucy.say()
     TypeError: lucy.say is not a function TypeError: lucy.say is not a function
>>> lucy.paws
    4
>>> typeof lucy.__proto__.say
     "undefned"
>>> typeof lucy.__proto__.paws
     "number"

你会发现:
>>> lucy.constructor
      Object()
>>> benji.constructor
      Dog()
>>> typeof lucy.constructor.prototype.paws
  "undefned"
>>> typeof benji.constructor.prototype.paws
  "number"
很有趣吧,难道你觉得我很无聊?

其实解决这个问题的方法如下:
>>> Dog.prototype = {paws: 4, hair: true};
>>> Dog.prototype.constructor = Dog;
所以,每当你重写了prototype,最好重置constructor属性
如果你问我为什么,我不知道.

现在你已经有了足够的javascript知识,下一篇文章将正式开始进入javascript的面向对象世界。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值