1. function Animal(name) {
  2. this.name = name;
  3. }
  4. Animal.prototype.color = 'white';
  5. var cat1 = new Animal('大毛');
  6. var cat2 = new Animal('二毛');
  7. cat1.color // 'white'
  8. cat2.color // 'white'

prototype 创作出来的目的:原型对象所有属性和方法,都能被实例对象共享。
创建一个原型:

  1. function f() {}
  2. typeof f.prototype // "object"

原型链

JavaScript 规定,所有对象都有自己的原型对象(prototype)。一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型。因此,就会形成一个“原型链”(prototype chain):对象到原型,再到原型的原型……

所有对象的原型最终都可以上溯到Object.prototype,即Object构造函数的prototype属性。也就是说,所有对象都继承了Object.prototype的属性。这就是所有对象都有valueOf和toString方法的原因,因为这是从Object.prototype继承的。
那么,Object.prototype对象有没有它的原型呢?回答是Object.prototype的原型是null。null没有任何属性和方法,也没有自己的原型。因此,原型链的尽头就是null。

  1. Object.getPrototypeOf(Object.prototype)
  2. // null

如果让构造函数的prototype属性指向一个数组,就意味着实例对象可以调用数组方法。

  1. var MyArray = function () {};
  2. MyArray.prototype = new Array();
  3. MyArray.prototype.constructor = MyArray;
  4. var mine = new MyArray();
  5. mine.push(1, 2, 3);
  6. mine.length // 3
  7. mine instanceof Array // true

由于MyArray.prototype指向一个数组实例,使得mine可以调用数组方法(这些方法定义在数组实例的prototype对象上面)。最后那行instanceof表达式,用来比较一个对象是否为某个构造函数的实例,结果就是证明mine为Array的实例,instanceof运算符的详细解释详见后文。

constructor 属性

constructor属性,默认指向prototype对象所在的构造函数。

  1. // 坏的写法
  2. C.prototype = {
  3. method1: function (...) { ... },
  4. // ...
  5. };
  6. // 好的写法
  7. C.prototype = {
  8. constructor: C,
  9. method1: function (...) { ... },
  10. // ...
  11. };
  12. // 更好的写法
  13. C.prototype.method1 = function (...) { ... };

如果不能确定constructor属性是什么函数,还有一个办法:通过name属性,从实例得到构造函数的名称。

  1. function Foo() {}
  2. var f = new Foo();
  3. f.constructor.name // "Foo"

instanceof 运算符

instanceof运算符返回一个布尔值,表示对象是否为某个构造函数的实例。
由于instanceof检查整个原型链,因此同一个实例对象,可能会对多个构造函数都返回true。

  1. var d = new Date();
  2. d instanceof Date // true
  3. d instanceof Object // true

由于任意对象(除了null)都是Object的实例,所以instanceof运算符可以判断一个值是否为非null的对象。

  1. var obj = { foo: 123 };
  2. obj instanceof Object // true
  3. null instanceof Object // false

上面代码中,除了null,其他对象的instanceOf Object的运算结果都是true。
如果一个对象的原型是null,instanceof判断会失真。
instanceof运算符只能用于对象,不适用原始类型的值。