ES6(一)

85 阅读7分钟

关于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>

image.png

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']]