龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > Javascript编程 >

深入理解JavaScript之强大的原型和原型链(1)(2)

时间:2013-03-06 14:58来源:未知 作者:admin 点击:
分享到:
重写原型: 在使用第三方JS类库的时候,往往有时候他们定义的原型方法是不能满足我们的需要,但是又离不开这个类库,所以这时候我们就需要重写他们

重写原型:

在使用第三方JS类库的时候,往往有时候他们定义的原型方法是不能满足我们的需要,但是又离不开这个类库,所以这时候我们就需要重写他们的原型中的一个或者多个属性或function,我们可以通过继续声明的同样的add代码的形式来达到覆盖重写前面的add功能,代码如下:

  1. //覆盖前面Calculator的add() function   
  2. Calculator.prototype.add = function (x, y) {  
  3.     return x + y + this.tax;  
  4. };  
  5.  
  6. var calc = new Calculator();  
  7. alert(calc.add(1, 1)); 

这样,我们计算得出的结果就比原来多出了一个tax的值,但是有一点需要注意:那就是重写的代码需要放在最后,这样才能覆盖前面的代码。

原型链

在将原型链之前,我们先上一段代码:

  1. function Foo() {  
  2.     this.value = 42;  
  3. }  
  4. Foo.prototype = {  
  5.     method: function() {}  
  6. };  
  7.  
  8. function Bar() {}  
  9.  
  10. // 设置Bar的prototype属性为Foo的实例对象  
  11. Bar.prototype = new Foo();  
  12. Bar.prototype.foo = 'Hello World';  
  13.  
  14. // 修正Bar.prototype.constructor为Bar本身  
  15. Bar.prototype.constructor = Bar;  
  16.  
  17. var test = new Bar() // 创建Bar的一个新实例  
  18.  
  19. // 原型链  
  20. test [Bar的实例]  
  21.     Bar.prototype [Foo的实例]   
  22.         { foo: 'Hello World' }  
  23.         Foo.prototype  
  24.             {method: ...};  
  25.             Object.prototype  
  26.                 {toString: ... /* etc. */}; 

上面的例子中,test 对象从 Bar.prototype 和 Foo.prototype 继承下来;因此,它能访问 Foo 的原型方法 method。同时,它也能够访问那个定义在原型上的 Foo 实例属性 value。需要注意的是 new Bar() 不会创造出一个新的 Foo 实例,而是重复使用它原型上的那个实例;因此,所有的 Bar 实例都会共享相同的 value 属性。

属性查找:

当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止,到查找到达原型链的顶部 - 也就是 Object.prototype - 但是仍然没有找到指定的属性,就会返回 undefined,我们来看一个例子:

  1. function foo() {  
  2.            this.add = function (x, y) {  
  3.                return x + y;  
  4.            }  
  5.        }  
  6.  
  7.        foo.prototype.add = function (x, y) {  
  8.            return x + y + 10;  
  9.        }  
  10.  
  11.        Object.prototype.subtract = function (x, y) {  
  12.            return x - y;  
  13.        }  
  14.  
  15.        var f = new foo();  
  16.        alert(f.add(1, 2)); //结果是3,而不是13  
  17.        alert(f.subtract(1, 2)); //结果是-1 

通过代码运行,我们发现subtract是安装我们所说的向上查找来得到结果的,但是add方式有点小不同,这也是我想强调的,就是属性在查找的时候是先查找自身的属性,如果没有再查找原型,再没有,再往上走,一直插到Object的原型上,所以在某种层面上说,用 for in语句遍历属性的时候,效率也是个问题。

还有一点我们需要注意的是,我们可以赋值任何类型的对象到原型上,但是不能赋值原子类型的值,比如如下代码是无效的:

  1. function Foo() {}  
  2. Foo.prototype = 1; // 无效 

精彩图集

赞助商链接