ES6新特性
常用的ES6语法
箭头函数语法
ES6标准新增了一种新的函数:Arrow Function(箭头函数)。
通常函数的定义方法:
varfn1 =
function(a, b){
return
a + b
}
function fn2(a, b) {
return
a + b
}
使用ES6箭头函数语法定义函数,将原函数的“function”关键字和函数名都删掉,并使用“=>”连接参数列表和函数体
var fn1 =
(a, b) =>{
return
a + b
}
(a, b) => {
return
a + b
}
当函数参数只有一个,括号可以省略;但是没有参数时,括号不可以省略
// 无参
varfn1 =
function(){}
varfn1 =
() =>{}
// 单个参数
varfn2 =
function(a){}
varfn2 =
a =>{}
// 多个参数
varfn3 =
function(a, b){}
varfn3 =
(a, b) =>{}
// 可变参数
varfn4 =
function(a, b, ...args){}
varfn4 =
(a, b, ...args) =>{}
箭头函数相当于匿名函数,并且简化了函数定义。箭头函数有两种格式,一种只包含一个表达式,省略掉了{ … }和return。还有一种可以包含多条语句,这时候就不能省略{ … }和return
() =>
return'hello'
(a, b) => a + b
(a) => {
a = a +
1
return
a
}
如果返回一个对象,需要特别注意,如果是单表达式要返回自定义对象,不写括号会报错,因为和函数体的{ … }有语法冲突。
注意,用小括号包含大括号则是对象的定义,而非函数主体
x=> {key: x} //
报错
x=> ({key: x}) //
正确
箭头函数看上去是匿名函数的一种简写,但实际上,箭头函数和匿名函数有个明显的区别:箭头函数内部的this是词法作用域,由上下文确定。(词法作用域就是定义在词法阶段的作用域。换句话说,词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的,因此当词法分析器处理代码时会保持作用域不变 。)
非箭头函数
var Person = {
firstName
:
'hello',
lastName
:
'world',
getFullName
:
function(){
console
.log(
this)
var
first =
this.firstName
// hello
var
fn =
function(){
console
.log(
this)
return
this
.firstName +
this.lastName
}
return
fn()
}
}
Person.getFullName()
//{firstName: "hello", lastName: "world",getFullName:f}
//Window {postMessage: f, blur: f, focus: f, close: f, frames: Window,...}
现在,箭头函数完全修复了this的指向,this总是指向词法作用域,也就是外层调用者Person
var Person = {
firstName
:
'hello',
lastName
:
'world',
getFullName
:
function(){
console
.log(
this)
var
first =
this.firstName
// hello
var
fn =
() =>{
console
.log(
this)
return
this
.firstName +
this.lastName
}
return
fn()
}
}
Person.getFullName()
//{firstName: "hello", lastName: "world",getFullName:f}
//{firstName: "hello", lastName: "world",getFullName:f}
let 与 const
ES6新增加了两个重要的 JavaScript 关键字: let 和 const。
let 命令(推荐使用)
let 声明的变量只在 let 命令所在的代码块内有效。
{
let
a =
0;
a
// 0
}
a
// 报错 ReferenceError: a is not defined
let 是在代码块内有效,var 是在全局范围内有效:
{
let
a =
0;
var
b =
1;
}
a
// ReferenceError: a is not defined
b
// 1
const 命令
const 声明一个只读变量,声明之后不允许改变。意味着,一旦声明必须初始化,否则会报错。
constPI =
"3.1415926";
PI
// 3.1415926
const MY_AGE;
// SyntaxError: Missing initializer in const declaration
解构赋值
解构赋值是对赋值运算符的扩展。
他是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。
在解构中,有下面两部分参与:
解构的源,解构赋值表达式的右边部分。解构的目标,解构赋值表达式的左边部分。
数组模型的解构(Array)
基本
let[a, b, c] = [
1,
2,
3];
// a = 1 // b = 2 // c = 3
可嵌套
let[a, [[b], c]] = [
1, [[
2],
3]];
// a = 1 // b = 2 // c = 3
可忽略
let[a, , b] = [
1,
2,
3];
// a = 1 // b = 3
不完全解构
let[a =
1, b] = [];
// a = 1, b = undefined
剩余运算符
let[a, ...b] = [
1,
2,
3];
//a = 1 //b = [2, 3]
字符串等
在数组的解构中,解构的目标若为可遍历对象,皆可进行解构赋值。可遍历对象即实现 Iterator 接口的数据。
let[a, b, c, d, e] =
'hello'; // a =
'h'// b =
'e'// c =
'l'// d =
'l'// e =
'o'
解构默认值
let[a =
2] = [
undefined];
// a = 2
当解构模式有匹配结果,且匹配结果是 undefined 时,会触发默认值作为返回结果。
let[a =
3, b = a] = [];
// a = 3, b = 3
let[a =
3, b = a] = [
1];
// a = 1, b = 1
let[a =
3, b = a] = [
1,
2];
// a = 1, b = 2
//a 与 b 匹配结果为 undefined ,触发默认值:a = 3; b = a =3
//a 正常解构赋值,匹配结果:a = 1,b 匹配结果 undefined ,触发默认值:b = a =1
//a 与 b 正常解构赋值,匹配结果:a = 1,b = 2
对象模型的解构(Object)
基本
let{ foo, bar } = { foo:
'aaa', bar:
'bbb'}; // foo =
'aaa'// bar =
'bbb'
let{ baz : foo } = { baz :
'ddd'}; // foo =
'ddd'
可嵌套可忽略
letobj = {p: [
'hello', {y:
'world'}] };
let{p: [x, { y }] } = obj; // x =
'hello'// y =
'world'
letobj = {p: [
'hello', {y:
'world'}] };
let {p: [x, { }] } = obj; // x =
'hello'
不完全解构
letobj = {p: [{y:
'world'}] };
let {p: [{ y }, x ] } = obj; // x = undefined // y =
'world'
剩余运算符
let{a, b, ...rest} = {a:
10, b:
20, c:
30, d:
40};
// a = 10 // b = 20 // rest = {c: 30, d: 40}
解构默认值
let{a =
10, b =
5} = {a:
3};
// a = 3; b = 5;
let{a: aa =
10, b: bb =
5} = {a:
3};
// aa = 3; bb = 5;
字符串
ES6 之前判断字符串是否包含子串,用 indexOf 方法,ES6 新增了子串的识别方法
includes():返回布尔值,判断是否找到参数字符串。
startsWith():返回布尔值,判断参数字符串是否在原字符串的头部。
endsWith():返回布尔值,判断参数字符串是否在原字符串的尾部。
以上三个方法都可以接受两个参数,需要搜索的字符串,和可选的搜索起始位置索引。
letstring
=
"apple,banana,orange";
string.includes(
"banana");
// true
string.startsWith(
"apple");
// true
string.endsWith(
"apple");
// false
string.startsWith(
"banana",
6)
// true
对象
属性的简洁表示法
ES6允许对象的属性直接写变量,这时候属性名是变量名,属性值是变量值。
constage =
12;
constname =
"Amy";
const person = {age, name};
person
//{age: 12, name: "Amy"}
//等同于
const person = {age: age, name: name}
方法名也可以简写
const person = {
sayHi(){
console
.log(
"Hi");
}
}
person.sayHi();
//"Hi"
//等同于
const person = {
sayHi
:
function(){
console
.log(
"Hi");
}
}
person.sayHi();
//"Hi"
数组
数组创建 Array.of()
将参数中所有值作为元素形成数组。
// 参数值可为不同类型
console.log(
Array.of(
1,
2,
3,
4));
// [1, 2, 3, 4]
console.log(
Array.of(
1,
'2',
true));
// [1, '2', true]
// 参数为空时返回空数组
console.log(
Array.of());
// []
将类数组对象或可迭代对象转化为数组 Array.from()
Array.
from(arrayLike[, mapFn[, thisArg]])
//arrayLike
想要转换的类数组对象或可迭代对象
//mapFn
可选,
map
函数,用于对每个元素进行处理,放入数组的是处理后的元素
console.log(Array.
from([
1,
2,
3],
(n) =>n *
2));
//[
2,
4,
6]
转换可迭代对象
转换 map
let map =
newMap();
map.set(
'key0',
'value0');
map.set(
'key1',
'value1');
console.log(Array.
from(map));
//[[
'key0',
'value0'],[
'key1',
//'value1'
]]
转换 set
letarr = [
1,
2,
3];
letset
=
newSet(arr);
console.log(Array.
from(
set));
// [1, 2, 3]
转换字符串
let str =
'abc';
console.log(Array.
from(str));
//[
"a",
"b",
"c"]
扩展的方法
查找find()
查找数组中符合条件的元素,若有多个符合条件的元素,则返回第一个元素。
letarr =
Array.of(
1,
2,
3,
4);
console.log(arr.find(
item =>item >
2));
// 3
遍历
遍历键值对 entries()
for(
let[key,
value] of [
'a',
'b'].entries()){
console.log(key,
value);
}
// 0 "a" // 1 "b"
遍历键名 keys()
for(
letkey
of[
'a',
'b'].keys()){
console
.log(key);
}
// 0 // 1
遍历键值 values()
for(
letvalue
of [
'a',
'b'].values()){
console.log(
value);
}
// "a" // "b"
数组是否包含指定值 includes()
// 参数1:包含的指定值
[
1,
2,
3].includes(
1);
// true
Map 与 Set
Map 对象
Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。
varmyMap =
newMap();
varkeyString =
"a string";
myMap.
set(keyString,
"和键'a string'关联的值");
myMap.
get(keyString);
// "和键'a string'关联的值"
myMap.
get(
"a string");
// "和键'a string'关联的值"
// 因为 keyString === 'a string'
Map 的迭代
对 Map 进行遍历,以下两个最高级。
for…of
varmyMap =
newMap
();
myMap.set(
0,
"zero");
myMap.set(
1,
"one");
// 将会显示两个 log。一个是 "0 = zero" 另一个是 "1 = one"
for(
var[key, value]
ofmyMap) {
console
.log(key +
" = "+ value);
}
for(
var[key, value]
ofmyMap.entries()) {
console
.log(key +
" = "+ value);
}
/* 这个 entries 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的 [key, value] 数组。 */
// 将会显示两个log。一个是 "0" 另一个是 "1"
for(
varkey
ofmyMap.keys()) {
console
.log(key);
}
/* 这个 keys 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的键。 */
// 将会显示两个log。一个是 "zero" 另一个是 "one"
for(
varvalue
ofmyMap.values()) {
console
.log(value);
}
/* 这个 values 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的值。 */
forEach()
varmyMap =
newMap
();
myMap.set(
0,
"zero");
myMap.set(
1,
"one");
// 将会显示两个 logs。一个是 "0 = zero" 另一个是 "1 = one"
myMap.forEach(
function(value, key){
console
.log(key +
" = "+ value);
}, myMap)
Set 对象
Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。
letmySet =
newSet();
mySet.
add(
1);
// Set(1) {1}
mySet.
add(
5);
// Set(2) {1, 5}
mySet.
add(
5);
// Set(2) {1, 5} 这里体现了值的唯一性
mySet.
add(
"some text");
// Set(3) {1, 5, "some text"} 这里体现了类型的多样性
varo = {a:
1, b:
2};
mySet.
add(o); mySet.
add({a:
1, b:
2});
// Set(5) {1, 5, "some text", {…}, {…}}
// 这里体现了对象之间引用不同不恒等,即使值相同,Set 也能存储
Set 对象作用
数组去重
varmySet =
newSet
([
1,
2,
3,
4,
4]);
[...mySet];
// [1, 2, 3, 4]
并集
vara =
newSet
([
1,
2,
3]);
varb =
newSet
([
4,
3,
2]);
varunion =
newSet
([...a, ...b]);
// {1, 2, 3, 4}
交集
varintersect =
newSet
([...a].filter(
x =>b.has(x)));
// {2, 3}
差集
vardifference =
newSet
([...a].filter(
x =>!b.has(x)));
// {1}
迭代
constset
=
newSet();
set.
add(
"zero");
set.
add(
"one");
for(
letitem of
set) {
console.log(item);
}
// output: // zero // one