From 074785cea106179cb3305637055ab0a009ca74f2 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:42:52 -0500 Subject: initial commit --- .../reference/operators/spread_syntax/index.html | 249 +++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 files/ru/web/javascript/reference/operators/spread_syntax/index.html (limited to 'files/ru/web/javascript/reference/operators/spread_syntax/index.html') diff --git a/files/ru/web/javascript/reference/operators/spread_syntax/index.html b/files/ru/web/javascript/reference/operators/spread_syntax/index.html new file mode 100644 index 0000000000..c96be61337 --- /dev/null +++ b/files/ru/web/javascript/reference/operators/spread_syntax/index.html @@ -0,0 +1,249 @@ +--- +title: Spread syntax +slug: Web/JavaScript/Reference/Operators/Spread_syntax +translation_of: Web/JavaScript/Reference/Operators/Spread_syntax +--- +
{{jsSidebar("Operators")}}
+ +
Spread syntax позволяет расширить доступные для итерации элементы (например, массивы или строки) в местах
+ + + +
{{EmbedInteractiveExample("pages/js/expressions-spreadsyntax.html")}}
+ + + +

Синтаксис

+ +

Для вызовов функций:

+ +
myFunction(...iterableObj);
+
+ +

Для литералов массива или строк:

+ +
[...iterableObj, '4', 'five', 6];
+ +

Для литералов объекта (новое в ECMAScript 2018):

+ +
let objClone = { ...obj };
+ +

Примеры

+ +

Spread в вызовах функций

+ +

Замена apply

+ +

Обычно используют {{jsxref( "Function.prototype.apply")}} в случаях, когда хотят использовать элементы массива в качестве аргументов функции.

+ +
function myFunction(x, y, z) { }
+var args = [0, 1, 2];
+myFunction.apply(null, args);
+ +

С spread syntax вышеприведенное можно записать как:

+ +
function myFunction(x, y, z) { }
+var args = [0, 1, 2];
+myFunction(...args);
+ +

Любой аргумент в списке аргументов может использовать spread syntax, и его можно использовать несколько раз.

+ +
function myFunction(v, w, x, y, z) { }
+var args = [0, 1];
+myFunction(-1, ...args, 2, ...[3]);
+ +

Apply для new

+ +

Вызывая конструктор через ключевое слово new, невозможно использовать массив и apply напрямую (apply выполняет [[Call]], а не [[Construct]]).Однако благодаря spread syntax, массив может быть с легкостью использован со словом new:

+ +
var dateFields = [1970, 0, 1];  // 1 Jan 1970
+var d = new Date(...dateFields);
+
+ +

Чтобы использовать new с массивом параметров без spread syntax, вам потребуется использование частичного применения:

+ +
function applyAndNew(constructor, args) {
+   function partial () {
+      return constructor.apply(this, args);
+   };
+   if (typeof constructor.prototype === "object") {
+      partial.prototype = Object.create(constructor.prototype);
+   }
+   return partial;
+}
+
+
+function myConstructor () {
+   console.log("arguments.length: " + arguments.length);
+   console.log(arguments);
+   this.prop1="val1";
+   this.prop2="val2";
+};
+
+var myArguments = ["hi", "how", "are", "you", "mr", null];
+var myConstructorWithArguments = applyAndNew(myConstructor, myArguments);
+
+console.log(new myConstructorWithArguments);
+// (internal log of myConstructor):           arguments.length: 6
+// (internal log of myConstructor):           ["hi", "how", "are", "you", "mr", null]
+// (log of "new myConstructorWithArguments"): {prop1: "val1", prop2: "val2"}
+ +

Spread в литералах массива

+ +

Более мощный литерал массива

+ +

Без spread syntax, применение синтаксиса литерала массива для создания нового массива на основе существующего недостаточно и требуется императивный код вместо комбинации методов push, splice, concat и т.д. С spread syntax реализация становится гораздо более лаконичной:

+ +
var parts = ['shoulders', 'knees'];
+var lyrics = ['head', ...parts, 'and', 'toes'];
+// ["head", "shoulders", "knees", "and", "toes"]
+
+ +

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

+ +

Копирование массива

+ +
var arr = [1, 2, 3];
+var arr2 = [...arr]; // like arr.slice()
+arr2.push(4);
+
+// arr2 becomes [1, 2, 3, 4]
+// arr remains unaffected
+
+ +

Примечание: Spread syntax на самом деле переходит лишь на один уровень глубже при копировании массива. Таким образом, он может не подходить для копирования многоразмерных массивов, как показывает следующий пример: (также как и c {{jsxref("Object.assign()")}}) и синтаксис spred 

+ +
const a = [[1], [2], [3]];
+const b = [...a];
+b.shift().shift(); // 1
+// О нет. Теперь на массив "а" относятся также: а
+//[[], [2], [3]]
+
+ +

Лучший способ конкатенации массивов

+ +

Для конкатенации массива часто используется {{jsxref("Array.concat")}}:

+ +
var arr1 = [0, 1, 2];
+var arr2 = [3, 4, 5];
+// Append all items from arr2 onto arr1
+arr1 = arr1.concat(arr2);
+ +

С использованием spread syntax:

+ +
var arr1 = [0, 1, 2];
+var arr2 = [3, 4, 5];
+arr1 = [...arr1, ...arr2];
+
+ +

{{jsxref("Array.unshift")}} часто используется для вставки массива значений в начало существующего массива. Без spread syntax:

+ +
var arr1 = [0, 1, 2];
+var arr2 = [3, 4, 5];
+// Prepend all items from arr2 onto arr1
+Array.prototype.unshift.apply(arr1, arr2) // arr1 is now [3, 4, 5, 0, 1, 2]
+ +

С использованием spread syntax [Следует отметить, что такой способ создает новый массив arr1. В отличие от {{jsxref("Array.unshift")}}, исходный массив не мутируется]:

+ +
var arr1 = [0, 1, 2];
+var arr2 = [3, 4, 5];
+arr1 = [...arr2, ...arr1]; // arr1 is now [3, 4, 5, 0, 1, 2]
+
+ +

Spread в литералах объекта

+ +

Предложение Rest/Spread Properties for ECMAScript (стадия 4) добавляет свойства spread в литералы объекта. Оно копирует собственные перечисляемые свойства данного объекта в новый объект.

+ +

Поверхностное копирование (без прототипа) или объединение объектов теперь возможно с использованием более короткого, чем {{jsxref("Object.assign()")}}, синтаксиса.

+ +
var obj1 = { foo: 'bar', x: 42 };
+var obj2 = { foo: 'baz', y: 13 };
+
+var clonedObj = { ...obj1 };
+// Object { foo: "bar", x: 42 }
+
+var mergedObj = { ...obj1, ...obj2 };
+// Object { foo: "baz", x: 42, y: 13 }
+ +

Обратите внимание, что {{jsxref("Object.assign()")}} запускает setters, а spread syntax нет.

+ +

Обратите внимание, что вы не можете заменить или имитировать функцию {{jsxref("Object.assign()")}}:

+ +
var obj1 = { foo: 'bar', x: 42 };
+var obj2 = { foo: 'baz', y: 13 };
+const merge = ( ...objects ) => ( { ...objects } );
+
+var mergedObj = merge ( obj1, obj2);
+// Object { 0: { foo: 'bar', x: 42 }, 1: { foo: 'baz', y: 13 } }
+
+var mergedObj = merge ( {}, obj1, obj2);
+// Object { 0: {}, 1: { foo: 'bar', x: 42 }, 2: { foo: 'baz', y: 13 } }
+ +

В приведенном выше примере оператор распространения не работает так, как можно было бы ожидать: он распространяет массив аргументов в литерал объекта благодаря параметру rest.

+ +

Только для итерируемых объектов

+ +

Spread syntax ( кроме случаев spread properties) может быть применен только к итерируемым объектам (iterable objects) :

+ +
var obj = {'key1': 'value1'};
+var array = [...obj]; // TypeError: obj is not iterable
+
+ +

Spread с большим количеством значений

+ +

При использовании spread оператора в вызовах функций необходимо быть внимательным к возможному переполнению в ядре JavaScript. Существует ограничение по максимально возможному количеству аргументов функции. См. apply() для уточнения.

+ +

Rest синтаксис (параметры)

+ +

Синтаксис для rest оператора выглядит таким же как и для spread оператора, однако он используется для деструктуризации массивов и объектов. Фактически, rest оператор противоположен spread оператору: последний раскладывает массив на элементы, тогда как первый собирает много элементов в один. См. rest parameters.

+ +

Specifications

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('ES2015', '#sec-array-initializer')}}{{Spec2('ES2015')}}Defined in several sections of the specification: Array Initializer, Argument Lists
{{SpecName('ES2018', '#sec-object-initializer')}}{{Spec2('ES2018')}}Defined in Object Initializer
{{SpecName('ESDraft', '#sec-array-initializer')}}{{Spec2('ESDraft')}}Без изменений.
{{SpecName('ESDraft', '#sec-object-initializer')}}{{Spec2('ESDraft')}}Без изменений.
+ +

Browser compatibility

+ + + +

{{Compat("javascript.operators.spread")}}

+ +

See also

+ + -- cgit v1.2.3-54-g00ecf