在使用"new"关键字构造函数后直接调用函数?

3

在许多编程语言中,我需要将某些函数直接调用新实例封装到括号中:

 (new Date()).toString()

在JS中,new Date().toString()Date().toString()的结果是相同的。

是否可以在实例化新对象后立即使用函数调用的方式?

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


“new”不是“可选的”。当您需要它提供的行为时,它是必需的,否则就不需要。 - Pointy
你最好学习一下JS中新关键字的细微差别,以及理解面向对象范式与原型范式之间的区别。 - Chaim Friedman
1
请注意,new Date().toString()Date().toString()的结果是相同的。但是,new Date()是一个日期对象,而Date()是一个字符串。这两者的toString()方法返回相同的结果只是“巧合”。 - Freeman Lambda
2个回答

5
在许多编程语言中,为了直接在新实例上调用某些函数,我需要将其包装在括号中。是否允许以这种方式立即在实例化的新对象上使用函数调用?
我认为问题在于潜在的歧义。虽然(new Date()).toString()很清楚,但new Date().toString()在理论上可能意味着(new Date()).toString()或new (Date().toString)()。
但是这里运算符优先级来拯救了我们。
带有参数列表的new运算符的优先级高于函数调用。因此,在new Date().toString()中执行顺序就像这些数学运算必须执行的顺序一样明确(至少对引擎而言)2 + 3 * 4。
但要注意,在JS中,您也可以写new Date;而不带括号,这个操作符new(没有参数列表)的优先级低于函数调用。因此,new Date.toString()被解释为new(Date.toString)(),您会收到一个错误,指出toString()不是构造函数。

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

完全不是这样。这不是JS的特性,而是这些函数/类/构造函数实现中的怪癖。

有点像这些实现:

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构造函数具有(由规范定义)两个不同的返回值,具体取决于您将其作为函数调用还是作为构造函数调用。

所以,最终规则是 new Date().toString()=(new Date()).toString()new Date.toString()=new (Date.toString)() - ANTARA
@ANTARA 是的,这就是它被解释/解决的顺序;例如 2+3*4 被解释为 2+(3*4) 而不是 (2+3)*4。这就是所谓的运算符优先级。 - Thomas

2

EMCAScript规范

Date构造函数是%Date%内置对象,也是全局对象Date属性的初始值。当作为构造函数调用时,它会创建并初始化一个新的Date对象。当以函数形式而非构造函数形式调用Date时,它会返回一个表示当前时间(协调世界时)的字符串。

// 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

最后,您可以立即使用新创建的对象,无需将其包装在括号中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接