关于ES6
ECMAScript 6.0(简称 ES6)是 JavaScript 语言的下一代标准
关于变量声明
let声明变量
没有变量提升
console.log(a)
let a=1;
//ReferenceError: Cannot access 'a' before initialization
只在块级作用域内有效
{
let a = 10;
var b = 1;
}
a // ReferenceError: a is not defined.
b // 1
暂时性死区
在一个块级作用域内,如果存在有let声明的变量,那么该变量自动绑定当前作用域
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
const 声明常量
const声明一个只读的常量。一旦声明,常量的值就不能改变。
const a=5;
a=6;//TypeError: Assignment to constant variable.
const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
const的作用域与let命令相同:只在声明所在的块级作用域内有效。
const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
const声明的常量,也与let一样不可重复声明。
变量的解构赋值
let [变量名1,变量名2,变量名3]=[值1,值2,值3];
案例:
let [foo, [[bar], baz]] = [1, [[2], 3]];
let [foo] = [];
let [bar, foo] = [1];
let [x, y] = [1, 2, 3];
字符串的扩展
模板字符串:
支持换行(不需要拼接字符串了)
可以写变量
console.log(`好好学习
天天向上`);
函数的扩展
函数默认参数
用es5实现函数默认参数:
弊端,如果传入0 false等数据会认为没有传参数
function fn(a){
a=a||5
}
es6的写法:
function fn(a=5){
console.log(a)
}
rest参数
ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。
rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
rest参数是一个真正的数组,数组特有的方法都可以使用
function fn(a,...b){
console.log(a)//1
console.log(b)//[2, 3, 4]
}
fn(1,2,3,4)
箭头函数
语法
let fn=m=>m
关于this指向:箭头函数中的this指向的是定义时所在的对象(内部的this就是定义时上层作用域中的this)
也就是说箭头函数没有自己的this,箭头函数内部的this指向是固定的,相比之下,普通函数的this的指向是不可变的
function Timer() {
this.s1 = 0;
this.s2 = 0;
// 箭头函数
setInterval(() => this.s1++, 1000);
// 普通函数
setInterval(function () {
this.s2++;
}, 1000);
}
var timer = new Timer();
setTimeout(() => console.log('s1: ', timer.s1), 3100);
setTimeout(() => console.log('s2: ', timer.s2), 3100);
数组的扩展
扩展运算符:
... 扩展运算符 可以把数组和类数组结构拆分成以逗号分隔的参数序列
console.log(...[1, 2, 3])
// 1 2 3
对象的扩展
语法上的简化
如果对象的属性值是变量,并且变量的名字跟属性名同名,键值对可以省略为一个
如果对象的属性值是函数,可以省略:function
let birth = '2000/01/01';
const Person = {
name: '张三',
//等同于birth: birth
birth,
// 等同于hello: function ()...
hello() { console.log('我的名字是', this.name); }
};
对象的解构赋值
let {name,age}={name:"小明",age:18}
配合扩展运算符
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }
嵌套解构
let {name,age,hobby:{sport}}={name:"小明",age:18,hobby:{sport:"basketball"}}
symbol
ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。(和字符串类似)
symble数据要通过symbol函数来生成
// 没有参数的情况
let s1 = Symbol();
let s2 = Symbol();
s1 === s2 // false,因为都是独一无二的
// 有参数的情况,传参具备描述性
let s1 = Symbol('foo');
let s2 = Symbol('foo');
s1 === s2 // false
symbol作为对象的属性名:
let mySymbol = Symbol();
// 第一种写法
let a = {};
a[mySymbol] = 'Hello!';
// 第二种写法
let a = {
[mySymbol]: 'Hello!'
};
Set
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值
const set = new Set([1, 2, 3, 4, 4]);//1,2,3,4
set可以为数组自动去重:
let arr = new Array(1,1,1,2,2,3,3,9,9,6,7,7,5,5,4,2,4,9);
let set = new Set(arr);
arr=[...set];//先拆再合
console.log(set);
Set的属性和方法
- size :返回Set实例的成员总数
- add(value) :添加某个值,返回 Set 结构本身
- delete(value) :删除某个值,返回一个布尔值,表示删除是否成功。
- has(value):返回一个布尔值,表示该值是否为Set的成员。
- clear():清除所有成员,没有返回值。
s.add(1).add(2).add(2);
// 注意2被加入了两次,但是最后set里只有2个值。set会自动去除
//检测set长度
s.size // 2
//检测是否有某个值
s.has(1) // true
s.has(2) // true
s.has(3) // false
//删除
s.delete(2);
s.has(2) // false
set的遍历操作
- keys():返回键名的遍历器
- values():返回键值的遍历器
- entries():返回键值对的遍历器
- forEach():使用回调函数遍历每个成员
keys(),values(),entries()
let set = new Set(['red', 'green', 'blue']);
for (let item of set.keys()) {
console.log(item);
}
// red
// green
// blue
for (let item of set.values()) {
console.log(item);
}
// red
// green
// blue
for (let item of set.entries()) {
console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]
forEach()
let set = new Set([1, 4, 9]);
set.forEach((value, key) => console.log(key + ' : ' + value))
// 1 : 1
// 4 : 4
// 9 : 9
关于for of循环
循环对象可以用for in,不能用for of
const obj = {
a: 1,
b: 2,
c: 3
}
for (let i in obj) {
console.log(i)
// a
// b
// c
}
for (let i of obj) {
console.log(i)
// Uncaught TypeError: obj is not iterable 报错了
}
循环数组用for in 和for of都行
const arr = ['a', 'b', 'c']
// for
for (let i in arr) {
console.log(i)
// 0
// 1
// 2
}
// for of
for (let i of arr) {
console.log(i)
// a
// b
// c
}
for in 和 for of区别
区别一:for in 和 for of 都可以循环数组,for in 输出的是数组的index下标,而for of 输出的是数组的每一项的值。
const arr = [1,2,3,4]
// for ... in
for (const key in arr){
console.log(key) // 输出 0,1,2,3
}
// for ... of
for (const key of arr){
console.log(key) // 输出 1,2,3,4
}
区别二:for in 可以遍历对象,for of 不能遍历对象,只能遍历带有iterator接口的,例如Set,Map,String,Array
const object = { name: 'lx', age: 23 }
// for ... in
for (const key in object) {
console.log(key) // 输出 name,age
console.log(object[key]) // 输出 lx,23
}
// for ... of
for (const key of object) {
console.log(key) // 报错 Uncaught TypeError: object is not iterable
}
总结:for in适合遍历对象,for of适合遍历数组。for in遍历的是数组的索引,对象的属性,以及原型链上的属性。
Map
定义:ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
Map的属性和方法
- size :返回 Map 实例的成员总数
const map = new Map();
map.set('foo', true);
map.set('bar', false);
map.size // 2
- set(key, value) :set方法设置键名key对应的键值为value
const m = new Map();
m.set('edition', 6) // 键是字符串
m.set(262, 'standard') // 键是数值
m.set(undefined, 'nah') // 键是 undefined
- get(key) get方法读取key对应的键值,如果找不到key,返回undefined
const m = new Map();
const hello = function() {console.log('hello');};
m.set(hello, 'Hello ES6!') // 键是函数
m.get(hello) // Hello ES6!
- has(key):has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中
const m = new Map();
m.set('edition', 6);
m.set(262, 'standard');
m.set(undefined, 'nah');
m.has('edition') // true
m.has('years') // false
m.has(262) // true
m.has(undefined) // true
- delete(key):delete方法删除某个键,返回true。如果删除失败,返回false。
const m = new Map();
m.set(undefined, 'nah');
m.has(undefined) // true
m.delete(undefined)
m.has(undefined) // false
- clear():clear方法清除所有成员,没有返回值。
let map = new Map();
map.set('foo', true);
map.set('bar', false);
map.size // 2
map.clear()
map.size // 0
Map的遍历方法
- keys():返回键名的遍历器
- values():返回键值的遍历器
- entries():返回键值对的遍历器
- forEach():使用回调函数遍历每个成员
keys(),values(),entries()
const map = new Map([
['F', 'no'],
['T', 'yes'],
]);
for (let key of map.keys()) {
console.log(key);
}
// "F"
// "T"
for (let value of map.values()) {
console.log(value);
}
// "no"
// "yes"
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"
// 或者
for (let [key, value] of map.entries()) {
console.log(key, value);
}
// "F" "no"
// "T" "yes"
// 等同于使用map.entries()
for (let [key, value] of map) {
console.log(key, value);
}
// "F" "no"
// "T" "yes"
forEach()
const map = new Map()
.set(1, 'a')
.set(2, 'b')
.set(3, 'c');
map.forEach(function(value, key, map) {
console.log("Key: %s, Value: %s", key, value);
});
</script>
Map与数组的转换
const map = new Map([ [1, 'one'],
[2, 'two'],
[3, 'three'],
]);
[...map.keys()]
// [1, 2, 3]
[...map.values()]
// ['one', 'two', 'three']
[...map.entries()]
// [[1,'one'], [2, 'two'], [3, 'three']]
[...map]
// [[1,'one'], [2, 'two'], [3, 'three']]