有两种创建对象的方法
直接
var x = {};
使用new关键字,即使用构造函数。
var x = new Object(); //要么 var x = new Date(); //使用构造函数。
有没有办法确定如何创建该对象?
答案 0 :(得分:3)
从根本上说,在JavaScript中,我们不关心如何创建对象。我们通常只是假设如果物体像鸭子一样走路并像鸭子一样说话,它就是一只鸭子。 (这被称为“鸭子打字”。)结果也是如此,因为我们不能知道对象是如何创建的。
这里确实有两个问题:
如何判断对象是使用对象初始值设定项({}
)还是new Object
和
如何判断某个对象是使用其中一个还是其他构造函数创建的(如Date
)。
问题1的答案是:你不能。在结果对象中没有任何区别,因此您无法分辨它是如何创建的。
问题2的答案更复杂:
您无法确切知道对象是使用给定的构造函数创建的。 JavaScript太强大了,让你对对象有太多的控制权,因为它可以确定。
您可以知道对象的原型链告诉您的内容,您可以从中推断它的构造方式,但推断可能不正确。
我们带你的
var x = new Date();
例子。要进行推理,您至少可以使用三种工具:
instanceof
:例如,if (x instanceof Date)
。 instanceof
是接受对象和函数的运算符。它检查对象的原型链,以查看函数的prototype
属性引用的对象是否在链中的任何位置。如果是,instanceof
的结果为true
;如果没有,那就是false
。因此,如果使用new Date
创建对象(如果new Foo
来自Foo
,则为Date
),x instanceof Date
将为真。
但是,JavaScript再次强大,你可以欺骗它。例如:
var x = Object.create(Date.prototype);
console.log(x instanceof Date); // true
我们没有使用new Date
来创建该对象,但我们不能说我们没有。 (在这种特殊情况下,x
将无法作为Date
正常工作,因为Date
个对象具有普通对象所没有的特殊内部插槽。许多Date.prototype
1}}函数将在上面失败。但那是Date
- 具体的。)
constructor
属性。默认情况下,函数上的prototype
属性具有指向函数的属性constructor
。例如,Date.prototype.constructor === Date
在正常情况下为true
。由于使用构造函数创建的对象将该对象作为其原型,因此您可以使用constructor
来查看与该对象关联的构造函数(如果有):if (x.constructor === Date)
将创建true
使用new Date
(在正常情况下)。
但同样,我们可以愚弄这个检查:
var x = Object.create({constructor: Date});
console.log(x.constructor === Date); // true
getPrototypeOf
并且相关:您可以直接检查对象的原型链(而不仅仅是通过instanceof
)。但是这与instanceof
具有相同的漏洞:我们可以通过使用Object.create
创建对象(或使用自定义构造函数在Object.create
之前使用自定义构造函数)来欺骗它。
instanceof
的优势在于它会检查整个层次结构,而不依赖于constructor
;在使用ES5及更早版本创建的层次结构中(例如,在ES2015的class
之前),人们经常无法正确设置constructor
。
因此,从根本上说,我们并不关心对象是如何创建的;这也是一样,因为我们无法确切地知道它是如何被创造的。
答案 1 :(得分:2)
你无法区分普通对象的创建,因为对于javascript,这是完全相同的事情。
var o1 = {};
var o2 = new Object();