如何判断对象是使用'Object.create'还是使用文字语法/'new'关键字创建的

时间:2016-02-08 20:13:28

标签: javascript

我正在试图弄清楚是否有方法可以判断对象是使用Object.create()还是使用new关键字/文字语法创建的。因为使用Object.create()创建的对象不会从prototype属性中获取属性(它们只是复制所有属性),而使用new和文字语法创建的对象仅使用prototype属性中的属性,似乎很难说出对象是如何创建的。例如:

function Meat() {};
var beef = new Meat();
var tuna = Object.create(Meat);

console.log(Object.getPrototypeOf(tuna));//=> [Function: Meat]
console.log(Object.getPrototypeOf(beef));//=> {}

console.log(tuna.constructor.prototype);//=> [Function]
console.log(beef.constructor.prototype);//=> {}

console.log(tuna.prototype);//=> {}
console.log(beef.prototype);//=> undefined

console.log(tuna.__proto__);//=> object
console.log(beef.__proto__);//=> object

console.log(typeof tuna);//=> object
console.log(typeof beef);//=> object

console.log(Meat.prototype.isPrototypeOf(tuna));//=> false
console.log(Meat.prototype.isPrototypeOf(beef));//=> true   

似乎没有办法告诉对象继承它的属性的方法。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

Object.create是一种非常通用的对象构造操作。 没有办法告诉对象是否是使用Object.create创建的,因为这些对象没有可靠的功能(除此之外他们无法做到)本机对象或代理)。

根本不是Object.create只是复制所有属性“ - 它只是将[[Prototype]](又名__proto__)引用设置为您提供的值。唯一类似“复制”的行为是指定可选的第二个参数,但它采用属性描述符

我注意到你犯了一个错误,可能会让你混淆这个问题:

 var tuna = Object.create(Meat);

如果您的意思是“制作一个类似于new Meat()”结果的对象,那么这是错误的。你想要的是:

var tuna = Object.create(Meat.prototype);

因为Object.create的参数是新对象的原型,而不是构造函数。通过执行此操作获得的对象将对instanceofisPrototypeOf等作为new Meat()作出相同的反应;它只是没有在其上运行Meat构造函数,因此它不会拥有此类对象通常所做的任何属性。

由于您的示例构造函数为空,一旦您解决了这个问题,这两个对象将对您的各种测试产生相同的响应。这并不能帮助你区分(因为你不能),但它应该可以帮助你不需要分辨出来。

答案 1 :(得分:0)

无法可靠地确定对象是否是使用Object.create或new someFunction语法创建的。对象的constructor属性是最有用的指南,但不保证结果。例如:

function Foo() {};
var foo = new Foo();
foo.constructor == Foo; // true

constructor不是只读属性,所以

Foo.prototype.constructor = Object;
foo.constructor == Foo;  // changes to false

完整地设置构造函数的原型对象通常也会将构造函数(由实际构造函数创建的对象继承)更改为原型的构造函数:

Foo.prototype = {foo: "was here"};
var foo = new Foo ();
foo.constructor == Foo;   // false
foo.constructor == Object;  // true, the constructor of {foo: "was here"} is Object.

最后一个结果,foo的原型链结构现在与Object.create创建的结构相同:

var foo = Object.create({foo: "was here"};
foo.constructor == Object;  // true;

但为了突破这个有用的希望,Object.create()返回对象的构造函数不必是Object:

var bar = Object.create( new Foo()); // the original Foo
bar.constructor == Object ; // false
bar.constructor == Foo;     // true; 

或多或少的任何组合"关键属性"可以使用构造函数 Object.create进行设置。某些组合可能是人为的,但其他组合将是设计或易于编码。

Object.create不会通过设计在原型链中留下可检测到的面包屑。