Вы знаете все эти синтаксисы ES6 (часть 1)?

внешний интерфейс JavaScript

предисловие

ES6 существует уже более 6 лет.Я считаю, что общая грамматика ES6 у всех очень хорошая.Планирую обобщить все грамматики ES6, что мне удобно для более гибкого использования и закрепления знаний. Надеюсь, это поможет вам!

let

представлять

letОператор объявляет локальную переменную блочной области и при необходимости инициализирует ее значением. Как объявляется новая переменная.

Он имеет следующие характеристики

Дублирование деклараций не допускается.

Var можно объявлять повторно (последнее объявление перезапишет предыдущее объявление), а let нельзя (будет сообщено об ошибке), что позволяет избежать повторного именования.

var a = 1;
var a = 2;
console.log(a); // 2
let a = 1;
let a = 2;
console.log(a); // Uncaught SyntaxError: Identifier 'a' has already been declared

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

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

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

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

В первом сценарии внутренние переменные могут переопределять внешние переменные.

var tmp = new Date();

function f() {
  console.log(tmp);
  if (false) {
    var tmp = 'hello world'; // 这里会有变量提升
  }
}
f(); // undefined

ifВнешняя часть блока кода использует внешнийtmpпеременная, используемая внутриtmpПеременная.但是,函数fПосле выполнения результат выводаundefined, причина в том, что переменная продвигается, в результате чего внутреннийtmpПеременная переопределяет внешнийtmpПеременная.

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

var s = 'hello';
for (var i = 0; i < s.length; i++) {
  console.log(s[i]);
}
// for循环外面打印
console.log(i); // 5

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

область блока в es6

{
  let a = 10;
  var b = 1;
}
console.log(b); // 1
console.log(a); // Uncaught ReferenceError: a is not defined

letна самом деле добавляет область действия на уровне блоков в JavaScript,letОбъявленная переменная действительна только в том блоке кода, где она находится, и внешний уровень не может получить переменную, объявленную с помощью let. {} в приведенном выше коде является областью действия на уровне блоков.

ES6 допускает произвольное вложение блочных областей.

{{{{
  {let insane = 'Hello World'}
  console.log(insane); // 报错
}}}};

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

Внутренние области могут определять переменные с тем же именем во внешних областях.

{{{{
  let insane = 'Hello World';
  {let insane = 'Hello World'}
}}}};

forЦиклический счетчик подходит для использованияletЗаказ.

for (let i = 0; i < 10; i++) {
  // ...
}
console.log(i); // ReferenceError: i is not defined

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

Измените его на объявление var

for (var i = 0; i < 3; i++) {
  console.log(i); //输出0 1 2
}
console.log(i); //只会输出3

Для более подробного ознакомления с областью применения циклов for обратитесь к этой статье.статья

Временная мертвая зона

var a = 1
{ 
 a = 6 
 let a  // Uncaught ReferenceError: Cannot access 'a' before initialization
}

Внутри блока кода используйтеletПеременная недоступна, пока команда не объявит ее. Это синтаксически называется暂时性死区ES6 определяет временную мертвую зону, в основном для уменьшения ошибок времени выполнения, предотвращая использование переменной до ее объявления, что приводит к неожиданному поведению. Подобные ошибки распространены в ES5, и с этим условием их легко избежать.

переменное продвижение

Что касается того, существует ли переменное продвижение, то в настоящее время оно не является единообразным. Руань ИфэнНачало работы с ECMAScript 6Он четко указан в главе «Пусть и Const» в不存在变量提升. Но в моем понимании все еще есть переменное улучшение. Вот пример для иллюстрации:

 var a = 1;
  (function () {
    console.log(a); // 1
  })();

Сделаем простое преобразование

 var a = 1;
  (function () {
    console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization
    let a = 2
  })();

Отсюда видно, что пусть также существует变量提升Да, но переменная не может быть прочитана или записана до того, как переменная будет назначена, иначе будет сообщено об ошибке, что暂时性死区.

Переменные не монтируются в окно

На мой взгляд, монтировать переменные, объявленные с помощью var, в окно - очень плохой дизайн, что может легко привести к загрязнению переменных и злоупотреблению глобальными переменными. Поэтому новый метод объявления больше не монтирует объявленные переменные в окно.

// var声明的变量会挂载到window上
var a = 1;
window.a // 1

// let声明的变量不会挂载到window
let b = 1;
window.b // undefined

Свойства объектов верхнего уровня связаны с глобальными переменными, что считается одним из самых больших недостатков дизайна языка JavaScript. Такой дизайн приносит несколько больших проблем.Во-первых, невозможно сообщить об ошибке необъявленной переменной во время компиляции.О ней может знать только среда выполнения (поскольку глобальные переменные могут быть созданы свойствами объекта верхнего уровня, а свойства свойств Создание динамическое); во-вторых, программистам легко создавать глобальные переменные по незнанию (например, опечатки); наконец, свойства объектов верхнего уровня можно читать и записывать везде, что очень неблагоприятно для модульного программирования . с другой стороны,windowОбъект имеет значение сущности, которое относится к объекту окна браузера, а объект верхнего уровня — это объект со значением сущности, что также неуместно.

Начиная с ES6, глобальные переменные будут постепенно отделяться от свойств объекта верхнего уровня.

const

constОбъявите константу только для чтения. После объявления значение константы не может быть изменено.Другие функции такие же, как и у let.

const a = 1;
a = 3; // TypeError: Assignment to constant variable.

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

const a;
// SyntaxError: Missing initializer in const declaration

constНа самом деле гарантируется не то, что значение переменной не может быть изменено, а то, что данные, хранящиеся в адресе памяти, на который указывает переменная, не могут быть изменены. Для простых типов данных (числа, строки, логические значения) значение сохраняется по адресу памяти, на который указывает переменная, поэтому оно эквивалентно константе. Но для данных составного типа (в основном объекты и массивы) адрес памяти, на который указывает переменная, является только указателем на фактические данные,constГарантировать можно только то, что этот указатель фиксирован (то есть всегда указывает на другой фиксированный адрес), а то, что структура данных, на которую он указывает, является переменной, совершенно не поддается контролю. Следовательно, объявление объекта константой должно выполняться с большой осторожностью.

const a = {};
// 为 a 添加一个属性,可以成功
a.prop = 123;
// 将 a 指向另一个对象,就会报错
a = {}; // TypeError: "a" is read-only

Суммировать

Для использования вар:

  • Нам нужно понимать тот факт, что особенности var: такие как расширение области действия, глобальный объект окна, отсутствие области действия на уровне блоков и т. д. — это некоторые исторические проблемы; это своего рода JavaScript в начале проектирования.语言缺陷

  • Конечно, мы также воспользовались этим недостатком, чтобы создать серию вопросов для интервью, чтобы проверить понимание каждым самого языка JavaScript и лежащих в его основе слоев.

  • Но на практике мы можем использовать последнюю спецификацию для записи, то есть больше не использовать var для определения переменных

Для let и const:

  • Для let и const в настоящее время он находится в стадии разработки.推荐使用из

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

  • Используйте let только тогда, когда мы точно знаем, что переменная должна быть переназначена позже.

В любом случае, просто слово, больше не используйте var в будущем!

присваивание деструктуризации

ES6 позволяет извлекать значения из массивов и объектов и присваивать значения переменным по определенному шаблону, который называется деструктурированием

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

以前的取值方式

const obj = { a:1, b:2, c:3 }
const a = obj.a; 
const b = obj.b; 
const c = obj.c; 

现在的取值方式

const obj = { a:1, b:2, c:3 }
const {a,b,c} = obj;

修改解构出来的名称

const obj = { a:1, b:2, c:3 }
const {a:a1, b:b1, c} = obj;
console.log(a1)  // 1
console.log(b1)  // 2
console.log(c)   // 3

给默认值

const obj = { a:1, b:2, c:3 }
const {d = 5} = obj;
const {e:e1 = 6} = obj;
console.log(d)  // 5
console.log(e1)  // 6

深层对象的解构

  const metadata = {
    title: "english-title",
    translations: [
      {
        title: "我是深处的title",
      },
    ],
    friend: {
      girlFriend: {
        name: {
          firstName: "chimmy",
        },
      },
    },
  };

  let {
    title: englishTitle, // rename
    translations: [
      {
        title: localeTitle, // rename
      },
    ],
    friend: {
      girlFriend: {
        name: { firstName },
      },
    },
  } = metadata;

  console.log(englishTitle); // "english-title"
  console.log(localeTitle); // "我是深处的title"
  console.log(firstName); // "chimmy"

Деструктуризация массива

// 以前获取数组里面值得方式
var names = ["abc", "cba", "nba"]
// var item1 = names[0]
// var item2 = names[1]
// var item3 = names[2]

// 对数组的解构: []
let [item1, item2, item3] = names
console.log(item1, item2, item3) // abc cba nba

// 解构后面的元素
let [, , itemz] = names
console.log(itemz) // nba

// 解构出一个元素,后面的元素放到一个新数组中
let [itemx, ...newNames] = names
console.log(itemx, newNames) // abc ['cba', 'nba']

// 解构的默认值
let [itema, itemb, itemc, itemd = "aaa"] = names
console.log(itemd) // aaa

// 通过解构交换变量
let a = 1;
let b = 3;
[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1

деструктуризация параметра функции

Параметры функции также можно назначать с помощью деструктуризации.

function add([x, y]){
  return x + y;
}
add([1, 2]); // 3

Деструктуризация параметров функции также может использовать значения по умолчанию.

function move({x = 0, y = 0} = {}) {
  return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]

Улучшения литерала объекта и имена вычисляемых свойств

let name = "jimmy"
let age = 18
// 属性的简写
let obj = {
 name,
 age
}
// 等同于
let obj = {
 name:name,
 age:age
}

// 方法的简写
let obj2 = {
  bar() {
    console.log(this)
  },
}
//   等同于
let obj2 = {
  bar:function() {
    console.log(this)
  }
}

// 计算属性名(对象的键可以是变量)
let obj3 = {}
obj3[name] = "chimmy";
console.log(obj3.jimmy); // chimmy

Развернуть синтаксис ( ... )

Синтаксис распространения,Выражения массива или строки могут быть расширены синтаксически во время вызова функции/конструкции массива; выражения объекта также могут быть расширены ключом-значением при создании литеральных объектов. (буквально обычно относится к[1, 2, 3] или {name: "mdn"}Эта лаконичная конструкция)

Пример

const names = ["abc", "cba", "nba"]
const info = {name: "why", age: 18}

// 1.函数调用时
function foo(x, y, z) {
  console.log(x, y, z)  // abc cba nba
}
foo(...names)

// 2.构造数组时
const newNames = [...names]
console.log(newNames) // ['abc', 'cba', 'nba']
console.log(...[1, 2, 3]) // 1 2 3

// 3.构建对象字面量时ES2018(ES9)
const obj = { ...info, address: "成都市", ...names }
console.log(obj) // {0: 'abc', 1: 'cba', 2: 'nba', name: 'why', age: 18, address: '成都市'}

Скопируйте массив (неглубокая копия)

Массивы являются составными типами данных.Если вы копируете напрямую, вы просто копируете указатель на базовую структуру данных, а не клонируете новый массив.

const a1 = [1, 2];
const a2 = a1;
a2[0] = 2;
console.log(a1) // [2, 2]
const a1 = [1, 2];
const a2 = [...a1];
a2[0] = 2;
console.log(a1) // [1, 2]

Объединить массивы

const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];

// ES5 的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]

// ES6 的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]

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

Звуковые строки и другие идентификаторы до ES6

const name = "jimmy";
const age = 18;
const height = 1.88;
console.log("my name is " + name + ", age is " + age + ", height is " + height)

Строки шаблона, предоставляемые ES6

const age = 18;
const height = 1.88;

// 支持变量
const message = `my name is ${name}, age is ${age}, height is ${height}`;
console.log(message); // my name is , age is 18, height is 1.88

// 支持表达式
const info = `age double is ${age * 2}`;
console.log(info); // age double is 36

// 支持函数调用
function doubleAge() {
  return age * 2;
}
const info2 = `double age is ${doubleAge()}`;
console.log(info2); // double age is 36

расширение объекта

object.is()

грамматика

Object.is(value1, value2);

Первое значение для сравнения.value1

Второе сравниваемое значение.value2

представлять

ES5 сравнивает два значения на равенство всего двумя операторами: оператор равенства (==) и оператор строгого равенства (===). Оба они имеют недостатки, первый автоматически преобразует тип данных, второйNaNне равный себе и+0равный-0. В JavaScript отсутствует операция, при которой во всех контекстах, пока два значения совпадают, они должны быть равны.

ES6 предлагает алгоритм «равенства одинаковых значений» для решения этой проблемы.Object.isЭто новый способ развертывания этого алгоритма. Он используется для сравнения того, являются ли два значения строго равными, и имеет в основном то же поведение, что и оператор строгого сравнения (===).

Object.is('foo', 'foo')
// true
Object.is({}, {})
// false

Отличий всего два: одно+0не равно-0, дваNaNравно самому себе.

console.log(NaN === NaN); // false
console.log(0 === -0);     // true

Object.is(NaN, NaN) // true
Object.is(+0, -0) // false

Object.assign()

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

// 目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };

const returnedTarget = Object.assign(target, source);

console.log(target); // { a: 1, b: 4, c: 5 } 注意目标对象自身也会改变
console.log(returnedTarget); { a: 1, b: 4, c: 5 }
// Object.assign()的返回值其实就是目标对象
target === returnedTarget // true

грамматика

Object.assign(target, ...sources)
  • targetцель.
  • sourcesисходный объект. Нет ограничений на количество

Возвращаемое значение目标对象

Если есть только один параметр,Object.assign()Этот параметр будет возвращен напрямую.

const obj = {a: 1};
Object.assign(obj) === obj // true

Если параметр не является объектом, он сначала будет преобразован в объект, а затем возвращен.

typeof Object.assign(2) // "object"

из-заundefinedа такжеnullНе могут быть преобразованы в объекты, поэтому, если они используются в качестве параметров, будет сообщено об ошибке.

Object.assign(undefined) // 报错
Object.assign(null) // 报错

// 如果`undefined`和`null`不在首参数,就不会报错。
let obj = {a: 1};
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj // true

общего пользования

(1) Добавить атрибуты к объектам

class Point {
  constructor(x, y) {
    Object.assign(this, {x, y});
  }
}

Вышеупомянутый метод проходитObject.assign()метод, будетxсвойства иyатрибут добавлен кPointЭкземпляр объекта класса.

(2) Добавить методы к объектам

Object.assign(SomeClass.prototype, {
  someMethod(arg1, arg2) {
    ···
  },
  anotherMethod() {
    ···
  }
});

// 等同于下面的写法
SomeClass.prototype.someMethod = function (arg1, arg2) {
  ···
};
SomeClass.prototype.anotherMethod = function () {
  ···
};

Приведенный выше код использует краткое представление атрибута объекта, непосредственно вкладывая две функции в брекетах, а затем использоватьassign()метод добавлен вSomeClass.prototypeсреди.

(3) Клонировать объект

function clone(origin) {
  return Object.assign({}, origin);
}

Обратите внимание, что этот метод является поверхностной копией. Для подробного понимания см.Что вы знаете о глубоком и поверхностном копировании js?

(4) Объединить несколько объектов

Объединение нескольких объектов в один объект.

const merge = (target, ...sources) => Object.assign(target, ...sources);

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

const merge = (...sources) => Object.assign({}, ...sources);

(5) Укажите значения по умолчанию для свойств

const DEFAULTS = {
  logLevel: 0,
  outputFormat: 'html'
};

function processContent(options) {
  options = Object.assign({}, DEFAULTS, options);
  console.log(options);
  // ...
}

В приведенном выше кодеDEFAULTSобъект является значением по умолчанию,optionsОбъекты — это параметры, вводимые пользователем.Object.assign()метод будетDEFAULTSа такжеoptionsобъединиться в новый объект, если оба имеют свойства с одинаковым именем, тоoptionsЗначение свойства будет переопределятьDEFAULTSстоимость имущества.

Как перемещаться по объектам (расширенный)

Как обойти значение каждого ключа и значения в объекте?

let obj = {
  name: "jimmy",
  age: 18,
  like: "girl",
};

В основном следующими способами

// for...in的作用是用于遍历对象的。
for (let key in obj) {
  console.log(key, obj[key]);
}

// Object.keys()用于返回对象所有key组成的数组。
Object.keys(obj).forEach((key) => {
  console.log(key, obj[key]);
});

// Object.getOwnPropertyNames()用于返回对象所有key组成的数组。
Object.getOwnPropertyNames(obj).forEach((key) => {
  console.log(key, obj[key]);
});

// Reflect.ownKeys()用于返回对象所有key组成的数组。

Reflect.ownKeys(obj).forEach((key) => {
  console.log(key, obj[key]);
});

// 打印的都是
// name jimmy
// age 18
// like girl

расширение функции

значение функции по умолчанию

До ES6 нельзя было напрямую указать значения по умолчанию для параметров функции, использовались только обходные пути.

function log(x, y) {
 if (typeof y === 'undefined' || typeof y === 'null') {
   y = 'World';
 }
  console.log(x, y);
}

log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello World

Это очень некрасиво писать, когда функция имеет много параметров, участвующих в инициализации. ES6 позволяет устанавливать значения по умолчанию для параметров функции, что пишется сразу после определения параметра.

function log(x, y = 'World') {
  console.log(x, y);
}

log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello

У метода написания ES6 есть еще два преимущества: во-первых, люди, читающие код, могут сразу понять, какие параметры можно опустить, не заглядывая в тело функции или документацию; во-вторых, это способствует будущей оптимизации кода, даже если будущая версия находится в разработке. внешний интерфейс, полное удаление этого параметра не приведет к сбою выполнения предыдущего кода.

остаточный параметр

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

function add(...values) {
  let sum = 0;

  for (var val of values) {
    sum += val;
  }

  return sum;
}

add(2, 5, 3) // 10

код вышеaddФункция является функцией суммирования, и с помощью параметра rest в функцию можно передать любое количество параметров.

Вот параметр rest вместо этогоargumentsПримеры переменных.

// arguments变量的写法
function sortNumbers() {
  return Array.from(arguments).sort();
}

// rest参数的写法
const sortNumbers = (...numbers) => numbers.sort();

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

Обратите внимание, что параметр покоя больше не может иметь другие параметры (т. Е. Только последний параметр), в противном случае будет сообщена ошибка.

// 报错
function f(a, ...b, c) {
  // ...
}

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

Можно сказать, что стрелочные функции являются большим преимуществом ES6.Являетесь ли вы функциональным энтузиастом или объектно-ориентированным разработчиком, вы должны использовать функции. Прежде чем объявить функцию, вам нужно использовать функцию следующим образом:

function hello() {
    console.log('say hello')
}
// 或

let hello = function() {
    console.log('say hello')
}

Теперь это можно сделать:

let hello = () => {
    console.log('say hello')
}

А если есть параметры?

let hello = (name) => {
    console.log('say hello', name)
}
// 或者

let hello = name => {
    console.log('say hello', name)
}
// 如果只有一个参数,可以省略括号,如果大于一个参数一定要记得带括号

Объявление и параметры функции написаны четко, так на что следует обратить внимание в возвращаемом значении?

Возврат и {} можно опустить, если возвращаемое значение является выражением.

 let pow = x => x * x

если возвращаемое значение является буквальным объектом

let person = (name) => ({
      age: 20,
      addr: 'Beijing City'
  })

Примечание на функции стрелки

  • В стрелочной функции этого нет, внутреннийthisопределяется в верхней областиthis. То есть внутри стрелочной функцииthisнаведение фиксировано

  • Не может использоваться как конструктор, то есть не может использоваться со стрелочными функциями.newкоманду, иначе будет выдана ошибка.

  • Стрелочные функции не могут использовать объект arguments, которого нет в теле функции. Если вы хотите использовать его, вы можете вместо этого использовать остальные параметры.

  • недоступноyieldкоманда, поэтому функции со стрелками нельзя использовать в качестве функций-генераторов.

Свойство длины функции

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

function foo(a, b = 1, c) {
    console.log(arguments.length)
}
foo('a', 'b') //2

Однако в ES6 аргументы больше нельзя использовать для суждения, но можно использовать Function.length для суждения.

function foo(a, b = 1, c) {
    console.log(foo.length)
}
foo('a', 'b') // 1

Осторожные одноклассники находят результаты Function.Length отличными от аргументов! Правильно, Function.Length — это количество переменных перед первым параметром по умолчанию:

После того как функция укажет значение по умолчанию, свойство length функции вернет количество параметров без указанного значения по умолчанию.

расширение массива

Array.from

представлять

Array.fromМетоды используются для преобразования двух типов объектов в настоящие массивы: массивоподобные объекты и итерируемые объекты (включая новые структуры данных ES6 Set и Map).

грамматика

Array.from(arrayLike[, mapFn[, thisArg]])
  • arrayLike Объект псевдомассива или итерируемый объект, который вы хотите преобразовать в массив.
  • mapFn необязательный Если этот параметр указан, функция обратного вызова будет выполняться для каждого элемента в новом массиве.
  • thisArg необязательный Этот объект при выполнении функции обратного вызова mapFn

Ниже представлен массивоподобный объект,Array.fromПревратите его в настоящий массив.

let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
};

// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']

// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

В практических приложениях распространенными массивоподобными объектами являются коллекции NodeList, возвращаемые операциями DOM, а также коллекции внутри функций.argumentsобъект.Array.fromможет преобразовать их в реальные массивы.


// NodeList对象
let ps = document.querySelectorAll('p');
Array.from(ps).filter(p => {
  return p.textContent.length > 100;
});

// arguments对象
function foo() {
  var args = Array.from(arguments);
  // ...
}

// Set
const set = new Set(['foo', 'bar', 'baz', 'foo']);
Array.from(set); // [ "foo", "bar", "baz" ]

// Map
const map = new Map([[1, 2], [2, 4], [4, 8]]);
Array.from(map); // [[1, 2], [2, 4], [4, 8]]

Если аргумент является реальным массивом,Array.fromвернет идентичный новый массив.

Array.from([1, 2, 3]) // [1, 2, 3]

Array.fromМожет принимать второй параметр, который действует как массивmapметод для обработки каждого элемента и помещения обработанного значения в возвращаемый массив.

Array.from(arrayLike, x => x * x);
// 等同于
Array.from(arrayLike).map(x => x * x);

Array.from([1, 2, 3], (x) => x * x)
// [1, 4, 9]

for...of

Новые методы обхода массива в ES6

for (let val of [1, 2, 3]) {
    console.log(val); // 1,2,3
}

Array.prototype.find()

представлять

Метод find() возвращает значение первого элемента в массиве, которое удовлетворяет предоставленной тестовой функции, в противном случае он возвращает неопределенное значение.

const array1 = [5, 12, 8, 130, 44];
const found = array1.find(element => element > 10);
console.log(found); //12

грамматика

arr.find(callback[, thisArg])

callback Функция для выполнения на каждом элементе массива, получающая 3 аргумента:

element当前遍历到的元素。

index 可选 当前遍历到的索引

array 数组本身

thisArg используется при выполнении обратного вызоваthis Объект.

Array.prototype.findIndex()

Метод findIndex() возвращает индекс первого элемента в массиве, который удовлетворяет предоставленной тестовой функции. В противном случае вернуть -1. На самом деле это работает в паре с find(), разница в том, что она возвращает индекс вместо значения.

let array = [5, 12, 8, 130, 44];
let found = array.find(function(element) {
    return element > 10;
});
console.log(found); // 1

Array.prototype.fill()

представлять

fill() Метод заполняет все элементы массива от начального до конечного индекса фиксированным значением. Индекс завершения не включен.

грамматика

arr.fill(value[, start[, end]])

value используется для заполнения значения элемента массива В качестве альтернативы начальный индекс по умолчанию равен нулю. end необязательный завершающий индекс по умолчанию this.length Возвращает массив измененного значения

если startявляется отрицательным числом, начальный индекс будет автоматически рассчитан какlength+start, в length Да thisобъектыlength стоимость имущества. если endявляется отрицательным числом, конечный индекс будет автоматически рассчитан какlength+end.

const array1 = [1, 2, 3, 4];
console.log(array1.fill(0, 2, 4)); // [1, 2, 0, 0]
console.log(array1.fill(5, 1)); //  [1, 5, 5, 5]
// 只有一个参数,说明其他两项都是默认值,会替换数组全部内容
console.log(array1.fill(6)); // [6, 6, 6, 6]

Array.prototype.copyWithin()

экземпляр массиваcopyWithin()Метод внутри текущего массива копирует элементы указанной позиции в другие позиции (перезаписывает исходные элементы), а затем возвращает текущий массив. То есть использование этого метода изменит текущий массив.

Array.prototype.copyWithin(target, start = 0, end = this.length)

Он принимает три параметра.

  • цель (обязательно): Начать замену данных в этой позиции. Если отрицательно, значит взаимно.
  • start (необязательно): начать чтение данных с этой позиции,默认为 0. Отрицательное значение означает отсчет с конца.
  • конец (необязательно): остановить чтение данных до достижения этой позиции,默认等于数组长度. Отрицательное значение означает отсчет с конца.
// 将3号位复制到0号位
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]

// -2相当于3号位,-1相当于4号位
[1, 2, 3, 4, 5].copyWithin(0, -2, -1) // [4, 2, 3, 4, 5]

// 参数不足三个,没有的参数就是默认值
[1, 2, 3, 4, 5].copyWithin(-2) // [1, 2, 3, 1, 2]
[1, 2, 3, 4, 5].copyWithin(0, 3) // [4, 5, 3, 4, 5]

Array.of()

Array.of()Метод используется для преобразования набора значений в массив.

Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1

Основная цель этого метода — дополнить конструктор массиваArray()недостаточности. Поскольку количество параметров разное, это приведет кArray()поведение разное.

Array() // []
Array(3) // [, , ,]
Array(3, 11, 8) // [3, 11, 8]

В коде лица,Array()Если у метода нет параметров, один параметр или три параметра, возвращаемые результаты будут другими. Только при количестве параметров не менее 2,Array()Будет возвращен новый массив параметров. Когда параметр имеет только одно положительное целое число, он фактически указывает длину массива.

Array.of()в основном может быть использован для заменыArray()илиnew Array(), и нет перегрузки из-за разных параметров. Он ведет себя очень равномерно.

Array.of() // [] `Array.of()`总是返回参数值组成的数组。如果没有参数,就返回一个空数组。
Array.of(undefined) // [undefined]
Array.of(1) // [1]
Array.of(1, 2) // [1, 2]

Расширение номера

Number.isFinite()

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

Number.isFinite(15) // true
Number.isFinite(0.8) // true
Number.isFinite(NaN) // false
Number.isFinite(Infinity) // false
Number.isFinite(-Infinity) // false
Number.isFinite('foo') // false
Number.isFinite('15') // false
Number.isFinite(true) // false

Обратите внимание, что если тип параметра не является числовым,Number.isFiniteвсегда возвращайсяfalse.

Number.isNaN()

Используется для проверки того, является ли значение NaN.

Number.isNaN(NaN) // true
Number.isNaN(15) // false
Number.isNaN('15') // false
Number.isNaN(true) // false
Number.isNaN(9/NaN) // true
Number.isNaN('true' / 0) // true
Number.isNaN('true' / 'true') // true

Если тип параметра неNaN,Number.isNaNвсегда возвращайсяfalse.

Number.isInteger()

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

Number.isInteger(25) // true
Number.isInteger(25.1) // false

Number.isInteger() // false
Number.isInteger(null) // false
Number.isInteger('15') // false
Number.isInteger(true) // false

Number.MAX_SAFE_INTEGER Number.MIN_SAFE_INTEGER

Диапазон целых чисел, которые JavaScript может точно представить, находится в-2^53прибыть2^53между (за исключением двух конечных точек), за пределами этого диапазона, это значение не может быть точно представлено.

Math.pow(2, 53) // 9007199254740992

9007199254740992  // 9007199254740992
9007199254740993  // 9007199254740992

Math.pow(2, 53) === Math.pow(2, 53) + 1 // true

В приведенном выше коде число за пределами 53-й степени 2 является неточным.

Представлен ES6Number.MAX_SAFE_INTEGERа такжеNumber.MIN_SAFE_INTEGERЭти две константы используются для представления верхнего и нижнего пределов этого диапазона.

Number.MAX_SAFE_INTEGER === Math.pow(2, 53) - 1 // true
Number.MAX_SAFE_INTEGER === 9007199254740991 // true

Number.MIN_SAFE_INTEGER === -Number.MAX_SAFE_INTEGER // true
Number.MIN_SAFE_INTEGER === -9007199254740991 // true

Number.isSafeInteger()

Диапазон целых чисел, которые может точно представить JavaScript, находится между -2^53 и 2^53 (исключая две конечные точки), за пределами этого диапазона это значение не может быть точно представлено.

Math.pow(2, 53) // 9007199254740992

Math.pow(2, 53) === Math.pow(2, 53) + 1 // true

Число.parseInt(), Число.parseFloat()

ES6 перенес глобальные методы parseInt(), parseFloat() в объект Number, и поведение осталось полностью неизменным. Цель этого состоит в том, чтобы постепенно уменьшить глобальный метод, делая язык постепенно модульным.

Расширение строки

String.prototype.includes()

В ES5 вы можете использовать метод indexOf, чтобы определить, содержится ли строка в другой строке.indexOf возвращает позицию нижнего индекса вхождения или -1, если она не существует.

const str = 'jimmy'

console.log(str.indexOf('y'))  // 4

ES6 предоставлена ​​включает в себя способ определить, содержится ли строка в другой строке, она возвращает значение логического типа.

const str = 'jimmy'
console.log(str.includes('mm')) // true

// 区分大小写
'Blue Whale'.includes('blue'); // returns false

грамматика

str.includes(searchString[, position])
  • searchString Строка для поиска в этой строке.
  • позиция, с которой позиция индекса текущей строки, чтобы начать поиск подстрок, значение по умолчанию0.

返回值

Возвращает, если текущая строка содержит искомую строкуtrue; иначе возвратfalse. ;

String.prototype.startsWith()

Определяет, находится ли строка параметра в начале исходной строки, и возвращает значение логического типа.

const str = 'jimmy'
console.log(str.startsWith('ji')) // true

String.prototype.endsWith()

Определяет, находится ли строка параметра в конце исходной строки, и возвращает значение логического типа.

const str = 'jimmy'

console.log(str.endsWith('my')) // true

String.prototype.repeat()

Метод Repeat возвращает новую строку, которая повторяет исходную строку n раз.

const str = 'jimmy'
const newStr = str.repeat(2)
console.log(newStr) // jimmyjimmy

Symbol

ES6 представляет новый примитивный тип данныхSymbol, представляющий уникальное значение. Это седьмой тип данных в языке JavaScript.Первые шесть: undefined, null, Boolean, String, Number и Object.

为什么要引入Symbol呢

Все имена свойств объекта ES5 представляют собой строки, что легко вызывает конфликты имен свойств. Например, если вы используете объект, предоставленный кем-то другим, но хотите добавить к этому объекту новый метод (шаблон миксина), имя нового метода может конфликтовать с существующим методом. Было бы неплохо, если бы существовал механизм, обеспечивающий уникальность имени каждого атрибута, что принципиально предотвращало бы конфликт имен атрибутов. Это то, что представил ES6Symbolпричина.

Значение символа черезSymbolгенерация функций. То есть имя свойства объекта теперь может иметь два типа: один — это существующая строка, а другой — недавно добавленный тип символа. Любое имя свойства, относящееся к типу Symbol, уникально, и можно гарантировать, что оно не будет конфликтовать с другими именами свойств.

let a = Symbol();
let b = Symbol();

typeof a  // symbol
console.log(a === b); // false

Функция Symbol может принимать строку в качестве параметра, представляющего описание экземпляра Symbol, в основном для того, чтобы его было легче отличить при отображении на консоли или при преобразовании в строку.

let s1 = Symbol('foo')
let s2 = Symbol('foo')
console.log(s1) //Symbol(foo)
console.log(s2) // Symbol(foo)
// `Symbol`函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的`Symbol`函数的返回值是不相等的。
console.log(s1 === s2) // false

Уведомление

Symbolнельзя использовать перед функциейnewкоманду, иначе будет сообщено об ошибке. Это связано с тем, что результирующий символ является примитивным значением, а не объектом. То есть, поскольку значения Symbol не являются объектами, свойства не могут быть добавлены. По сути, это строковый тип данных.

Если аргументом Symbol является объект, объектtoStringметод, преобразуйте его в строку, а затем сгенерируйте значение Symbol.

const obj = {
  toString() {
    return 'abc';
  }
};
const sym = Symbol(obj); // Symbol(abc)

Symbol 值不能与其他类型的值进行运算,会报错。

let sym = Symbol('My symbol');

"your symbol is " + sym
// TypeError: can't convert symbol to string
`your symbol is ${sym}`
// TypeError: can't convert symbol to string

Symbol 值可以显式转为字符串,布尔值 但是不能转为数值。

let sym = Symbol('My symbol');
String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'

Boolean(sym) // true
!sym  // false

Number(sym) // TypeError
sym + 2 // TypeError

Symbol.for()

Symbol.for()Принимает строку в качестве параметра и ищет значение Symbol с этим параметром в качестве имени. Если есть, верните значение Symbol, в противном случае создайте новое значение Symbol со строкой в ​​качестве имени и зарегистрируйте его глобально.

let s1 = Symbol.for('foo')
let s2 = Symbol.for('foo')
console.log(s1 === s2) // true

Symbol.for() и Symbol() генерируют новые символы. Разница между ними в том, что первые будут регистрироваться в глобальной среде поиска, вторые — нет. Symbol.for() не возвращает новое значение типа Symbol при каждом вызове, а сначала проверяет, существует ли уже данный ключ, и создает новое значение, если оно не существует.

Symbol.keyFor()

Метод Symbol.keyFor() возвращает зарегистрированный ключ типа Symbol.

const s1 = Symbol('foo')
console.log(Symbol.keyFor(s1)) // undefined

const s2 = Symbol.for('foo')
console.log(Symbol.keyFor(s2)) // foo

Сценарии применения

消除魔术字符串

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

function getArea(shape, options) {
  let area = 0;

  switch (shape) {
    case 'Triangle': // 魔术字符串
      area = .5 * options.width * options.height;
      break;
     /* ... more code ... */
  }

  return area;
}

getArea('Triangle', { width: 100, height: 100 }); // 魔术字符串

В приведенном выше коде строки Triangle и Circle являются магическими строками. Он появляется много раз и образует «сильную связь» с кодом, что не способствует его модификации и сопровождению в будущем.

Обычный способ избавиться от волшебной строки — записать ее как переменную.

const shapeType = {
  triangle: 'Triangle'
};

function getArea(shape, options) {
  let area = 0;
  switch (shape) {
    case shapeType.triangle:
      area = .5 * options.width * options.height;
      break;
  }
  return area;
}

getArea(shapeType.triangle, { width: 100, height: 100 });

В приведенном выше коде мы поместилиTriangleнаписано какshapeTypeобъектtriangleсвойств, что устраняет сильную связь.

Если внимательно проанализировать, то можно найтиshapeType.triangleНеважно, какое значение это равно, просто убедитесь, что он не соответствует другомуshapeTypeЗначение свойства можно настроить. Следовательно, это идеально подходит для использования значений символов.

const shapeType = {
  triangle: Symbol()
};

окончательный код

const shapeType = {
    triangle: Symbol(),
    circle: Symbol()
}

function getArea(shape) {
    let area = 0
    switch (shape) {
        case shapeType.triangle:
             area = .5 * options.width * options.height;
             break;
        case shapeType.circle:
            // ... more code ...
            break
    }
    return area
}
console.log(getArea(shapeType.triangle))

Symbol 类型还可以用于定义一组常量,保证这组常量的值都是不相等的。

const COLOR_RED    = Symbol();
const COLOR_GREEN  = Symbol();

function getComplement(color) {
  switch (color) {
    case COLOR_RED:
      return COLOR_GREEN;
    case COLOR_GREEN:
      return COLOR_RED;
    default:
      throw new Error('Undefined color');
    }
}

Самым большим преимуществом использования значений Symbol для констант является то, что никакое другое значение не может иметь такое же значение, поэтому вышеизложенное может быть гарантировано.switchЗаявления работают, как задумано.

Set

ES6 предоставляет новую структуру данных Set. Он похож на массив, но все значения членов уникальны и нет повторяющихся значений.

Setсам по себе является конструктором, который генерирует структуру данных Set.

 let s = new Set()
 // 在实例化的同时传入默认的数据。
 let s2 = new Set([1,2,3])
 
 // 初始化的参数必须是可遍历的,可以是数组或者自定义遍历的数据结构。

добавление данных

 let s = new Set()
 s.add('chimmy')
 s.add('18')
 s.add('jimmy').add('18')
 // Set 数据结构不允许数据重复,所以添加重复的数据是无效的
 console.log(s); // Set(3) { 'chimmy', '18', 'jimmy' }

удалить данные

  // 删除指定数据
  s.delete('jimmy') // true
  // 删除全部数据
  s.clear()

Найти и суммировать

// 判断是否包含数据项,返回 true 或 false
s.has('hello') // true
// 计算数据项总数
s.size // 3

Сценарии применения

Дедупликация массива

let arr = [1, 2, 3, 4, 2, 3]
let s = [...new Set(arr)]
console.log(s) // [1,2,3,4]

дедупликация слияния

let arr1 = [1, 2, 3, 4]
let arr2 = [2, 3, 4, 5, 6]
let s = new Set([...arr1, ...arr2])
console.log(s) // Set(6) { 1, 2, 3, 4, 5, 6 }
console.log([...s]) // [ 1, 2, 3, 4, 5, 6 ]
console.log(Array.from(s)) // [ 1, 2, 3, 4, 5, 6 ]

перекресток

let arr1 = [1, 2, 3, 4]
let arr2 = [2, 3, 4, 5, 6]
let s1 = new Set(arr1)
let s2 = new Set(arr2)
let result = new Set(arr1.filter(item => s2.has(item)))
console.log(Array.from(result)) // [ 2, 3, 4 ]

разница

let arr1 = [1, 2, 3, 4];
let arr2 = [2, 3, 4, 5, 6];
let s1 = new Set([1, 2, 3, 4])
let s2 = new Set([2, 3, 4, 5, 6])
let arr3 = new Set(arr1.filter(item => !s2.has(item)))
let arr4 = new Set(arr2.filter(item => !s1.has(item)))
console.log(arr3) // Set(1) { 1 }
console.log(arr4) // Set(2) { 5, 6 }  
console.log([...arr3, ...arr4]) // [ 1, 5, 6 ]

WeakSet

Структура WeakSet похожа на Set, это тоже набор уникальных значений. Однако он отличается от Set двумя способами.

Членами WeakSet могут быть только объекты, а не другие типы значений.

const ws = new WeakSet()
ws.add(1)
// TypeError: Invalid value used in weak set
ws.add(Symbol())
// TypeError: invalid value used in weak set
let ws = new WeakSet()
const obj1 = {
    name: 'imooc'
}
const obj2 = {
    age: 5
}
ws.add(obj1)
ws.add(obj2)
ws.delete(obj1)
console.log(ws)
console.log(ws.has(obj2))

WeakSet не имеет свойства размера, нет возможности перебирать его элементы.

Все объекты в WeakSet являются слабыми ссылками, то есть механизм сборки мусора не рассматривает ссылку на объект в WeakSet, то есть, если другие объекты больше не ссылаются на объект, механизм сборки мусора автоматически освободит память занята объектом, независимо от того, существует ли еще объект в WeakSet.

Map

Объекты JavaScript (Object) по сути представляют собой набор пар ключ-значение (структура Hash), но традиционно в качестве ключей могут использоваться только строки. Это накладывает существенные ограничения на его использование.

const data = {};
const element = document.getElementById('myDiv');

data[element] = 'metadata';
data['[object HTMLDivElement]'] // "metadata"

Первоначальное намерение приведенного выше кода - использовать узел DOM в качестве объекта.data, но поскольку объект принимает только строки в качестве имен ключей,elementавтоматически преобразуется в строку[object HTMLDivElement].

为了解决这个问题,ES6 提供了 Map 数据结构。 Он подобен объекту и также представляет собой набор пар ключ-значение, но область действия «ключей» не ограничивается строками, и в качестве ключей могут использоваться различные типы значений (включая объекты).也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。 Если вам нужна структура данных "ключ-значение", Map больше подходит, чем Object.

const m = new Map();
const o = {p: 'Hello World'};

m.set(o, 'content')
m.get(o) // "content"

m.has(o) // true
m.delete(o) // true
m.has(o) // false

В приведенном выше коде используется структура Mapsetметод, предметoтак какmключ , а затем используйтеgetметод для чтения этого ключа, затем используйтеdeleteметод удаляет этот ключ.

добавление данных

  let map = new Map()
  let keyObj = {}
  let keyFunc = function() {}
  let keyString = 'a string'

  // 添加键
  map.set(keyString, "和键'a string'关联的值")
  map.set(keyObj, '和键keyObj关联的值')
  map.set(keyFunc, '和键keyFunc关联的值')
  console.log(map) //
  // Map(3) {
  // 'a string' => "和键'a string'关联的值",
  // {} => '和键keyObj关联的值',
  // [Function: keyFunc] => '和键keyFunc关联的值'
  // }

удалить данные

  // 删除指定的数据
  map.delete(keyObj)
  // 删除所有数据
  map.clear()

Поиск и статистика

  // 统计所有 key-value 的总数
  console.log(map.size) //3
  // 判断是否有 key-value
  console.log(map.has(keyObj)) // true

Получать

 console.log(map.get(keyObj)) // 和键keyObj关联的值

weakMap

Подобно структуре Map, структура WeakMap также используется для создания набора пар ключ-значение.

// WeakMap 可以使用 set 方法添加成员
const wm1 = new WeakMap()
const key = {
    foo: 1
}
wm1.set(key, 2)
wm1.get(key) // 2

// WeakMap 也可以接受一个数组,
// 作为构造函数的参数
const k1 = [1, 2, 3]
const k2 = [4, 5, 6]
const wm2 = new WeakMap([
    [k1, 'foo'],
    [k2, 'bar']
])
wm2.get(k2) // "bar"

Есть два различия между WeakMap и Map.

  • Объект, на который указывает имя ключа WeakMap, не включается в механизм сборки мусора.
  • WeakMap принимает в качестве ключей только объекты (кроме null) и не принимает в качестве ключей другие типы значений.
const map = new WeakMap()
map.set(1, 2)
// TypeError: 1 is not an object!
map.set(Symbol(), 2)
// TypeError: Invalid value used as weak map key
map.set(null, 2)
// TypeError: Invalid value used as weak map key

наконец

В этой статье 10 000 слов, ограниченных пробелом, ES6Class,Proxy,Reflect,Promise,ModuleЯ напишу несколько статей отдельно в будущем, чтобы объяснить подробно.

рекомендуемая статья

Полное объяснение грамматики ES7-ES12