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

How to tell if an object was created with 'Object.create' or using literal syntax/'new' keyword

本文关键字:语法 文字 new 关键字 创建 何判断 判断 对象 create Object      更新时间:2023-09-26

我试图弄清楚是否有办法判断对象是使用 Object.create() 还是使用 new 关键字/文字语法创建的。 由于使用 Object.create() 创建的对象不会从原型属性中删除属性(它们只是复制所有属性(,而使用new和文字语法创建的对象仅从原型属性中获取属性,因此似乎很难判断对象是如何创建的。 例如:

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   

似乎没有任何方法可以告诉对象继承其属性的方法。 有什么想法吗?

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构造函数,因此它不会具有此类对象通常执行的任何属性。

由于示例构造函数为空,因此一旦修复了此问题,这两个对象将对各种测试具有相同的响应。这并不能帮助你区分(因为你不能(,但它应该帮助你不需要区分。

没有办法可靠地确定对象是使用 Object.create 还是新的 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设计上不会在原型链中留下可检测的面包屑。