[Серия ES6] 90% интерфейсов используют ES6 для упрощения кода, вы использовали их все?

JavaScript
[Серия ES6] 90% интерфейсов используют ES6 для упрощения кода, вы использовали их все?

Предисловие (Введение в ECMAScript)

исходныйJavaScriptСуществует 2 языковых стандарта:

ECMA-262: Основной стандарт, разработанный ECMA International (Ecma International) отвечает за управление (чтобы позволить начальноеJavaScriptс начальнымJScriptразработан в соответствии с одним и тем же набором стандартовECMAScript, который выстраивается какEcmaиз262Стандартный, так что получитеECMA-262Нумерация. )

ISO/IEC 16262: Второй стандарт Международной организации по стандартизации.ISO(International Standard Organization) и Международной электротехнической комиссииIEC(International Electrotechnical Commission) отвечает за управление

По причинам авторского права на товарный знак канонический стандарт называет этот языкECMAScript, так в принципеJavaScriptиECMAScriptОтносится к одному и тому же, но иногда различается:

  • JavaScript: относится к языку и его реализации
  • ECMAScript: Относится к языковым стандартам и языковым версиям, таким как ES6 для версии 6 языка (стандартная).

История развития ECMAScript

  • ECMAScript 1 (июнь 1997 г.): первое издание спецификации.
  • ECMAScript 2 (июнь 1998 г.): введены незначительные обновления для синхронизации стандартов ISO.
  • ECMAScript 3 (декабрь 1999 г.): добавлены регулярные выражения, обработка строк, операторы управления (do-while, switch), обработка исключений (try-catch) и многие другие основные функции.
  • Ecmascript 4 (отменено в июле 2008 года): Первоначально он был крупномасштабным обновлением (статическими типами, модулями, пространствами имен и т. Д.), Но пролет был слишком большим, были различия, и он не был широко использован
  • ECMAScript 5 (декабрь 2009 г.): небольшие изменения, добавлены некоторые функции стандартной библиотеки и строгий режим.
  • ECMAScript-5.1 (июнь 2011 г.): еще одно небольшое обновление для синхронизации со стандартами ISO.
  • ECMAScript 6 (июнь 2015 г.): волна обновлений, реализация многих концепций ES4 того года и официальный переход на версии соглашения об именах по годам.
  • ECMAScript 2016 (июнь 2016 г.): первый ежегодный выпуск с более коротким циклом выпуска и меньшим количеством новых функций, чем ES6.
  • ECMAScript 2017 (июнь 2017 г.): второе ежегодное издание...

Будущие версии ECMAScript (ES2018, ES2019, ES2020 и т. д.) официально утверждены в июне.

Начало работы (сосредоточьтесь на ES6)

Цитата здесь阮一峰учительскийES6标准入门Краткое содержание книги: ES6 — это одновременно и исторический, и общий термин, означающий после версии 5.1.JavaScriptстандарты нового поколения, охватывающиеES2015、ES2016、ES2017подожди, покаES2015Это официальное название, конкретно относящееся к официальной версии языкового стандарта, выпущенной в том же году.Упоминание ES6 на рынке обычно относится кES2015стандартный, но иногда общий下一代 JavaScript

В этой статье в основном объясняется следующее:

  • Блочная область видимости (Block Scoping, ES2015)
  • Деструктуризация (Destructuring, ES2015)
  • Стрелочные функции (ES2015)
  • строка шаблона (строка шаблона, ES2015)
  • Параметры отдыха и спреда (ES2015)
  • Сокращение литерала объекта (сокращение объекта, ES2015)
  • include() для экземпляров массива (ES2016)
  • Асинхронный синтаксис Async/await (ES2017)

область действия блока

Зачем вам нужна блочная область?

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

  • В первом сценарии внутренние переменные могут переопределять внешние переменные.
var tmp = new Date()
function fn() {
  console.log(tmp)
  if (false) {
    var tmp = 'hello world'
  }
}
fn() // undefined

Исходное намерение приведенного выше кода состоит в том, что внешняя часть блока кода if использует внешнюю переменную tmp, а внутренняя часть использует внутреннюю переменную tmp. Однако функцияfnПосле выполнения результат выводаundefined, потому что продвижение переменной приводит к тому, что внутренняя переменная tmp перезаписывает внешнюю переменную tmp.

  • Во втором сценарии переменная цикла, используемая для подсчета, передается как глобальная переменная.
var s = 'hello'
for (var i = O; i < s.length; i++) {
  console.log(s[i])
}
console.log(i) // 5

В приведенном выше коде переменнаяiИспользуется только для управления циклом, но после окончания цикла не исчезает, а просачивается в глобальную переменную.

letфактическиJavaScriptДобавлена ​​область действия блока.

function fl() {
  let n = 5
  if (true) {
    let n = 10
  }
  console.log(n) // 5
}

Вышеупомянутая функция имеет два блока кода, оба объявляют переменные.n, вывод после запуска5. Это означает, что внешний кодовый блок не зависит от внутреннего кодового блока. При использованииvarОпределите переменную, и окончательное выходное значение будет10

тогда мы можем использовать块级作用域что делать?

Давайте делать тротуар вопросы

for (var i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i)
  }, 1000)
}
// 5 5 5 5 5

изменить наES6впустить

for (let i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i)
  }, 1000)
}
// 0 1 2 3 4

Увидев это, я думаю, вы поняли преимущества области видимости на уровне блоков.

ТакES5Может ли это быть реализовано块级作用域эффект? Да, мы можем использовать замыкания

for (var i = 0; i < 5; i++) {
  ;(function (index) {
    setTimeout(() => {
      console.log(index)
    }, 1000)
  })(i)
}
// 0 1 2 3 4

разрушать

Деструктуризация: это процесс разбиения структуры данных на более мелкие части. В ES6 извлекайте значения из массивов и объектов и присваивайте значения переменным.

Так в чем польза деконструкции?

  1. Операцию объявления переменных можно значительно упростить.
// ES5
var foo = 1
var bar = 2
var baz = 3

// ES6
let [foo, bar, baz] = [1, 2, 3]
  1. Variable Swap: выглядит как зеркальное отображение. Шаблон деструктурирования в левой части оператора присваивания и временно созданный литерал массива в правой части. x присваивается значение y в массиве, а y присваивается значение x в массиве.
let x = 1
let y = 2
;[x, y] = [y, x]
// x = 2, y = 1
  1. деструктуризация объекта
var obj = { x: 1, y: 2, c: 1 }
let { x, y } = obj
// x = 1
// y = 2
  1. Деструктуризация строки
const [a, b, c, d, e] = 'hello'
// a => h
// b => e
// c => l
// d => l
// e => o
  1. деструктуризация параметра функции
const xueyue = {
  name: '雪月',
  age: 18,
}

function getAge({ name, age }) {
  return `${name}今年${age}岁`
}

getAge(xueyue) // 雪月今年18岁

стрелочная функция

ES6Стрелки разрешены=>определить функцию

var f = v => v

// 等同于 ES5 的
var f = function (v) {
  return v
}

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

var f = () => 5
// 等同于 ES5 的
var f = function () {
  return 5
}

var sum = (numl, num2) => numl + num2
// 等同于 ES5 的
var sum = function (numl, num2) {
  return numl + num2
}

Стрелочные функции можно использовать в сочетании с деструктурированием.

const full = ({ first , last }) => first + ' ' + last;
// 等同于 ES5 的
function full(person) {
  return person.first + ' ' + person.last;
}

Стрелочные функции делают выражения более краткими

const isEven = n => n % 2 === 0
const square = n => n * n

var result = values.sort((a, b) => a - b)
// 等同于 ES5 的
var result = values.sort(function (a, b) {
  return a - b
})

В приведенном выше коде используются только две строки, определяющие две простые функции инструмента. Если вам не нужны стрелочные функции, вы можете занять несколько строк, и лучше написать свой глаз.

Примечания по использованию стрелочных функций

  1. внутри функцииthisОбъект — это объект, в котором он определен, а не объект, в котором он используется.
  2. нельзя использовать в качестве конструктора, то есть нельзя использоватьnewкоманду, иначе будет выдана ошибка.
  3. недоступноargumentsобъект, который не существует в теле функции. Если вы хотите использовать его, вы можете использоватьrestвместо этого параметр.
  4. недоступноyieldкоманду, поэтому функции стрелок нельзя использовать в качествеGeneratorфункция.

Из четырех пунктов, приведенных выше, особенно следует отметить первый.thisУказатель на объект изменяем, но в стрелочных функциях он фиксирован.

// ES6
function foo() {
  setTimeout(() => {
    console.log('id:', this.id)
  }, 100)
}

// 转换成ES5
function foo() {
  var _this = this

  setTimeout(function () {
    console.log('id:', _this.id)
  }, 100)
}

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

строка шаблона

Строка шаблона — это расширенная версия строки, заключенная в обратные кавычки.(``)Я БЫ . Его можно использовать как обычную строку, его также можно использовать для определения многострочных строк или для встраивания переменных в строки.

const { log } = console
const name = '雪月'
const age = 18

// 普通字符串拼接
const result = name + '今年' + age + '岁'
// 使用模板字符串
const result2 = `${name}今年${age}岁`
log(result) // 雪月今年18岁
log(result2) // 雪月今年18岁

// ${} 大括号可以放入任意的 JavaScript 表达式,可以进行运算
const result3 = `${name}今年${age * 2}岁`
log(result3) // 雪月今年36岁

Оставшиеся аргументы / расширение синтаксиса

ES6 представил остальные параметры (в форме...变量名), используется для получения дополнительных параметров функции, так что нет необходимости использоватьargumentsобъект.restПеременная совместного размещения параметров представляет собой массив, в который помещаются избыточные параметры.

function sortNumbers() {
  return Array.prototype.slice.call(arguments).sort()
}
// 使用 rest
const sortNumbers = (...numbers) => numbers.sort()

Сравнивая два вышеприведенных способа записи, можно обнаружить, что,restПараметры написаны более естественно и лаконично.

оператор спреда (spread) представляют собой три точки (...), как вrestИнверсия аргументов Преобразует массив в последовательность аргументов, разделенных запятыми.

console.log(...[1, 2, 3])
// 1 2 3

console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5

Вот оператор спреда вместоapplyПрактический пример применения методаMath.maxМетод упрощает поиск самого большого элемента в массиве.

// ESS 的写法
Math.max.apply(null, [14, 3, 77])
// ES6 的写法
Math.max(...[14, 3, 77])
// 等同于
Math.max(14, 3, 77)

Оператор распространения предоставляет новый способ объединения массивов.

//  ESS
;[1, 2].concat(more)
// ES6
;[1, 2, ...more]

Оператор распространения (...) объекта используется для извлечения всех проходимых свойств объекта параметра и их копирования в текущий объект.

let z = { a: 3, b: 'bb' }
let n = { ...z }
n // { a: 3, b: 'bb' }
n === z // false

обращать внимание: ...Расширение объекта может быть выполнено только тогда, когда свойство объекта基本数据类型является深拷贝,если引用数据类型,Это浅拷贝.

let z = { a: 3, b: 'bb', c: { name: 'ccc' } }
let n = { ...z }

n // { a: 3, b: 'bb', c: { name: 'ccc' } }
n === z // false
n.c === z.c // true
// n.c 跟 z.c 是同一个引用地址

Сокращенный синтаксис объектного литерала

const name = '雪月'

// ES5写法
const obj = {
  name: name,
  f: function () {
    console.log(this.name)
  },
}

// ES6简写
const obj2 = {
  name,
  f() {
    console.log(this.name)
  },
}

obj.f() // 雪月
obj2.f() // 雪月

использоватьvueВаши одноклассники чувствуют себя знакомыми?

new Vue({
  el: '#app',
  data() {
    return {
      list: [],
    }
  },
})

include() для экземпляров массива

Метод Array.prototype.includes возвращает логическое значение, указывающее, содержит ли массив заданное значение, аналогично методу include для строк. ES2016 представил этот метод.

;[1, 2, 3].includes(2) // true
;[1, 2, 3].includes(4) // false
;[1, 2, NaN].includes(NaN) // true

До этого метода мы обычно использовали метод indexOf массива, чтобы проверить, содержит ли он определенное значение.

// ES5
if (arr.indexOf(el) !== -1) {
  // ...
}

// ES6
if (arr.includes(el)) {
  // ...
}

// 那么 indexOf 能不能做到类似于 includes 的写法呢? 我们可以利用 ~ 位运算符
if (~arr.indexOf(el)) {
  // ...
}

indexOfУ метода есть два недостатка.Одним из них является то, что он недостаточно семантичен.Его смысл в том,чтобы найти первое вхождение значения параметра,поэтому он недостаточно интуитивен,чтобы сравнить,не равно ли оно -1. Во-вторых, он использует оператор строгого равенства (===) внутри для суждения, что приводит кNaNнеправильное объявление.

;[NaN].indexOf(NaN)
// -1

includesЕсли вы используете другой алгоритм оценки, проблем нет.

;[NaN].includes(NaN)
// true

Асинхронный/ожидающий асинхронный синтаксис

ES2017введен стандартasyncФункции, которые делают асинхронные операции более удобными.

asyncЧто такое функция? Одним словом, этоGeneratorСинтаксический сахар для функций.

async function getTitle(url) {
  let response = await fetch(url)
  let html = await response.text()
  return html.match(/<title>([\s\S]+)<\/title>/i)[1]
}

getTitle('https://tc39.github.io/ecma262/').then((res) => console.log(res))

В приведенном выше коде функцияgetTitleВнутри три операции:抓取网页,取出文本,匹配页面标题. Только после того, как все три операции будут завершены, он будет выполненthenв методеconsole.log

конец (незаконченный)

Статья знакомитES6Некоторые общие синтаксис и сценарии использования; ноES6Содержание гораздо больше, чем это, заинтересованные студенты могут перейти к阮一峰老师的 Руководство по началу работы с ES6Подробности смотрите в книге. Если вы узнали эту книгу, вы также можете купить ее по официальным каналам. Это предотвратит потерю денег издателями при публикации книг с открытым исходным кодом, тем самым поощряя больше авторов открывать свои книги с открытым исходным кодом.

Постскриптум (список API)

Есть намного большеES6ПолезныйAPIЯ кратко упомяну об этом, друзья, чтобы увидеть, полезно ли это в обычное время.

;[1, 4, -5, 10].find(n => n < 0)
// -5

;[1, 5, 10, 15].findIndex((value, index, arr) => value > 9) 
// 2

;[1, 2, [3, [4, 5]]].flat()
// [1, 2, 3, [4, 5]]

;[1, 2, [3, [4, 5]]].flat(2)
// [1, 2, 3, 4, 5]

;[3, 8, 54, 8, 3, NaN, NaN, 'NaN', 'NaN'].filter((number, index, arr) => arr.indexOf(number) === index)
// [3, 8, 54, "NaN"] 利用filter过滤去重,注意会漏掉NaN

;[1, 2, 3, 4].map((item) => item * 2)
// [2, 4, 6, 8] 利用map返回一个新数组,不改变原数组

// 使用 reduce 求和; reduce功能极其强大 ! yyds
;[0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array){
  return accumulator + currentValue;
}); 
// 10

// ES2017 引入了跟 Object.keys 配套的 Object.values 和 Object.entries,作为遍历一个对象的补充手段,
// 供 for...of 循环使用。
let { keys, values, entries } = Object;
let obj = { a: 1, b: 2, c: 3 };

for (let key of keys(obj)) {
  console.log(key); // 'a', 'b', 'c'
}

for (let value of values(obj)) {
  console.log(value); // 1, 2, 3
}

for (let [key, value] of entries(obj)) {
  console.log([key, value]); // ['a', 1], ['b', 2], ['c', 3]
}