在另一个问题中,一个用户指出使用new关键字是危险的,并提出了一个不使用new的对象创建解决方案。我不相信这是真的,主要是因为我使用过Prototype、Script.aculo.us和其他优秀的JavaScript库,它们都使用new关键字。

尽管如此,昨天我在YUI剧院看了Douglas Crockford的演讲,他说了完全相同的事情,他不再在他的代码中使用new关键字(Crockford谈JavaScript -第三幕:函数终极- 50:23分钟)。

使用new关键字“不好”吗?使用它的优点和缺点是什么?


当前回答

JavaScript是一种动态语言,有无数种方法可以把其他语言阻止你的事情搞砸。

避免使用像new这样的基本语言特性,因为你可能会搞砸,这有点像在穿过雷区之前脱掉你闪闪发光的新鞋,以防你的鞋被弄脏。

我使用了一种约定,函数名以小写字母开头,而实际上是类定义的“函数”以大写字母开头。结果是一个非常引人注目的视觉线索,“语法”是错误的:

var o = MyClass();  // This is clearly wrong.

最重要的是,良好的命名习惯会有所帮助。毕竟,函数是做事情的,因此它的名字中应该有一个动词,而类代表对象,是没有任何动词的名词和形容词。

var o = chair() // Executing chair is daft.
var o = createChair() // Makes sense.

Stack Overflow的语法着色是如何解释上面的代码的,这很有趣。

其他回答

在我看来,在2021年的JavaScript中,“新”是一个有缺陷的概念。它在不需要的地方添加单词。它使函数/构造函数的返回值为隐式,并强制在函数/构造函数中使用此返回值。在代码中添加噪声从来都不是一件好事。

// With new
function Point(x, y) {
    this.x = x
    this.y = y
}
let point = new Point(0, 0)

Vs.

// Without new
function Point(x, y) {
    return { x, y }
}
let point = Point(0, 0)

我同意PEZ和一些人的观点。

在我看来,“新”显然是自我描述的对象创建,而Greg Dean所描述的YUI模式完全被模糊了。

有人可能会写var bar = foo;或者var bar = baz();在baz不是对象的地方,创建方法似乎要危险得多。

我写了一篇关于如何缓解不使用new关键字调用构造函数的问题的文章。

它主要是说教性的,但它展示了如何创建使用或不使用new的构造函数,并且不需要在每个构造函数中添加样板代码来测试它。

不使用new的构造函数

以下是该技巧的要点:

/**
 * Wraps the passed in constructor so it works with
 * or without the new keyword
 * @param {Function} realCtor The constructor function.
 *    Note that this is going to be wrapped
 *    and should not be used directly
 */
function ctor(realCtor) {
  // This is going to be the actual constructor
  return function wrapperCtor() {
    var obj; // The object that will be created
    if (this instanceof wrapperCtor) {
      // Called with new
      obj = this;
    } else {
      // Called without new. Create an empty object of the
      // correct type without running that constructor
      surrogateCtor.prototype = wrapperCtor.prototype;
      obj = new surrogateCtor();
    }
    // Call the real constructor function
    realCtor.apply(obj, arguments);
    return obj;
  }

  function surrogateCtor() {}
}

下面是如何使用它:

// Create our point constructor
Point = ctor(function(x, y) {
  this.x = x;
  this.y = y;
});

// This is good
var pt = new Point(20, 30);
// This is OK also
var pt2 = Point(20, 30);

另一个新案例是我所说的Pooh Coding。我建议你顺应你所使用的语言,而不是反对它。

这种语言的维护者很有可能会根据他们鼓励使用的习语来优化语言。如果他们在语言中添加了一个新的关键字,他们可能认为在创建新实例时保持清晰是有意义的。

按照语言的意图编写的代码将在每个版本中提高效率。而避免语言关键结构的代码将随着时间的推移而遭受损失。

这远远超出了性能。我数不清我听过(或说过)多少次“他们为什么要这么做?”事实经常证明,在编写代码的时候,有一些“好的”理由。遵循语言之道是你的代码将来不会被嘲笑的最好保证。

情况1:new不是必需的,应该避免使用

var str = new String('asd');  // type: object
var str = String('asd');      // type: string

var num = new Number(12);     // type: object
var num = Number(12);         // type: number

情况2:new是必需的,否则您将得到一个错误

new Date().getFullYear();     // correct, returns the current year, i.e. 2010
Date().getFullYear();         // invalid, returns an error