Яка різниця між "Array ()" та "[]" при оголошенні масиву JavaScript?


841

Яка реальна різниця між оголошенням масиву таким:

var myArray = new Array();

і

var myArray = [];

[]лексем: ARRAY_INIT; new Arrayжетони: NEW, IDENTIFIER; new Array()жетони:NEW, IDENTIFIER, CALL
noobninja

Відповіді:


951

Різниця є, але різниці в цьому прикладі немає.

Використовуючи більш багатослівний метод: new Array()чи є один додатковий параметр у параметрах: якщо ви передасте число конструктору, ви отримаєте масив такої довжини:

x = new Array(5);
alert(x.length); // 5

Щоб проілюструвати різні способи створення масиву:

var a = [],            // these are the same
    b = new Array(),   // a and b are arrays with length 0

    c = ['foo', 'bar'],           // these are the same
    d = new Array('foo', 'bar'),  // c and d are arrays with 2 strings

    // these are different:
    e = [3]             // e.length == 1, e[0] == 3
    f = new Array(3),   // f.length == 3, f[0] == undefined

;

Ще одна відмінність полягає в тому, що при використанні new Array()ви можете встановити розмір масиву, який впливає на розмір стека. Це може бути корисно, якщо ви отримуєте переповнення стека ( Performance of Array.push vs Array.unshift ). Це те, що відбувається, коли розмір масиву перевищує розмір стека, і його потрібно буде створити заново. Таким чином, насправді, залежно від випадку використання, може бути підвищення продуктивності при використанні, new Array()оскільки ви можете запобігти виникненню переповнення.

Як зазначено у цій відповіді , new Array(5)насправді undefinedдо масиву не буде додано п'ять елементів. Це просто додає місця для п’яти предметів. Майте на увазі, що використання Arrayцього способу ускладнює покладатися на array.lengthрозрахунки.


66
Це трохи неправильно. Є одна дуже важлива відмінність між новим масивом () та [], який я детально розробив у своїй відповіді.
coderjoe

30
Але як зазначається у вашій відповіді, це відрізняється лише тим, що ви повністю божевільні та перезаписуєте функцію Array ..
nickf

19
Добре важливо те, що використання нового оператора змушує інтерпретатора робити всілякі додаткові кроки, щоб перейти до глобальної сфери, шукати конструктор, викликати конструктор і призначати результат ... що в більшості випадків буде aa масив виконання. Ви можете уникнути накладних пошуків глобального конструктора, просто скориставшись []. Це може здатися невеликим, але коли ви знімаєте для роботи в реальному часі майже в реальному часі, це може змінити значення.
coderjoe

5
Є величезна різниця у виконанні: jsperf.com/create-an-array-of-initial-size/2
Marco Luglio

4
Щоправда, але вам також не потрібні крапки з комою або перервами у більшості місць, де я їх додаю. Йдеться про послідовність та розбірливість. Ви знаєте, ІМХО.
nickf

774

Різниця між створенням масиву з неявним масивом та конструктором масиву є тонкою, але важливою.

Коли ви створюєте масив, використовуючи

var a = [];

Ви говорите інтерпретатору створити новий масив виконання. Ніяка додаткова обробка взагалі не потрібна. Зроблено.

Якщо ви використовуєте:

var a = new Array();

Ви говорите інтерпретатору, я хочу зателефонувати конструктору Arrayі створити об'єкт. Потім він переглядає ваш контекст виконання, щоб знайти конструктор для виклику та викликає його, створюючи свій масив.

Ви можете подумати "Ну, це зовсім не має значення. Вони однакові!". На жаль, ви не можете цього гарантувати.

Візьмемо такий приклад:

function Array() {
    this.is = 'SPARTA';
}

var a = new Array();
var b = [];

alert(a.is);  // => 'SPARTA'
alert(b.is);  // => undefined
a.push('Woa'); // => TypeError: a.push is not a function
b.push('Woa'); // => 1 (OK)

У наведеному вище прикладі перший дзвінок попередить "SPARTA", як ви очікували. Другий не буде. Ви нарешті побачите невизначене. Ви також зауважите, що b містить всі функції нативного об’єкта Array, такі як push, де інший цього немає.

Хоча ви можете очікувати, що це станеться, це просто ілюструє той факт, що []це не те саме, що new Array().

Це, мабуть, найкраще просто використовувати, []якщо ви знаєте, що просто хочете масив. Я також не пропоную обійтись і переосмислити масив ...


157
Ну, гадаю, я знаю. Яка людина би перезаписала клас масиву, я не знаю ...
nickf

160
Ви абсолютно праві. Лише божевільний би переписав клас масиву. Тепер знайдіть хвилину і розгляньте всю додаткову роботу, використовуючи новий Array (), що змушує інтерпретатора зробити, щоб підтримати цих божевільних. Я просто уникаю цього разом із [].
coderjoe

51
Хороший приклад типу глобального забруднення, яке можливо за допомогою JavaScript.
David Snabel-Caunt

8
Варто зазначити, що новий масив (розмір) швидший, ніж інші можливі методи, використовуючи позначення []. Джерело: jsperf.com/create-an-array-of-initial-size/2
Marco Luglio

9
На жаль, тест неправильно підготовлений. Це тестування ініціалізації масиву з ініціалізацією масивів з подальшим доступом до масиву. Немає ніякого контролю, щоб довести, що браузери насправді попередньо розподіляють пам'ять (що специфікація не говорить, що вони повинні робити). Якщо ми можемо припустити, що доступ до масиву є постійним і більшість часу буде витрачено на виділення пам’яті в обох прикладах, тоді [] може бути кращим, якщо ви створюєте інстанцію мільйонів масивів. jsperf.com/array-instanciation
coderjoe

95

Є важлива відмінність, яку жодна відповідь ще не згадала.

Від цього:

new Array(2).length           // 2
new Array(2)[0] === undefined // true
new Array(2)[1] === undefined // true

Ви можете подумати, що new Array(2)це рівнозначно [undefined, undefined], але НЕ!

Давайте спробуємо map():

[undefined, undefined].map(e => 1)  // [1, 1]
new Array(2).map(e => 1)            // "(2) [undefined × 2]" in Chrome

Подивитися? Семантика абсолютно різна! То чому це?

Відповідно до ES6 Spec 22.1.1.2, завдання - Array(len)це просто створити новий масив, властивість lengthякого встановлено на аргумент, lenі це все, це означає, що всередині цього новоствореного масиву немає жодного реального елемента .

Функція map()згідно з специфікацією 22.1.3.15 спочатку перевірятиме HasPropertyпотім зворотний виклик, але виявляється, що:

new Array(2).hasOwnProperty(0) // false
[undefined, undefined].hasOwnProperty(0) // true

І тому не можна очікувати, що будь-які ітераційні функції працюють, як завжди, на масивах, створених зnew Array(len) .

BTW, Safari і Firefox мають набагато кращу "друк" для цієї ситуації:

// Safari
new Array(2)             // [](2)
new Array(2).map(e => 1) // [](2) 
[undefined, undefined]   // [undefined, undefined] (2) 

// Firefox
new Array(2)             // Array [ <2 empty slots> ]
new Array(2).map(e => 1) // Array [ <2 empty slots> ]
[undefined, undefined]   // Array [ undefined, undefined ]

Я вже надсилав проблему до Chromium і прошу їх виправити цю заплутану друк: https://bugs.chromium.org/p/chromium/isissue/detail?id=732021

ОНОВЛЕННЯ: Це вже виправлено. Зараз Chrome друкується як:

new Array(2)             // (2) [empty × 2]

22
Ваша єдина реальна відповідь
Віктор

Це має сенс, я просто наткнувся на іншу конструкцію, яку не можу знайти задокументовані посилання на: [...Array(2)]що еквівалентно [undefined, undefined]з точки зору результатів.
Роберто Андраде

Схоже, відповідь на мої попередні коментарі - "Оператор розповсюдження": javascript.info/rest-parameters-spread-operator
Роберто Андраде

@RobertoAndrade, які мають сенс, оскільки оператору розповсюдження потрібно буде прочитати записи, щоб він міг застосувати таке копіювання ... та читання такого повернення порожнього слота, undefinedяк зазвичай.
Хукс

51

Як не дивно, new Array(size)це майже в 2 рази швидше, ніж []у Chrome, і приблизно однакове у FF та IE (вимірюється створенням та заповненням масиву). Має значення лише якщо ви знаєте приблизний розмір масиву. Якщо додати більше елементів, ніж задана довжина, збільшення продуктивності втрачається.

Точніше: Array(це швидка операція постійного часу, яка не виділяє ніякої пам'яті, коли []це лінійна операція часу, яка встановлює тип і значення.


3
Я дуже тестував це в Node.js: коли вам потрібно помістити деяку кількість елементів у масив, new Array(length)на 0 <= size <= ~ 1000, за розміром> ~ 1000 перемог[]
glukki

1
перевірити це stackoverflow.com/questions/7375120 / ...
Xsmael

40

Для отримання додаткової інформації на наступній сторінці описано, чому вам ніколи не потрібно користуватисяnew Array()

Ніколи не потрібно використовувати new Object()JavaScript. Використовуйте {} замість цього об'єкт буквально . Аналогічно, не використовуйте new Array(), [] замість цього використовуйте літерал масиву . Масиви в JavaScript не мають нічого подібного до масивів на Java, а використання синтаксису, схожого на Java, вас не бентежить.

Не використовуйте new Number, new Stringабо new Boolean. Ці форми дають непотрібні обгортки об'єктів. Просто замість цього використовуйте прості літерали.

Також ознайомтеся з коментарями - new Array(length)форма не служить ніякій корисній цілі (принаймні, у сьогоднішніх реалізаціях JavaScript).


3
Крокфорд також говорить, що використовувати [], а не новий Array (). На жаль, він не каже, чому це у зв’язаній статті. Я припускаю, що це лише питання простору та швидкості. javascript.crockford.com/code.html
Nosredna

4
Crockford не є прихильником використання ключового слова "new" для створення нового примірника об'єкта в Javascript. На лекціях він заявив, що він вважає, що це створює неоднозначність і не вписується у спадок з прототипом стилю Javascript. Він спеціально має на увазі створені користувачем конструктори об'єктів, але, враховуючи це переконання, легко зрозуміти, чому він порекомендував би вам не використовувати його також із вбудованими версіями, коли є альтернативний синтаксис.
Алан Шторм

@Alan Storm: принаймні для Number, String та Boolean він каже, що "ці форми створюють непотрібні обгортки об'єктів", але я думаю, це не стосується Array.
ЛедвеFitz

10

Щоб краще зрозуміти []і new Array():

> []
  []
> new Array()
  []
> [] == []
  false
> [] === []
  false
> new Array() == new Array()
  false
> new Array() === new Array()
  false
> typeof ([])
  "object"
> typeof (new Array())
  "object"
> [] === new Array()
  false
> [] == new Array()
  false

Вищенаведений результат - з консолі Google Chrome у Windows 7.


4
але чому [] == [] або [] === [] неправдиво?
ану

5
"Вираз, що порівнює об'єкти, справедливо лише в тому випадку, якщо операнди посилаються на той самий Об'єкт." (джерело: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… )
srph

Ця відповідь вишнею підбирає приклади, щоб зрозуміти, що дві конструкції однакові. Інші публікації на цій сторінці вказують на відмінності, такі як Array(3)або new Array(3)не є такими, як [3].
ggorlen

8

Перший - це виклик конструктора об'єктів за замовчуванням. Ви можете використовувати його параметри, якщо хочете.

var array = new Array(5); //initialize with default length 5

Другий дає можливість створювати не порожній масив:

var array = [1, 2, 3]; // this array will contain numbers 1, 2, 3.

1
Те ж саме можна зробити з конструктором докладної форми: var array = new Array (1, 2, 3);
nickf

Тож я здогадуюсь, що ви можете робити var array = [5]квадратні дужки, але не використовувати конструктор, оскільки var array = Array(5)це порожній масив з 5 елементів.
cdmckay

cdmckay - це неправильно. var a = [5] буде масивом з одним елементом - числом п’ять.
ЛедвеFitz

2
@BarelyFitz: Це я сказав. У відповідь Богдана він говорить, що виклик конструктора не може використовуватися для ініціалізації масиву, але він помилявся. Мій коментар був лише для уточнення того, що ви не можете використовувати виклик конструктора для ініціалізації масиву одного елемента.
cdmckay

1
@cdmckay: Вибачте, я неправильно зрозумів ваш коментар. Для уточнення: new Array (arg) - якщо arg є числовим, це створює порожній масив довжиною = arg; новий масив (arg1, arg2) - створює новий масив та ініціалізує елементи масиву. Отже, якщо ви хочете створити масив з одним числовим елементом, як [5], ви не можете зробити це за допомогою нового масиву (5). Але насправді ніколи не слід використовувати новий Array (), тому це суперечка.
BarelyFitz

5

Я можу пояснити більш конкретний спосіб, починаючи з цього прикладу, який базується на гарному Фредріка.

var test1 = [];
test1.push("value");
test1.push("value2");

var test2 = new Array();
test2.push("value");
test2.push("value2");

alert(test1);
alert(test2);
alert(test1 == test2);
alert(test1.value == test2.value);

Я просто додав ще одне значення до масивів і зробив чотири сповіщення: Перше і друге - це дати нам значення, збережене в кожному масиві, щоб бути впевненим у значеннях. Вони повернуть те саме! Тепер спробуйте третій, він повертає помилкове, це тому

JS трактує test1 як ВАРІАБЛЮЮЮЧИЙ тип масиву даних , і він трактує test2 як ОБ'ЄКТ з функціональністю масиву , і тут є кілька незначних відмінностей.

Перша відмінність полягає в тому, що, коли ми викликаємо test1, вона викликає змінну, не замислюючись, вона просто повертає значення, які зберігаються в цій змінній, не зважаючи на її тип даних! Але, коли ми викликаємо test2, він викликає функцію Array (), а потім він зберігає наші "Pushed" значення у його властивості "Value" , і те ж саме відбувається, коли ми попереджаємо test2, він повертає властивість "Value" об'єкта масиву.

Отже, коли ми перевіряємо, чи є test1 рівним test2, звичайно, вони ніколи не повернуть істину, одна - це функція, а інша - змінна (з типом масиву), навіть якщо вони мають однакове значення!

Щоб переконатися в цьому, спробуйте четверте сповіщення, додавши до нього значення .value; воно повернеться правдою. У цьому випадку ми кажемо JS "Не зважаючи на тип контейнера, будь то функціональний чи змінний, будь ласка, порівняйте значення, які зберігаються в кожному контейнері, і скажіть нам, що ви бачили!" саме так і відбувається.

Я сподіваюся, що сказала ідею за цим чітко, і вибачте за свою погану англійську мову.


19
Дивовижно, що проголосовані такі повні та цілісні дурниці. Порівняння між масивами буде помилковим незалежно від того, як ви їх створюєте, оскільки воно порівнює ідентичність об'єкта, і вони є різними об'єктами. Масиви не мають властивості значення. []і new Array()тотожна; .valueбуде undefinedв обох випадках, і порівнювати їх завжди буде помилковим.
slikts

Погоджена, ця відповідь не має сенсу і нічого не показує. Немає такого array.value. і те, typeof []і typeof new Array()повернення object. Це одна з причин виникнення функції під назвоюArray.isArray
gman

4

Немає різниці, коли ви ініціалізуєте масив без будь-якої довжини. Так var a = []і те var b = new Array()саме.

Але якщо ви ініціалізуєте масив з довжиною на зразок var b = new Array(1);, він встановить довжину об’єкта масиву на 1. Отже, його еквівалент var b = []; b.length=1;.

Це буде проблематично, коли ви робите array_object.push, він додає елемент після останнього елемента та збільшує довжину.

var b = new Array(1);
b.push("hello world");
console.log(b.length); // print 2

проти

var v = [];
a.push("hello world");
console.log(b.length); // print 1

3

Перший - це конструктор об'єктів за замовчуванням call.mostly використовується для динамічних значень.

var array = new Array(length); //initialize with default length

другий масив використовується при створенні статичних значень

var array = [red, green, blue, yellow, white]; // this array will contain values.

3

Немає великої різниці, вони в основному роблять те саме, але роблять їх по-різному, але читайте далі, дивіться на це твердження на W3C:

var cars = ["Saab", "Volvo","BMW"];

і

var cars = new Array("Saab", "Volvo", "BMW");

Два вищевказані приклади роблять точно так само. Не потрібно використовувати новий масив ().
Для простоти, читабельності та швидкості виконання використовуйте перший (метод прямого масиву).

Але в той же час створення нового масиву за допомогою new Arrayсинтаксису вважається поганою практикою:

Уникайте нового масиву ()

Немає необхідності використовувати вбудований конструктор масиву JavaScript новий Array ().
Використовуйте замість [].
Ці два різних оператора створюють новий порожній масив з назвою точок:

var points = new Array();         // Bad
var points = [];                  // Good 

Ці два різних оператора створюють новий масив, що містить 6 чисел:

var points = new Array(40, 100, 1, 5, 25, 10); // Bad    
var points = [40, 100, 1, 5, 25, 10];          // Good

Нове ключове слово тільки ускладнює код. Це також може призвести до несподіваних результатів:

var points = new Array(40, 100);  // Creates an array with two elements (40 and 100)

Що робити, якщо я видалю один з елементів?

var points = new Array(40);       // Creates an array with 40 undefined elements !!!!!

Так що в основному не вважається найкращою практикою, і там є одна незначна різниця, ви можете пропустити довжину, new Array(length)як це, що також не рекомендується.


Привіт Алірезе, це скопійовані та вставлені звідкись? Будь ласка, додайте посилання на сторінку, з якої скопійовано текст. Детальну інформацію див. На цій сторінці довідкового центру . Дякую.
Панг

Корисно дляnew Array(40).fill(123)
gman

2

Різниця використання

var arr = new Array(size);

Або

arr = [];
arr.length = size;

Як було досить обговорено в цьому питанні.

Я хотів би додати питання швидкості - поточний найшвидший спосіб, на google chrome- це другий.

Але зверніть увагу, ці речі, як правило, сильно змінюються з оновленнями. Також час роботи буде відрізнятися між різними браузерами.

Наприклад, другий варіант, про який я згадав, працює на рівні 2 мільйони [оп / секунду] chrome, але якби ви спробували його, mozilla dev.ви отримаєте напрочуд більший показник у 23 мільйони.

У будь-якому разі, я б пропонував вам перевіряти це раз у раз у різних браузерах (і на машинах), використовуючи сайт як такий


2

Як я знаю різницю і можна знайти шматочок (або інші Funcitons масиву) як code1 й Кодекса2 показати U масив і його екземпляри :

код1:

[].slice; // find slice here
var arr = new Array();
arr.slice // find slice here
Array.prototype.slice // find slice here

code2:

[].__proto__ == Array.prototype; // true
var arr = new Array();
arr.__proto__ == Array.prototype; // true

висновок:

як ви можете бачити []і new Array()створювати новий екземпляр Array. І всі вони отримують функції прототипуArray.prototype

Вони є лише різними примірниками Array.so цим пояснюють, чому [] != []

:)


2

Я зазнав дивної поведінки, використовуючи [].

У нас є "Класи" моделей з полями, ініціалізованими на деяке значення. Наприклад:

require([
  "dojo/_base/declare",
  "dijit/_WidgetBase",
], function(declare, parser, ready, _WidgetBase){

   declare("MyWidget", [_WidgetBase], {
     field1: [],
     field2: "",
     function1: function(),
     function2: function()
   });    
});

Я виявив, що коли поля ініціалізуються з []тоді, вони поділяться всіма об'єктами Model. Внесення змін до одного впливає на всіх інших.

Це не відбувається, ініціалізуючи їх new Array(). Те саме для ініціалізації об'єктів ( {}проти нових Object())

TBH Я не впевнений, чи це проблема з рамкою, яку ми використовували ( Dojo )


2

Тут є більше, ніж очі. Більшість інших відповідей правильні, Але ТАКОЖ ..

new Array(n)

  • Дозволяє двигуну перерозподіляти місце для nелементів
  • Оптимізовано для створення масиву
  • Створений масив позначений рідкісним, який має найменш виконані операції з масивом, це тому, що кожен індексний доступ повинен перевіряти межі, бачити, чи існує значення, і ходити по прототипу ланцюга
  • Якщо масив позначений рідкісним, немає шляху назад (принаймні, у V8), він завжди буде повільнішим протягом його життя, навіть якщо ви заповнюєте його вмістом (запакований масив) через 1 мс або 2 години пізніше, не має значення

[1, 2, 3] || []

  • Створений масив позначений упакованим (якщо ви не використовуєте deleteабо [1,,3]синтаксис)
  • Оптимізований для масиву операцій ( for .., forEach, mapі т.д.)
  • Двигун повинен перерозподілити простір у міру зростання масиву

Це , ймовірно , це не так для старих браузерів версій / браузерів.


-2

Я знайшов одну різницю між двома конструкціями, які мене дуже важко вкусили.

Скажімо, у мене є:

function MyClass(){
  this.property1=[];
  this.property2=new Array();
};
var MyObject1=new MyClass();
var MyObject2=new MyClass();

У реальному житті, якщо я це роблю:

MyObject1.property1.push('a');
MyObject1.property2.push('b');
MyObject2.property1.push('c');
MyObject2.property2.push('d');

Я закінчую це:

MyObject1.property1=['a','c']
MyObject1.property2=['b']
MyObject2.property1=['a','c']
MyObject2.property2=['d']

Я не знаю, що мовна специфікація говорить, що має відбутися, але якщо я хочу, щоб у моїх об’єктів були унікальні масиви властивостей, я повинен використовувати new Array().


Цей JSFiddle показує, що висновок - це те, що ви очікували з літералом масиву []та new Array()конструктором, що призведе до одного елемента на масив на властивість. У вашому коді повинно бути щось інше, щоб отримати результат, показаний вище.
gfullam

Баккі, це не трапляється для мене в жодному браузері. Щоб отримати таку поведінку, вам доведеться зробити щось на кшталт цього: var property1static=[]; function MyClass(){ this.property1=property1static; this.property2=new Array(); };
Дейв Бертон

-3

Використання конструктора Array створює новий масив потрібної довжини і заповнює кожен з індексів невизначеним, присвоєний масив змінному створює індекси, для яких ви даєте йому інформацію.


1
Ні, масив НЕ заповнений, всередині немає індексу / клавіш. Наприклад. .Each не працював.
CFrei
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.