`obj.prototype` 和 `Object.getPrototypeOf(obj)` 的结果为什么不相同

vanisseg
  • 236

我有这样的代码

'use strict';
let log = console.log;

let cParent = function () {
  this.property1 = arguments[0] || null;
  this.property2 = arguments[1] || null;
  this.log = function () {
    log('log: ', this.property1);
  }
};

let obj1 = new cParent(4, 5);
log(obj1.prototype);
log(Object.getPrototypeOf(obj1));
log(cParent.prototype);
log(Object.getPrototypeOf(cParent));

得到的结果是

undefined
{}
{}
[Function]
回复
阅读 1.7k
4 个回答

原来以前对原型链的理解一直有问题,根据 @kmxz 的提示,参考了其他回答
对象的 prototype 属性的方法、属性为对象所属的那一“类”所共有。对象原型链通过 __proto__ 属性向上寻找。
__proto__ 指定 null 之外的原始类型(Number, String, Boolean, undefined, Symbol)值是无效的。
通过构造函数或者 {} 方式创建的对象的 prototype 属性默认为 undefined

{} 的继承

var a = {
  x: 10,
  calculate: function (z) {
    return this.x + this.y + z;
  }
};
 
var b = {
  y: 20,
  __proto__: a
};
 
var c = {
  y: 30,
  __proto__: a
};
 
// call the inherited method
b.calculate(30); // 60
c.calculate(40); // 80

如果没有明确指定,那么 __proto__ 默认为 Object.prototype,而Object.prototype 自身也有 __proto__ ,值为 null,是原型链的终点。

If a prototype is not specified for an object explicitly, then the default value for __proto__ is taken — Object.prototype. Object Object.prototype itself also has a __proto__, which is the final link of a chain and is set to null.

enter image description here

构造函数模式的继承

// a constructor function
function Foo(y) {
  // which may create objects
  // by specified pattern: they have after
  // creation own "y" property
  this.y = y;
}
 
// also "Foo.prototype" stores reference
// to the prototype of newly created objects,
// so we may use it to define shared/inherited
// properties or methods, so the same as in
// previous example we have:
 
// inherited property "x"
Foo.prototype.x = 10;
 
// and inherited method "calculate"
Foo.prototype.calculate = function (z) {
  return this.x + this.y + z;
};
 
// now create our "b" and "c"
// objects using "pattern" Foo
var b = new Foo(20);
var c = new Foo(30);
 
// call the inherited method
b.calculate(30); // 60
c.calculate(40); // 80
 
// let's show that we reference
// properties we expect
 
console.log(

  b.__proto__ === Foo.prototype, // true
  c.__proto__ === Foo.prototype, // true
 
  // also "Foo.prototype" automatically creates
  // a special property "constructor", which is a
  // reference to the constructor function itself;
  // instances "b" and "c" may found it via
  // delegation and use to check their constructor
 
  b.constructor === Foo, // true
  c.constructor === Foo, // true
  Foo.prototype.constructor === Foo, // true
 
  b.calculate === b.__proto__.calculate, // true
  b.__proto__.calculate === Foo.prototype.calculate // true
  
);

如果没有明确指定,通过构造函数创建的对象的 __proto__ 属性值为构造函数的 prototype 属性。

enter image description here

obj.__prototype__Object.getPrototypeOf(obj) 的结果才会相同。而他们通常又与 obj.constructor.prototype 相同。

在你的例子中,也就是 cParent.prototype === obj1.__proto__cParent.prototype === Object.getPrototypeOf(obj1)

一个是找爸爸一个是找老公 当然不同了

// 结果
log(obj1.prototype);                //undefined         : prototype 是所有函数才有的属性,实例对象没有此属性
log(Object.getPrototypeOf(obj1));   //{}                :Object.getPrototypeOf(obj1) === obj1.__proto__ === cParent.prototype 返回构造函数的prototype对象
log(cParent.prototype);             //{}                :Object.getPrototypeOf(obj1) === obj1.__proto__ === cParent.prototype 返回构造函数的prototype对象
log(Object.getPrototypeOf(cParent));//function () {}    :Object.getPrototypeOf(cParent) === cParent.__proto__ === Function.prototype
你知道吗?

宣传栏