如果我们要初始化一个数组,那么我们使用下面的几种方式
var a = Array()
var b = new Array()
var c = []
上面的三行代码都各自创建了一个length=0的JS数组。三者是如何运行的,又各自有什么区别?
- new Array()
根据new的规定,new只是一个语法糖。new Array()创建了一个对象,新建的对象a.__proto__ == Array.prototype。这是标准的一个由Class到实例的创建步骤。体现了JS在面向对象方面向主流语言的过度。 - Array()
Array()和new Array()完全一致。根据 spec,两者完全一致
When Array is called as a function rather than as a constructor, it creates and initialises a new Array object. Thus the function call Array(…) is equivalent to the object creation expression new Array(…) with the same arguments.
- []
[]也被称为literal syntax,它同样会创建一个空数组。得到的结果和new Array(),以及Array全部一样。
对于究竟应该使用new
还是使用{},[],
以及function
此类的literal syntax。网上的说法不一,具体的可以参考文章后面的链接。在自己实际使用中:
- 从性能上来讲,new Array() 在初始化大数组的时候,性能更加优异,在之前大数组创建的文章中已经提到了这个内容。当初始化一个空数组时候,两者性能几乎没有差异。因此优先使用Array()或者new Array()
- 从语言特性上讲,JS是一个基于原型继承的语言。无论是new的引入,以及在ES6中引入的Class语法糖,都是为了将JS进一步向对象化的方向进行过度。虽然使用new,会增加多一层的对象包裹,而使得内存冗余。但使用new后更加符合了对象化继承的概念。自我感觉上,使用new应该是更加好的方式。
在其他文章中,有人提到了使用new来实现对象化的一些问题,比如当使用一个function
作为基类的时候。我们可以在调用的时候,不使用new进行调用。比如下面的代码
function foo () {
var name = 'name'
}
foo.prototype.getName = function () { console.log(1) }
var t = foo()
此时t是一个undefined,而不是我们想要的继承getName方法的对象。并且此时JS解释器并不会报错。
为了解决这个问题,可以在function中添加下面的代码:
function foo()
{
// 如果用户没有使用new进行调用则静默调用new
if ( !(this instanceof foo) )
return new foo();
// constructor logic follows...
}
或者更通用的方法
if ( !(this instanceof arguments.callee) ) // 在这里不再使用foo来判定,而是通过callee来进行
throw new Error("Constructor called as a function");
其实,为了改进这个小错误,ES6进一步引入了Class
关键字。通过Class创建的对象,在调用的时候,必须使用new。Class依然是一个语法糖。
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
var t = Point() // Uncaught TypeError: Class constructor Point cannot be invoked without 'new'
参考链接:
JS秘密花园
使用new会不会有害处
为什么不要使用new
性能比较1
性能比较2
网友评论