在构造函数“new”之后直接调用函数

时间:2017-04-30 22:27:31

标签: javascript internals

在许多语言中,要直接在新实例上调用某些函数,我需要将其包装成大括号:

 (new Date()).toString()

在JS new Date().toString()Date().toString()中也会给出相同的结果。

是否允许在以这种方式实例化新对象后立即使用函数调用?

看起来new关键字有时是可选的。这怎么解释JS引擎?

2 个答案:

答案 0 :(得分:3)

  

在许多语言中,要直接在新实例上调用某些函数,我需要将其包装到大括号中   是否允许在以这种方式实例化新对象后立即使用函数调用?

我认为这里的问题是潜在的模棱两可。虽然(new Date()).toString()已明确,new Date().toString()可能(理论上)表示(new Date()).toString()new (Date().toString)()

operator precedence来救援。

new (with argument list)运算符的优先级高于函数调用。因此,new Date().toString()中的执行顺序与(至少是引擎)一样清晰,因为必须执行这些数学运算的顺序2 + 3 * 4

但请注意,在JS中,您也可以在不使用括号的情况下编写new Date;,并且此运算符new (without argument list)的优先级低于函数调用。因此,new Date.toString()被解释为new (Date.toString)(),并且您会收到toString()不是构造函数的错误。

  

看起来新关键字有时是可选的。这是如何由JS引擎解释的?

完全没有。这不是JS特性,这是实现这些函数/ classes / constructors

的一个怪癖

有点像这些实现:

function Foo(){
    if(!(this instanceof Foo)) 
        return new Foo();

    this.foo = 42;
}

//or something like
function Bar(){
    return Object.create(Bar.prototype, {
        bar: { value: 42 }
    });
}

console.log(new Foo(), Foo());
console.log(new Bar(), Bar());

再次提防。由于增加了安全性/故障安全性,您无法使用新的class关键字实现类似的功能。它添加了(隐藏)代码,以确保始终使用new关键字调用这些构造函数,否则构造函数会抛出错误。

修改 例如,Array构造函数的工作方式与上面描述的相似,但看起来如Freeman Lambdas answer中指出的那样),Date构造函数具有(由规范定义)两个不同的返回值,具体取决于是否为你把它称为函数或构造函数。

答案 1 :(得分:2)

EMCAScript spec

  

Date构造函数是%Date%内在对象和初始对象   全局对象的Date属性的值。当被称为   构造函数,它创建并初始化一个新的Date对象。当日期是   作为函数而不是作为构造函数调用,它返回一个String   代表当前时间(UTC)。

// with new
const a = new Date();
console.log(typeof a); // object
console.log(a instanceof Date); // true
console.log(a.toString()); // date formatted string

// without new
const b = Date();
console.log(typeof b); // string
console.log(b instanceof Date); // false
console.log(b.toString()); // date formatted string

正如您所看到的,在语言规范中明确描述了Date的这种行为,它与 new 是可选的无关。 通过阅读这些热门问题,您可以发现很多关于 new 的信息:https://stackoverflow.com/search?q=javascript+new+keyword

最后,您可以立即使用新创建的对象。没有必要将它包装在括号中。