Каждый год предложения вносятся в новейшую версию javascript (ECMA). В этом посте я продемонстрирую некоторые функции, представленные в ES2015/ES9.

Позволять

//old
var a;
//new
let b;

Классы

Термин «Синтаксический сахар» относится к новому синтаксису для выполнения ранее существовавших функций. Классы ES2015 — это пример такого синтаксиса, заменяющего предыдущий способ, которым мы использовали функции для создания классов в javascript.

//old
let Person = function (height, weight) {
   this.height = weight;
   this.weight = height;
   this.getBMI = function(){
     return this.weight/(this.height * this.height)
   }
}
let bob = new Person(10, 11)
console.log(bob.getBMI());
//new
class Person{
   constructor(height, weight){
      this.height = height;
      this.weight = weight;
   }
   getBMI(){
      return this.weight/(this.height * this.height)
   }
}

Стрелочные функции

Это новый способ создания анонимных функций с одним важным, но тонким отличием от текущего способа определения анонимных функций. В обычных анонимных функциях ключевое слово this автоматически привязывается к текущему контексту выполнения вызова функции (в данном случае объект).

this.name = "John" ;//global context

let object = {    
           name: "Mary",//local context
           sayHi: function(){      
                console.log(this === object);//Output true
                console.log(this.name);//Output Mary    
            }  
} 

object.sayHi();

Теперь стрелочные функции не привязываются автоматически к текущему контексту выполнения. Вместо этого он будет наследоваться от родительского контекста выполнения.

this.name = "John";//global context
let object = {    
           name: "Mary",//local context
           sayHi: ()=>{      
                console.log(this === object);//false
                console.log(this.name);//John
            }  
}
object.sayHi();

Это полезно, когда вы хотите определить анонимную функцию в другой функции, но вам нужно сослаться на глобальный контекст выполнения.

this.data = "Important String";

function waitAndPrintData(){
        setTimeout(()=>{
           console.log(this.data);
        }, 3000);
}

waitAndPrintData();//Output: Important String;

function waitAndPrintData2(){
    setTimeout(function(){
           console.log(this.data);
    }, 3000);
}

waitAndPrintData2();//Output: undefine

Такое поведение можно наблюдать и в классах

let classContext = undefined;
let setTimeoutContext = undefined;
class Student{
  constructor(name){
    classContext = this;
    this.name = name;
  }
  waitAndPrintName(){
    
    setTimeout(()=>{
      //doesnt introduce a new context
      setTimeoutContext = this;
      console.log(setTimeoutContext === classContext);//true
      console.log(this.name);//Prints name set in constructor
    }, 1000);
  }
  waitAndPrintName2(){
    let classContext = this;//this2
    setTimeout(function(){
      //new context created
      setTimeoutContext = this;
      console.log(setTimeoutContext === classContext);//false
      console.log(this.name);//Prints undefined
    }, 1000);
  }
}
let bob = new Student("John");
bob.waitAndPrintName();//John, this was inherited from class
bob.waitAndPrintName2();//undefined new this created in function, this.name is undefined

Оператор отдыха и распространения

Оператор расширения «…» может использоваться для параметров функций, массивов и манипулирования объектами.

Сбор параметров

Spread можно использовать для динамического сбора всех параметров, переданных функции, в виде массива. Полезно, когда вы не можете предсказать, сколько параметров пользователь может передать вашей функции.

function fun(...args){
   console.log(args);//Output: [ 1, 2, 3, 4, 5]
}
fun(1, 2, 3, 4, 5);

Параметры распространения

Обратный сбор параметров также может быть выполнен. Мы можем разбить массив на список аргументов, используя оператор распространения следующим образом:

function sum(num1, num2){
  return num1 + num2;
}

let values = [10, 30]

let ans = sum(...values);//array split into two values

Клонирование и слияние массивов

let arr1 = [1, 2, 3, {foo:"bar"}];
let arr2 = [...arr2];
arr2[4].foo = "baz";
let arr3= [...arr1, ...arr2]; 
console.log(arr3)//[1, 2, 3, {foo:"baz"}, 99, 2, 3, {foo:"baz"]

Важно отметить, что это неглубокая копия массива, поэтому изменения элементов копии не влияют на оригинал. Однако, если объект был в оригинале, на него будет ссылка в копии, поэтому изменения объекта в одном массиве появятся в другом.

Разрушение массива

Мы можем копировать элементы массива в переменные и создавать вложенные массивы с помощью операторов расширенного синтаксиса, это называется деструктурированием.

//old
let arr = [1, 2, 3, 4];
let first = arr[0];
let second = arr[1];
let rest = arr.slice(2, 4);
console.log(first, second, rest);//1, 2, [3, 4]
//new
let arr [1, 2, 3, 4];
let [first, second, ...rest] = arr;
console.log(first, second, rest)//output: 1, 2, [3, 4]

Мы также можем использовать деструктурирование для одновременного присваивания.

//old 
let a = 10, b = 11;
//new
let [a, b] = [10, 11]

Деструктуризация объекта

Мы также можем деструктурировать объекты. Если нам нужна переменная с именем, отличным от имени свойства, из которого она получает свое значение, мы указываем свойство перед переменной. Например, переменная firstname получает свое значение от object.name.

let object = {
  name:"John",
  age:10,
  weight: 110,
  height: 4
};
let {name:firstname, age, ..rest} = john;
console.log(firstname, age, rest);//Output: "John", 10, {weight:110, height:4}

Это позволяет нам деструктурировать параметры объекта такой функции. Если свойство отсутствует в объекте, мы можем указать значение по умолчанию. Например, в объекте, переданном для печати NameAndWeight, отсутствовало свойство веса, поэтому печатается значение по умолчанию 10.

function printNameAndWeight({name, weight=110}){
  console.log(name, weight);
}
let object = {
  name:"John",
  age:10,
  height: 4
};
printName(object);//Output John 110