深入理解JavaScript之强大的原型和原型链(1)(2)
重写原型:
在使用第三方JS类库的时候,往往有时候他们定义的原型方法是不能满足我们的需要,但是又离不开这个类库,所以这时候我们就需要重写他们的原型中的一个或者多个属性或function,我们可以通过继续声明的同样的add代码的形式来达到覆盖重写前面的add功能,代码如下:
- //覆盖前面Calculator的add() function
- Calculator.prototype.add = function (x, y) {
- return x + y + this.tax;
- };
- var calc = new Calculator();
- alert(calc.add(1, 1));
这样,我们计算得出的结果就比原来多出了一个tax的值,但是有一点需要注意:那就是重写的代码需要放在最后,这样才能覆盖前面的代码。
原型链
在将原型链之前,我们先上一段代码:
- function Foo() {
- this.value = 42;
- }
- Foo.prototype = {
- method: function() {}
- };
- function Bar() {}
- // 设置Bar的prototype属性为Foo的实例对象
- Bar.prototype = new Foo();
- Bar.prototype.foo = 'Hello World';
- // 修正Bar.prototype.constructor为Bar本身
- Bar.prototype.constructor = Bar;
- var test = new Bar() // 创建Bar的一个新实例
- // 原型链
- test [Bar的实例]
- Bar.prototype [Foo的实例]
- { foo: 'Hello World' }
- Foo.prototype
- {method: ...};
- Object.prototype
- {toString: ... /* etc. */};
上面的例子中,test 对象从 Bar.prototype 和 Foo.prototype 继承下来;因此,它能访问 Foo 的原型方法 method。同时,它也能够访问那个定义在原型上的 Foo 实例属性 value。需要注意的是 new Bar() 不会创造出一个新的 Foo 实例,而是重复使用它原型上的那个实例;因此,所有的 Bar 实例都会共享相同的 value 属性。
属性查找:
当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止,到查找到达原型链的顶部 - 也就是 Object.prototype - 但是仍然没有找到指定的属性,就会返回 undefined,我们来看一个例子:
- function foo() {
- this.add = function (x, y) {
- return x + y;
- }
- }
- foo.prototype.add = function (x, y) {
- return x + y + 10;
- }
- Object.prototype.subtract = function (x, y) {
- return x - y;
- }
- var f = new foo();
- alert(f.add(1, 2)); //结果是3,而不是13
- alert(f.subtract(1, 2)); //结果是-1
通过代码运行,我们发现subtract是安装我们所说的向上查找来得到结果的,但是add方式有点小不同,这也是我想强调的,就是属性在查找的时候是先查找自身的属性,如果没有再查找原型,再没有,再往上走,一直插到Object的原型上,所以在某种层面上说,用 for in语句遍历属性的时候,效率也是个问题。
还有一点我们需要注意的是,我们可以赋值任何类型的对象到原型上,但是不能赋值原子类型的值,比如如下代码是无效的:
- function Foo() {}
- Foo.prototype = 1; // 无效






