Page 169 - Node.js开发指南
P. 169

162  附录 A  JavaScript 的高级特性


                 };

                 var foo1 = new Foo();
                 var foo2 = new Foo();

                 console.log(foo1.func1 == foo2.func1); // 输出 false
                 console.log(foo1.func2 == foo2.func2); // 输出 true

                 尽管如此,并不是说在构造函数内创建属性不好,而是两者各有适合的范围。那么我们
             什么时候使用原型,什么时候使用构造函数内定义来创建属性呢?
                  除非必须用构造函数闭包,否则尽量用原型定义成员函数,因为这样可以减少开销。
                  尽量在构造函数内定义一般成员,尤其是对象或数组,因为用原型定义的成员是多个
                   实例共享的。
                 接下来,我们介绍一下JavaScript中的原型链机制。
                 原型链
                 JavaScript 中有两个特殊的对象: Object 与 Function,它们都是构造函数,用于生
             成对象。Object.prototype 是所有对象的祖先,Function.prototype 是所有函数的原
             型,包括构造函数。我把 JavaScript 中的对象分为三类,一类是用户创建的对象,一类是构
             造函数对象,一类是原型对象。用户创建的对象,即一般意义上用 new 语句显式构造的对
             象。构造函数对象指的是普通的构造函数,即通过 new 调用生成普通对象的函数。原型对象
             特指构造函数 prototype 属性指向的对象。这三类对象中每一类都有一个 __proto__ 属
             性,它指向该对象的原型,从任何对象沿着它开始遍历都可以追溯到 Object.prototype。
             构造函数对象有 prototype 属性,指向一个原型对象,通过该构造函数创建对象时,被创
             建对象的 __proto__ 属性将会指向构造函数的 prototype 属性。原型对象有 constructor
             属性,指向它对应的构造函数。让我们通过下面这个例子来理解原型:

                 function Foo() {
                 }
                 Object.prototype.name = 'My Object';
                 Foo.prototype.name = 'Bar';

                 var obj = new Object();
                 var foo = new Foo();
                 console.log(obj.name); // 输出 My Object
                 console.log(foo.name); // 输出 Bar
                 console.log(foo.__proto__.name); // 输出 Bar
                 console.log(foo.__proto__.__proto__.name); // 输出 My Object
                 console.log(foo. __proto__.constructor.prototype.name); // 输出 Bar
                 我们定义了一个叫做 Foo ()的构造函数,生成了对象 foo。同时我们还分别给 Object
             和 Foo 生成原型对象。
   164   165   166   167   168   169   170   171   172   173   174