The Exponentiation Operator
Единствената промяна в JavaScript синтаксиса, въведен в ECMAScript 2016 е exponentiation operator (оператор за степенуване), който е математическа операция, която прилага експонента върху база. JavaScript вече има Math.pow() метод за извършване на степенуване, но JavaScript също е един от малкото езици, които изискват метод, а не формален оператор. (И някои програмисти твърдят, че оператора е по-лесен за четене и разбиране.)
Оператора за степенуване е с две звездички (**), където левият оперант е базата, а десния оперант е експонентата. Например:
-
let result = 5 ** 2; console.log(result); // 25 console.log(result === Math.pow(5, 2)); // true
Този пример изчислява 5 2, което е равно на 25. Можете да използвате Math.pow() за постигане на същия резултат.
Поръчкови операции
Оператора за степенуване има най-висок приоритет от всички бинарни оператори в JavaScript (унарните оператори имат по-висок приоритет от **). Това означава, че той се прилага първи за всяка сложна операция, както в този пример:
-
let result = 2 * 5 ** 2; console.log(result); // 50
Изчисляването на 5 2 се случва първо. Получената стойност се умножава по 2 и крайния резултат е 50.
Operand Restriction
Оператора за степенуване има малко необичайно ограничение, което не присъства в другите оператори. Лявата страна на операцията за степенуване, не може да бъде унарен израз, освен ++ или --. Например това е невалиден синтаксис:
-
// syntax error let result = -5 ** 2;
В този пример -5 е синтактична грешка, защото редът на операциите е двусмислен. Не се разбира дали - се прилага само за 5 или за резултата на израза 5 ** 2. Забраната на унарни изрази от лявата страна на оператора за степенуване елиминира тази неяснота. За да се посочи ясно намерение, трябва да се включат скоби, около -5 или около 5 ** 2, както следва:
-
// ok let result1 = -(5 ** 2); // equal to -25 // also ok let result2 = (-5) ** 2; // equal to 25
Ако поставите скобите около израза, - се прилага към цялата работа. Когато скобите заобикалят -5, става ясно, че искате да повдигнете -5 на втората степен.
Няма нужда от скоби, ако се използва ++ и -- от лявата страна на оператора за степенуване, защото двата оператора имат ясно дефинирано поведение на техните операнти. Префикс ++ или -- променя операнта преди да се извършат всички други операции и версии на postfix прилагат някакви промени едва след оценка на целия израз. Случаи на използване на двата са безопасни от лявата страна на оператора, като този код показва:
-
let num1 = 2, num2 = 2; console.log(++num1 ** 2); // 9 console.log(num1); // 3 console.log(num2-- ** 2); // 4 console.log(num2); // 1
В този пример num1 се увеличава преди оператора за степенуване да се приложи, така че num1 става 3 и резултата от операцията е 9. За num2 стойността остава 2 за операцията на степенуване и след това намалява стойността на 1.
Метода Array.prototype.includes()
Може би си спомняте, че ECMAScript 6 добави String.prototype.includes(), който проверява дали някои определени substrings съществуват в рамките на даден string. Първоначално ECMAScript 6 също искаше да въведе Array.prototype.includes() метод, за да продължи тенденцията на третиране на strings и arrays по същия начин. Но спецификацията за Array.prototype.includes() не беше пълна в крайния срок за ECMAScript 6 и така Array.prototype.includes() се озова в ECMAScript 2016.
Как да използваме Array.prototype.includes()
Методът Array.prototype.includes() приема два аргумента: стойността за търсене и незадължителен индекс, от който да започне търсенето. Когато e подаден втория аргумент, includes() започва съвпадението от този индекс. (По подразбиране началния индекс е 0.) Върнатата стойност е true, ако стойността се намира вътре в array и false ако не е. Например:
-
let values = [1, 2, 3]; console.log(values.includes(1)); // true console.log(values.includes(0)); // false // start the search from index 2 console.log(values.includes(1, 2)); // false
Тука извикването на values.includes() връща true за стойност 1 и false за стойност 0, защото 0 не е в array. Когато вторият аргумент се използва, за да започне търсенето от индекс 2 (който съдържа стойност 3), values.includes() метода връща false, защото числото 1 не е намерено между индекс 2 и края на array.
Сравняване на стойност
Сравняването на стойност, извършвано от метода includes(), използва === оператора с едно изключение: NaN се счита за равно на NaN, въпреки че NaN === NaN дава резултат false. Това е различно от поведението на метода indexOf(), който строго използва === за сравнение. За да видите разликата, помислете върху този код:
-
let values = [1, NaN, 2]; console.log(values.indexOf(NaN)); // -1 console.log(values.includes(NaN)); // true
Метода values.indexOf() връща -1 за NaN, въпреки че NaN се съдържа в array. От друга страна values.includes() връща true за NaN, защото използва различна стойност за оператора за сравнение.
Друга особеност на това изпълнение е, че 0 и - 0 се считат за равни. В този случай поведението на indexOf() и includes() е едно и също:
-
let values = [1, +0, 2]; console.log(values.indexOf(-0)); // 1 console.log(values.includes(-0)); // true
Тука, indexOf() и includes() намират 0, когато се подава - 0, защото двете стойности се считат за равни. Обърнете внимание, че това е различно от поведението на метода на Object.is(), който счита 0 и - 0 за различни стойности.
Промяна на обхвата на функцията в Strict Mode
Когато strict mode беше въведен в ECMAScript 5, езикът стана съвсем малко по-лесен, отколкото в ECMAScript 6. Въпреки това, във ECMAScript 6 все още е разрешено да укажете стриктен режим с помощта на "use strict" директивата или в глобалния обхват на действие (което ще направи целия код в strict mode) или в обхвата на функция (така само функцията ще работи в strict mode). Последното се оказа проблем в ECMAScript 6 поради по-сложния начин, по който параметрите може да се определят, по-конкретно, с преструктуриране и default стойности за параметър. За да разберем проблема, да разгледаме следния код:
-
function doSomething(first = this) { "use strict"; return first; }
Тука, към името на параметъра first се присвоява стойност по подразбиране this. Каква стойност очаквате да бъде first? Спецификацията на ECMAScript 6 инструктира JavaScript машината в такива случаи да третира параметрите, като че работят в стриктен режим, така че this трябва да бъде равен на undefined. Въпреки това, изпълнението на параметри работещи в стриктен режим, когато "use strict" присъства вътре във функцията, се оказа доста трудно, защото стойностите за параметър по подразбиране могат да бъдат и функции. Тази трудност доведе до повечето JavaScript машини да не изпълняват такива функции (така this ще бъде равен на глобалния обект).
В резултат от трудността на изпълнение ECMAScript 2016, направи незаконно да има "use strict" директива вътре във функция, чиито параметри са destructured или имат default стойности. Разрешени са само прости списъци с параметри, тези които не съдържат destructured или стойности по подразбиране, когато "use strict" присъства в тялото на функция. Ето някои примери:
-
// okay - using simple parameter list function okay(first, second) { "use strict"; return first; } // syntax error function notOkay1(first, second=first) { "use strict"; return first; } // syntax error function notOkay2({ first, second }) { "use strict"; return first; }
Все още можете да използвате "use strict" с прости списъци от параметри, поради което okay() работи, както бихте очаквали (също, както в ECMAScript 5). Функцията notOkay1() е синтактична грешка, защото вече не може да използвате "use strict" във функции с default стойности на параметрите. По същия начин notOkay2() функцията е синтактична грешка, защото не можете да използвате "use strict" във функция с destructured параметри.
Като цяло, тази промяна премахва една точка от объркване на JavaScript програмистите, както и проблемното изпълнение за JavaScript машините.