let和const

let:

  1. 不允许重复声明
  2. 没有预解析,没有变量申明提升
  3. let可以在{}内声明块级作用域,变量或者函数只在该区域才生效

    1
    2
    3
    4
    5
    6
    {
    //该区域为暂存死区

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

    块级作用域相当于闭包形成的局部作用域

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    for (var i = 0; i < 5; i++) {
    (function (i) {
    setTimeout(function (i) {
    console.log(i);
    });
    })(i);
    }
    for (let i = 0; i < 5; i++) {
    setTimeout(function (i) {
    console.log(i);
    });
    }
实现选项卡功能的三种方式
  1. btns[i].index = i;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    var btns = document.querySelectorAll('input');
    var divs = document.querySelectorAll('div');

    for (var i = 0; i < divs.length; i++) {
    btns[i].index = i;
    btns[i].onclick = function () {
    for (var j = 0; j < divs.length; j++) {
    btns[j].className = '';
    divs[j].className = '';
    }
    divs[this.index].className = 'show';
    this.className = 'active';
    }
    }
  2. 使用闭包

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    for (var i = 0; i < divs.length; i++) {
    (function (i) {
    btns[i].onclick = function () {
    for (var j = 0; j < divs.length; j++) {
    btns[j].className = '';
    divs[j].className = '';
    }
    divs[i].className = 'show';
    this.className = 'active';
    }
    })(i);
    }
  3. 使用let

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    for (let i = 0; i < divs.length; i++) {
    btns[i].onclick = function () {
    for (var j = 0; j < divs.length; j++) {
    btns[j].className = '';
    divs[j].className = '';
    }
    divs[i].className = 'show';
    this.className = 'active';
    }
    }

const

  • 使用const定义常量,常量在定义之后不可以修改,必须给初始值

    1
    2
    3
    const a = 1;
    a = 2;
    console.log(a);//Uncaught TypeError: Assignment to constant variable
  • 如果常量的属性是一个对象,那么对象的属性是可以修改的

    1
    2
    3
    4
    5
    const a = {
    name:'hello'
    };
    a.name = 'world';
    console.log(a.name);//world

变量的解构赋值

解构赋值:ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

  • 数组的解构赋值:按照对应的顺序解构。

    1
    var [a, [b, c]] = [1, [2, 3]];
  • 对象的解构赋值: 按照名字一一对应

    1
    2
    3
    4
    5
    6
    7
    var obj = {
    foo: function () {},
    o: {},
    arr: [],
    str: 'abc'
    };
    var {foo, arr, str} = obj;

字符串扩展

  • str.repeat(10)把str复制10次
  • 模板字符串

    1
    2
    var name ='leo',age = 39;
    var str = `你的名字是:${name}你的年龄是:${age}`;
  • str.includes(要查找的字符串, 起始位置 )返回布尔值,表示是否找到了参数字符串

  • str.startWith(要查找的字符串, 起始位置),表示参数字符串是否在源字符串的头部
  • str.endWith(要查找的字符串, 起始位置),表示参数字符串是否在源字符串的尾部

数值扩展

  • Math.trunc(num),表示去掉小数点
  • Math.sign(-0),判断参数是正数、负数、正0还是负0
  • Math.hypot(3,4),返回所有参数的平方和的平方根(勾股定理)

数组扩展

  • Array.from(字符串|类数组),把字符串或者类数组转成真正的数组.
  • Array.of(1,2,3,4,5);,把参数转为数组.解决new Array(5)只有一个参数时,参数其参数为length的问题.
  • arr.find(function(value,index,arr){}),它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined。

    1
    [1, 2, 3, 4, 5].arr.find((value, index) => value > 3);//4
  • arr.findIndex(function(){}),数组实例的findIndex方法的用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。

    1
    2
    3
    [1, 5, 10, 15].findIndex(function(value, index, arr) {
    return value > 9;
    }) // 2
  • arr.fill(填充内容,开始位置,结束为止),替换选中的内容

    1
    [1, 2, 3, 4, 5].fill(6,2,4);// [1, 2, 6, 6, 5]
  • for...of,用于遍历键值, 而for...in用于遍历键名,一个数据结构只要部署了Symbol.iterator属性,就被视为具有iterator接口,就可以用for…of循环遍历它的成员。

    1
    2
    3
    4
    5
    6
    var arr = [1, 2, 3, 4, 5];
    var str = 'hello';
    var obj = {a: 1, b: 2, c: 3};
    for (var value of arr)console.log(value);//1,2,3,4,5
    for (var value of str)console.log(value);//h,e,l,l,o
    for (var value of obj)console.log(value);//Uncaught TypeError: obj[Symbol.iterator] is not a function
    • arr.keys(),用于对数组键名的遍历

      1
      2
      3
      4
      var arr = [1, 2, 3, 4, 5];
      for(let index of arr.keys()){
      console.log(index);//0,1,2,3,4
      }
    • arr.values(),用于对数组键值的遍历(默认)

      1
      2
      3
      4
      var arr = [1, 2, 3, 4, 5];
      for(let value of arr.values()){
      console.log(index);//1,2,3,4,5
      }
    • arr.entries(),用于对数组键值对的遍历

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      var arr = [1, 2, 3, 4, 5];
      for (var [key,value] of arr.entries()) {
      console.log(key, value);
      /*
      * 0 1
      * 1 2
      * 2 3
      * 3 4
      * 4 5
      * */
      }
  • 数组推导: 通过现有数组生成新数组

    1
    2
    3
    4
    5
    var arr = [1, 2, 3, 4, 5];
    var arr1 = [for(value of arr) value * 2 ];
    console.log(arr1);// [2, 4, 6, 8, 10]
    var arr2 = [for(value of arr)if(value > 3) value * 2 ];
    console.log(arr2);// [8, 10]

对象的扩展

  • 属性的简洁表示法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function fn(x, y) {
    x++;
    y++;
    /*return {
    x: x,
    y: y
    }*/
    return {
    x,
    y
    }
    }
    console.log(fn(1, 2));//Object {x: 2, y: 3}
  • 对象内方法的简洁表示

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var obj = {
    name:'momo',
    /*showName:function(){
    return this.name;
    }*/
    showName(){
    return this.name;
    }
    };
    console.log(obj.showName());
  • 属性名表达式: 用表达式作为对象的属性名, 把表达式放在方括号内.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var person = {
    name:'momo',
    [sex]:false,
    ['get'+'name'](){
    return this.name;
    }
    };
    console.log(person.getname());
    console.log(person[sex])
  • Object.is(a,b),用来判断两个值是否相等

    1
    2
    3
    4
    0===-0;//true
    Object.is(0, -0);//false
    NaN===NaN;//false
    Object.is(NaN,NaN);//true
  • Object.assign(target,source1,source2,...),将source对象的可枚举属性赋值到target对象上。注意:如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var obj1 = {};
    var obj2 = {
    name: 'zMouse'
    };
    var obj3 = {
    name: 'duoduo',
    age: 34
    };
    Object.assign(obj1, obj2, obj3);
    console.log(obj1);
  • Object.getPrototypeOf(object),用来获取一个对象的prototype对象

    1
    2
    3
    4
    5
    6
    7
    8
    var Cat = function(name){
    this.name = name;
    };
    Cat.prototype.showname = function(){
    return this.name;
    };
    var c1 = new Cat('momo');
    Object.getPrototypeOf(c1);
  • Object.setPrototypeOf(object,prototype),用来设置一个对象的prototype对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var Cat = function(name){
    this.name = name;
    };
    Cat.prototype.showname = function(){
    return this.name;
    };
    var Person = function(){
    };
    Person.prototype.dadoudou = function(){
    };
    var c1 = new Cat('momo');
    Object.setPrototypeOf(c1, Person.prototype);
    console.log(Object.getPrototypeOf(c1))
  • proxy,提供了一种机制,可以对外界的访问进行过滤和改写

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    var obj = {
    a: 1,
    b: 2
    };
    var p1 = new Proxy(obj, {
    get(obj, attr){ //当属性访问时触发
    return obj[attr];
    },
    set(obj, attr, value){ // 当属性修改时触发
    if (value < 10) {
    obj[attr] = value;
    }
    }
    });
    p1.a = 5;
    console.log(p1.a); // 5
    console.log(obj.a); // 5
    p1.b = 11;
    console.log(p1.b); // 2
    console.log(obj.b); // 2

函数扩展

函数参数的默认值,定义默认值的参数必须是尾参数,因为定义默认值之后该参数可忽略

1
2
3
4
function fn(a,b=2) {
return {a, b};
}
console.log(fn(1))//{a: 1, b: 2}

rest参数,用于获取函数的多余参数,rest为参数

1
2
3
4
function fn(a, b, ...re) {
console.log(re)
}
fn(1, 2, 3, 4, 5, 6, 7, 8, 9);

扩展运算符...,可以将数组或字符串转换为参数序列

  • 获取最大值

    1
    2
    3
    var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    Math.max.apply(null, arr);
    Math.max(...arr); // ... 的作用是将arr的[]去掉
  • 将字符串拆分

    1
    2
    3
    var str = 'hello';
    var arr = [...str];
    console.log(arr);// ["h", "e", "l", "l", "o"]

箭头函数() => {}

用来作为回掉函数使用

1
2
var f = a => a + 1;
console.log(f(1));//2
  • 注意:

    1. 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

    2. 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

    3. 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。

    4. 不可以使用yield命令,因此箭头函数不能用作Generator函数。

数据结构

Set

Set是一个构造函数,可以传入一个数组或类数组初始化默认值

1
2
3
4
5
6
7
var set = new Set([1, 2, 3, 4, 5, 6, 6, 6, 6]);
console.log(set);//1,2,3,4,5,6
set.size;//6
set.add(7); //1,2,3,4,5,6,7
set.delete(7); //true
set.has(7); //false
set.clear();

其成员不可以重复,所以可以用set去重

set常用的方法
  • set.size:成员的个数,相当于数组的长度
  • set.add(value),为Set的实例添加值
  • set.delete(value),删除Set实例的值
  • set.has(value),判断传入的参数是否为set的成员
  • set.clear(),清除set中所有的成员

Map

它类似于对象,也是键值对的集合,各种类型的值(包括对象)都可以当作键。Map接受一个数组作为参数,该数组的成员是一个一个表示键值对的数组。

1
2
3
4
5
var map = new Map([['xiaohong', 80], ['lisi', 78], ['wangwu', 56]]);
//Map{"xiaohong" => 80, "lisi" => 78, "wangwu" => 56}
map.size;//3
map.set('xiaobai',38);//Map {"xiaohong" => 80, "lisi" => 78, "wangwu" => 56, "xiaobai" => 38}
map.get('xiaobai');//38

Map常用的方法
  • map.size:成员的个数,相当于数组的长度
  • map.set(key,value):添加新键值对
  • map.get(key):通过key获取value
  • map.delete(key):删除map实例的值
  • map.has(key):判断传入的参数是否为map的成员
  • map.clear():清除map中所有的成员
Map的遍历
  • forEach

    1
    2
    3
    4
    5
    6
    7
    8
    map.forEach(function () {
    console.log(arguments);
    });
    /*
    [80, "xiaohong", Map]
    [78, "lisi", Map]
    [56, "wangwu", Map]
    */
  • for of

    1
    2
    3
    4
    5
    6
    7
    8
    for (var i of map) {
    console.log(i)
    }
    /*
    ["xiaohong", 80]
    ["xiaohong", 80]
    ["wangwu", 56]
    */
    • map.keys():遍历map的key值

      1
      2
      3
      4
      5
      6
      7
      8
      for (var i of map.keys()) {
      console.log(i)
      }
      /*
      iaohong
      xiaohong
      wangwu
      */
    • map.values():遍历map的value值

      1
      2
      3
      4
      5
      6
      7
      8
      for (var i of map.values()) {
      console.log(i)
      }
      /*
      80
      78
      56
      */
    • map.entries():遍历map的key和value值

      1
      2
      3
      4
      5
      6
      7
      8
      for (var [key,value] of map.entries()) {
      console.log(key,value)
      }
      /*
      xiaohong 80
      lisi 78
      wangwu 56
      */

Iterator和Symbol

Symbol

ES6引入了一种新的原始数据类型Symbol,表示一个独一无二的ID.它通过Symbol函数生成.

1
2
3
4
5
6
7
var s = Symbol();
console.log(s);//Symbol()
typeof s;//"symbol"
//独一无二
var s1 = Symbol('test');
var s2 = Symbol('test');
s1===s2;//false

Iterrator

遍历接口:必须部署一个iterator方法,该方法部署在一个键名为Symbol.iterator的属性上,对应的键值是一个函数,该函数返回一个遍历器对象

  1. 在Object上部署接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    Object.prototype[Symbol.iterator] = function () {
    var keys = Object.keys(this);
    var _this = this;
    var index = 0;
    return {
    next(){
    if (index < keys.length) {
    return {
    value: _this[keys[index++]], done: false
    }
    } else {
    return {
    value: undefined, done: true
    }
    }
    }
    }
    };
  2. 然后可以使用 for of 遍历value

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var obj = {
    a: 1,
    b: 2,
    c: 3,
    d: 4
    };
    for (var value of obj) {
    console.log(value);
    }
    /*
    1
    2
    3
    4
    */

Generator函数

可以理解为函数内部状态的遍历器,每调用一次,函数顶走势状态发生一次改变,执行Generator函数会返回一个遍历器对象.

  • 两个特征
    1. function关键字与函数名之间有一个星号
    2. 函数体内部使用yield语句,定义不同的内部状态
1
2
3
4
5
6
7
8
9
10
function* fn() {
yield 1;
yield 2;
return 'ending';
}
var f = fn();
console.log(f.next());//Object {value: 1, done: false}
console.log(f.next());//Object {value: 1, done: false}
console.log(f.next());//Object {value: ending, done: true}
console.log(f.next());//Object {value: undefined, done: true}

Promise

作用是可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数

Promise基本用法

1
new Promise(function (resolve, reject) {}).then(function () {}, function () {}).catch()

Promise案例

  • 使用回掉函数

    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
    29
    30
    31
    32
    33
    var ball1 = document.querySelector('.ball1');
    var ball2 = document.querySelector('.ball2');
    var ball3 = document.querySelector('.ball3');
    function animate(ball, distance, cb) {
    setTimeout(function () {
    var marginLeft = parseInt(ball.style.marginLeft);
    if (marginLeft === distance) {
    cb && cb();
    } else {
    if (marginLeft < distance) {
    marginLeft++;
    } else {
    marginLeft--;
    }
    ball.style.marginLeft = marginLeft + 'px';
    animate(ball, distance, cb);
    }
    }, 13);
    }

    animate(ball1, 100, function () {
    animate(ball2, 200, function () {
    animate(ball3, 300, function () {
    animate(ball3, 150, function () {
    animate(ball2, 150, function () {
    animate(ball1, 150, function () {

    })
    })
    })
    })
    })
    })
  • 使用promise

    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    function promiseAnimate(ball, distance) {
    return new Promise(function (resolve, reject) {
    function _animate() {
    setTimeout(function () {
    var marginLeft = parseInt(ball.style.marginLeft);
    if (marginLeft === distance) {
    resolve();
    } else {
    if (marginLeft < distance) {
    marginLeft++;
    } else {
    marginLeft--;
    }
    ball.style.marginLeft = marginLeft + 'px';
    _animate();
    }
    }, 13);
    }

    _animate();
    });
    }
    promiseAnimate(ball1, 100)
    .then(function () {
    return promiseAnimate(ball2, 200)
    })
    .then(function () {
    return promiseAnimate(ball3, 300)
    })
    .then(function () {
    return promiseAnimate(ball1, 300)
    })
    .then(function () {
    return promiseAnimate(ball2, 300)
    })
    .then(function () {
    return promiseAnimate(ball3, 300)
    });

Promise.all

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 var p1 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve();
console.log('p1');
}, 40);
});
var p2 = new Promise(function (resolve, reject) {
setTimeout(function () {
reject();
console.log('p2');
}, 400);
});
var p3 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve();
console.log('p3');
}, 1000);
});
var p4 = Promise.all([p1, p2, p3]);
p4.then(function () {
console.log('成功');
}, function () {
console.log('失败');
})
  • p4的状态由p1、p2、p3决定,分成两种情况。
    1. 只有p1、p2、p3的状态都变成resolve,p的状态才会变成resolve,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
    2. 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

Promise.race

1
2
3
4
5
6
var p4 = Promise.race([p1, p2, p3]);
p4.then(function () {
console.log('成功');
}, function () {
console.log('失败');
})
  • p4的状态由p1、p2、p3决定,分成两种情况。
    1. 只要p1、p2、p3中一个的状态变成resolve,p4的状态就变成resolve
    2. 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p4的回调函数。

class

定义类

  • ES6以前定义类的方法

    1
    2
    3
    4
    5
    6
    7
    function Cat(name) {
    this.name = name;
    }
    Cat.prototype.getName=function () {
    return this.name;
    }
    var cat1 = new Cat('momo');
  • 使用class定义类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     class Cat {
    constructor(name) {
    this.name = name;
    }

    getName() {
    return this.name;
    }
    }
    var cat1 = new Cat('momo');

继承

  • ES6以前方法的继承

    1
    2
    3
    4
    5
    function Dog(name, age) {
    Cat.apply(this, arguments);
    }
    Dog.prototype = new Cat();
    Dog.prototype.constructor = Dog;
  • ES6的继承

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Dog extends Cat {
    constructor(name, age) {
    //如果需要继承的参数很多,可以使用...rest参数发放
    // constructor(age,name,...rests)--super(...rests)
    super(name);
    this.age = age;
    }
    getAge() {
    return this.age;
    }
    }
    var dog1 = new Dog('maomao', 12);
    console.log(dog1.getName());//maomao

Module