如何区分使用{}创建的对象与使用new关键字创建的对象

时间:2017-03-11 08:05:21

标签: javascript

有两种创建对象的方法

  1. 直接

    var x = {};

  2. 使用new关键字,即使用构造函数。

    var x = new Object(); //要么 var x = new Date(); //使用构造函数。

  3. 有没有办法确定如何创建该对象?

2 个答案:

答案 0 :(得分:3)

从根本上说,在JavaScript中,我们不关心如何创建对象。我们通常只是假设如果物体像鸭子一样走路并像鸭子一样说话,它就是一只鸭子。 (这被称为“鸭子打字”。)结果也是如此,因为我们不能知道对象是如何创建的。

这里确实有两个问题:

  1. 如何判断对象是使用对象初始值设定项({})还是new Object

  2. 创建的
  3. 如何判断某个对象是使用其中一个还是其他构造函数创建的(如Date)。

  4. 问题1的答案是:你不能。在结果对象中没有任何区别,因此您无法分辨它是如何创建的。

    问题2的答案更复杂:

    您无法确切知道对象是使用给定的构造函数创建的。 JavaScript太强大了,让你对对象有太多的控制权,因为它可以确定。

    您可以知道对象的原型链告诉您的内容,您可以从中推断它的构造方式,但推断可能不正确。

    我们带你的

    var x = new Date();
    

    例子。要进行推理,您至少可以使用三种工具:

    1. 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 - 具体的。)

    2. 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
      
       

    3. getPrototypeOf并且相关:您可以直接检查对象的原型链(而不仅仅是通过instanceof)。但是这与instanceof具有相同的漏洞:我们可以通过使用Object.create创建对象(或使用自定义构造函数在Object.create之前使用自定义构造函数)来欺骗它。

    4. instanceof的优势在于它会检查整个层次结构,而不依赖于constructor;在使用ES5及更早版本创建的层次结构中(例如,在ES2015的class之前),人们经常无法正确设置constructor

      因此,从根本上说,我们并不关心对象是如何创建的;这也是一样,因为我们无法确切地知道它是如何被创造的。

答案 1 :(得分:2)

你无法区分普通对象的创建,因为对于javascript,这是完全相同的事情。

var o1 = {};
var o2 = new Object();