为什么要避免在JavaScript中创建对象?

时间:2017-01-04 07:01:47

标签: javascript

我正在关注W3Schools的JavaScript教程。在几乎每页都阅读的同时,他们会向用户注意“避免创建对象"并改为使用原始数据类型。他们给出了这样的理由,因为代码变得难以理解,或者如果使用对象,执行速度将会降低"。我们应该避免在JavaScript中创建对象吗?

例如:

var value = new Number(1);  // Avoid this
var value = 1;              // do something like this instead.

2 个答案:

答案 0 :(得分:103)

JavaScript中的“避免创建对象”这一陈述在JavaScript中是荒谬的,它在任何地方都有对象,并且是现存最面向对象的语言之一。但是“避免创建基元的对象版本”,这是您引用的代码所做的,是有效的。也就是说,避免使用new Stringnew Numbernew Boolean

JavaScript包含字符串,数字和布尔值的原始版本和对象版本。几乎没有任何理由明确地创建它们中的任何一个的对象版本,这样做确实会导致混淆;见内联评论:

var s1, s2, n1, n2;

// These are false because with ===, an object is never equal to a non-object
s1 = new String("hi");
s2 = "hi";
console.log(s1 === s2); // false
n1 = new Number(42);
n2 = 42;
console.log(n1 === n2); // also false

// These are false because even with ==, two *different* objects are never equal
// (even if they're equivalent)
s1 = new String("what the...");
s2 = new String("what the...");
console.log(s1 == s2);  // also false
n1 = new Number(42);
n2 = new Number(42);
console.log(n1 == n2);  // also false

字符串,数字和布尔值的对象版本主要用于使用为对象类型提供方法的相同机制来提供基元上的方法。当你这样做

console.log("foo".toUpperCase()); // "FOO"

原语字符串"foo"创建一个临时对象,然后从该对象中读取toUpperCase属性。由于对象继承自String.prototype,因此它具有toUpperCase并且一切都很好。一旦操作完成,临时对象就会被丢弃(除非某些东西保留对它的引用,但什么都没有,toUpperCase什么也没有,你必须添加一个返回String.prototype的方法对象以便它被保留。)

答案 1 :(得分:10)

它改变了操作符对数字,字符串和布尔值的直观表达方式:

  • 严格比较(===)在构建任何数字时中断,因此42 === 42为真,而42 === new Number(42)则不是,
  • 抽象比较(==)在两个数字都是对象时中断,因此42 == new Number(42)为真,而new Number(42) == new Number(42)则不是,
  • typeof运算符在构造数字时给出不同的结果,因此typeof(42)number,但typeof(new Number(42))object
  • 转换为布尔值时,0为false,但new Number(0)为真,因此以下两种行为会有不同的行为:

var a = 0;
if (a)
  console.log("not zero");
else
  console.log("zero!");     // "zero!"

var b = new Number(0);
if (b)
  console.log("not zero");     // "not zero"
else
  console.log("zero!");

因此,请避免new Numbernew Stringnew Boolean

除此之外,还有使用/不使用new和构造函数的问题。它源于几个事实:

  • 在JS中,构造函数是一个常规函数,使用this.foo语法添加新的属性和方法;
  • 在没有new关键字的情况下调用时,this会成为全局对象,从而导致副作用。

结果,一个小小的错误可能会产生灾难性后果:

color = "blue";

var Fruit = function(color) {
  this.color = color;
  return this;
};

var apple = new Fruit("green");

console.log(apple.color);       // "green"  --  okay

console.log(color);             // "blue"  --  okay

var banana = Fruit("yellow");

console.log(banana.color);      // "yellow"  --  okay

console.log(color);             // "yellow"  --  wait, what?

console.log(banana.apple);      // "{ color: 'green' }"  --  what??

console.log(banana.document);   // "{ location: [Getter/Setter] }"  --  what???

(这就是为什么有些人会在构造函数中添加显式检查,或者使用闭包。但这是另一个故事。)