es6基础语法总结

ECMAScript 6 简介

本笔记相当于阮一峰老师的ES6教程进行了进一步浓缩

  • ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。
  • ECMAScript 是 JavaScript 语言的标注规范。
  • JavaScript 是 ECMAScript 规范的具体实现。
    • 具体实现取决于各大浏览器厂商的支持进度
  • ECMAScript 6 也被称作 ECMAScript 2015
  • 目前,各大浏览器对 ES6 的支持可以查看kangax.github.io/compat-table/es6/。
  • 对于不支持 ES6 的环境,可以使用一些编译转码工具做转换处理再使用
    • 比如 babel

let 和 const 命令

1. let命令特性

1.1 let 具有块级作用域

1
2
3
4
5
6
7
{
let a = 10;
var b = 1;
}

console.log(a); // ReferenceError: a is not defined.
console.log(b); // 1

1.2 不存在变量提升

1
2
console.log(bar); // 报错ReferenceError
let bar = 2;

1.3 暂时性死区

1
2
3
4
5
6
7
var tmp = 123
if (true) {
// 当前所在块级区域的 tmp 会默认为被 let 声明绑定了
// 所以只能先声明后赋值
tmp = 'abc'; // ReferenceError
let tmp;
}

1.4 不允许重复声明

let不允许在相同作用域内,重复声明同一个变量。

1
2
3
4
5
6
7
8
9
10
11
// 报错
function func() {
let a = 10;
var a = 1;
}

// 报错
function func() {
let a = 10;
let a = 1;
}

2. 块级作用域的好处

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<script>
// 点击按钮依次弹出它的索引号
var btns = document.querySelectorAll("button");
// 1. 使用var变量 但得用闭包
// for (var i = 0; i < btns.length; i++) {
// // 用var 需要用到闭包 才能解决
// (function (i) {
// btns[i].onclick = function () {
// alert(i)
// }
// })(i)
// };

// 2. 使用let变量 直接就可以 因为let具有块级作用域
for (let i = 0; i < btns.length; i++) {
btns[i].onclick = function () {
alert(i)
}

};
</script>
</body>


3. const 命令特性

和 let 特性一样 唯一的区别在于 const 声明后不能再修改,常量

1
2
const PI = 3.14
PI = 3 // TypeError: Assignment to constant variable.
1
2
3
4
5
6
// const 常量 对于复杂类型, 内部的值可以更改 但是把复杂类型整体修改是不允许的, 也就是复杂类型整体的内存地址不可更改
const ary = [100, 200];
ary[0] = 1; // 因为更改内部的值 并没有更改它的内存地址 所有可以修改
console.log(ary); // 1,200
ary = [3, 4]; // 这个 把整体都重新赋值了也就是更改了它的内存地址 故报错
console.log(ary); // 报错

4. 解构赋值

注意:解构赋值 必须要同时进行,不能先声明再赋值 如: let {a,b}; {a,b}={a:12,b:5} 这样是错的

4.1 基本使用

1
2
3
4
let [a,b,c]  = [1,2,3] // 相当于以下
let a = 1
let b = 2
let c = 3

本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值

1
2
3
4
5
function f() {
console.log('aaa');
}

let [x = f()] = [1];

上面代码中,因为x能取到值,所以函数f根本不会执行。上面的代码其实等价于下面的代码。

1
2
3
4
5
6
let x;
if ([1][0] === undefined) {
x = f();
} else {
x = [1][0];
}

4.2 对象的解构赋值

1
2
3
4
5
6
let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"

let { baz } = { foo: 'aaa', bar: 'bbb' };
baz // undefined 因为bar变量没有对应的同名属性,导致取不到值,最后等于undefined。

4.3 字符串的解构赋值

1
2
3
4
5
6
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"

4.4 函数参数的解构赋值

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

add([1, 2]); // 3

上面代码中,函数add的参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量x和y。对于函数内部的代码来说,它们能感受到的参数就是x和y。

4.5 用途

(1) 交换变量的值
1
2
3
4
let x = 1;
let y = 2;

[x, y] = [y, x];

上面代码交换变量x和y的值,这样的写法不仅简洁,而且易读,语义非常清晰。

(2)从函数返回多个值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 返回一个数组

function example() {
return [1, 2, 3];
}
let [a, b, c] = example();

// 返回一个对象

function example() {
return {
foo: 1,
bar: 2
};
}
let { foo, bar } = example();

(3)提取 JSON 数据

解构赋值对提取 JSON 对象中的数据,尤其有用。

1
2
3
4
5
6
7
8
let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]

5.字符串的扩展

模板字符串

1
2
3
4
5
6
7
8
9
10
11
//  字符串模板 的 优点   1.  可以直接塞东西进去   $(东西)   2. 可以换行  注意用 反单引号 ``
let uname = '王鹏飞';
// 拼接字符串
// let str = 'hello,我的名字是' + uname + '';
// let str = 'hello,我的名字是' + uname;
let str = `hello,我的名字是${uname}`;//hello,我的名字是王鹏飞
console.log(uname);
console.log(str);

let arr = [1, 55, 88, 4156, 12];
arr.forEach((item, index) =>console.log(`第${index}个:${item}`));

startsWith 和 endsWidth

  • startsWith() : 表示参数字符串是否在原子符串的头部,返回布尔值
  • endsWidth() :表示参数字符串是否在原字符串的尾部,返回布尔值
1
2
3
let str = 'hello world'
str.startsWith('hello') // true
str.endsWidth('!') // true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 // startsWith
let start = 'https://www.baidu.com/';
if (start.startsWith('http:')) {
console.log('普通网址');
} else if (start.startsWith('https:')) {
console.log('加密网址');
} else if (start.startsWith('svg:')) {
console.log('库');
} else {
console.log('其他网址')
};
// endsWidth
let end = '1.jpg';
if (end.endsWith('.jpg')) {
console.log('jpg图片');
} else if (end.endsWith('.png')) {
console.log('png图片');
} else if (end.endsWith('.webp')) {
console.log('webp图片');
}
// repeat
console.log('wpf'.repeat(3)); // 把wpf 重复三次 wpfwpfwpf色图st

6.数组的扩展

6.1 Array.from()

Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。

下面是一个类似数组的对象,Array.from将它转为真正的数组。

1
2
3
4
5
6
7
8
9
10
11
12
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']

实际应用中,常见的类似数组的对象是 DOM 操作返回的 NodeList 集合,以及函数内部的arguments对象。Array.from都可以将它们转为真正的数组。

1
2
3
4
5
6
7
8
9
10
11
// NodeList对象
let ps = document.querySelectorAll('p');
Array.from(ps).filter(p => {
return p.textContent.length > 100;
});

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

上面代码中,querySelectorAll方法返回的是一个类似数组的对象,可以将这个对象转为真正的数组,再使用filter方法。

6.2 Array.of()

Array.of方法用于将一组值,转换为数组。

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

这个方法的主要目的,是弥补数组构造函数Array()的不足。因为参数个数的不同,会导致Array()的行为有差异.

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

6.3 数组实例的 find() 和 findIndex()

find()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const arr = [{
name: 'wpf',
age: 23
},
{
name: 'zyz',
age: 24
}, {
name: 'zd',
age: 25
}
]
let newArr = arr.find(item => item.name === 'wpf')
console.log(newArr); // { name: 'wpf', age: 23 }
findIndex()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const arr = [{
name: 'wpf',
age: 23
},
{
name: 'zyz',
age: 24
}, {
name: 'zd',
age: 25
}
]
let newArr = arr.findIndex(item => item.name === 'zyz')
console.log(newArr); // 1

数组实例的 includes()

数组中是否包含某个元素

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

rest参数

rest 参数(形式为…变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

1
2
3
4
5
function fn(a, ...args) {
console.log(...args); // 2 3
console.log(args); // [2,3]
}
fn(1, 2, 3)

箭头函数

箭头函数就是用来简化函数定义语法的
适用场景: 在方法中使用。 比如: find(),map(),等

1
2
3
4
funciton sum (num1,num2){
return num1 + num2
} // 相当于以下代码
const sum = (num1,num2) => num1 + num2
  • 箭头函数特点
    • 如果形参只有一个的话,可以省略小括号()
    • 如果函数体中的代码只有一个return,可以省略小括号()
    • this指向的是原先定义好的位置,而不是随着当前箭头函数的位置而改变
  • 由于箭头函数this 的指向问题 所以:
    • 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
    • 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
1
2
3
4
5
6
7
8
9
function Person() {  
this.age = 0;
setInterval(() => {
// 回调里面的 `this` 变量就指向了期望的那个对象了
this.age++;
}, 3000);
}

var p = new Person();