let关键字

特点var关键字let关键字
变量提升×
作用域没有块级作用域,是函数作用域有块级作用域
重复声明×
重新赋值
  1. 变量提升

    1
    2
    console.log(age);
    let age = 38;

    image-20200701114547150

  2. 作用域

    1
    2
    3
    4
    5
    for (var i = 0; i < 10; i++) {}
    console.log(i);

    for (let n = 0; i < 10; i++) {}
    console.log(n);

    image-20200701114808765

    图中可对比看出,如果用var声明,在循环外部还是可以使用i变量;但用let声明变量,循环外部不可以使用n变量

  3. 不可重复声明

    1
    2
    3
    let num2 = 10;
    let num2 = 20;
    console.log("num2: ", num2);

    image-20200701115104294

  4. 重新赋值

    1
    2
    3
    let num2 = 10;
    num2 = 20;
    console.log("num2: ", num2);

    image-20200701115202044

const关键字

使用场景

  1. 一些不会变化的值,比如圆周率PI
  2. 大事件项目中,保存基地址
  1. 没有变量提升

    image-20200701115648469

  2. 有块级作用域

    image-20200701115756085

  3. 不能重复声明

    image-20200701115830566

  4. 不能重新赋值(声明必须要初始化)

    image-20200701115846798

解构赋值

对象解构

取对象中属性的值,赋值给变量。

例如对于如下对象来说,在ES5与ES6中将对象赋值于变量的方式

1
2
3
4
5
6
let obj = {
name: "波波",
age: 38,
gender: "男",
score: 88,
};

ES5中的写法

1
2
3
4
5
let name1 = obj.name;
let age1 = obj.age;
let gender1 = obj.gender;
let score1 = obj.score;
console.log(name1, age1, gender1, score1);

ES6中的写法

  1. 定义变量名

    1
    2
    let { name: name2, age: age2, gender: gender2, score: score2 } = obj;
    console.log(name2, age2, gender2, score2);
  2. 变量名可与属性名一致

    1
    2
    let { name: name, age: age, gender: gender, score: score } = obj;
    console.log(name, age, gender, score);
  3. 当变量名与属性名一致时,可以省略变量名

    1
    2
    let { name, age, gender, score } = obj;
    console.log(name, age, gender, score);

以上代码的输出结果都为下图所示

image-20200701153427629

当简写时,对象中没有的属性会赋值为undefined

1
2
3
4
5
6
7
8
let obj = {
name: "波波",
age: 38,
gender: "男",
score: 88,
};
let { name, age, gender, fenshu } = obj;
console.log(name, age, gender, fenshu);

image-20200701153747123

简写与全写可以一起用

1
2
let { name, age, gender, score: fenshu } = obj;
console.log(name, age, gender, fenshu);

image-20200701153937328

设置默认值。当对象中没有此属性时会赋值为默认值而不是undefined。如果对象中存在这个属性,那么将赋值为对象中的属性,而不是默认值。

1
2
let { name, age, gender, score: fenshu, height = 180 } = obj;
console.log(name, age, gender, fenshu, height);

image-20200701154223592

赋值一个除了某个属性不存在,但存在其余属性的对象

1
2
3
4
5
6
7
8
9
10
let obj = {
name: "波波",
age: 38,
gender: "男",
score: 100,
};

// obj2相当于是obj对象里面除了name属性之外的属性组成的一个对象
let { name, ...obj2 } = obj;
console.log(obj2); // { age: 38, gender: '男', score: 100 }

image-20200702092507243

数组解构

把数组中每一个元素的值依次的赋值给变量。声明如下数组:

1
2
// 声明一个数组
let arr = [10, 20, 30, 40];

ES5中的写法

1
2
3
4
5
let num1 = arr[0];
let num2 = arr[1];
let num3 = arr[2];
let num4 = arr[3];
console.log(num1, num2, num3, num4);

ES6中的写法

  1. 基础写法–一一对应

    1
    2
    let [num1, num2, num3, num4] = arr;
    console.log(num1, num2, num3, num4);

    image-20200701155309108

  2. 默认值与没有值时与对象解构一致。

    1
    2
    3
    let [num1, num2, num3, num4, num5] = arr;
    console.log(num1, num2, num3, num4, num5); // num5为undefined

    1
    2
    let [num1, num2, num3, num4, num5=5] = arr;
    console.log(num1, num2, num3, num4, num5); // num5为5

解构赋值结合函数声明

ES5中的写法

1
2
3
4
5
6
7
8
function test1(obj) {
console.log(obj.name, obj.age, obj.gender);
}
test1({
name: "波波",
age: 38,
gender: "男",
});

ES6中的写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function test2({ name, age, gender, height = 180 }) {
console.log(name, age, gender, height);
}
test2({
name: "波波",
age: 38,
gender: "男",
});
test2({
name: "波波",
age: 38,
gender: "男",
height: 160,
});

image-20200701160704150

箭头函数

简单来说,箭头函数就是匿名函数的一个简写。

1
2
3
4
5
6
7
8
9
10
// 1. 普通的匿名函数
let fn = function (name) {
console.log("my name is ", name);
};
fn("波波");

// 2. 箭头函数
let fn1 = (name) => console.log("my name is ", name);
fn1("波波");

image-20200701161344962

简写规则:

  1. function改成=>=>可以读成goes to

  2. 如果只有一个形参,那就可以省略形参小括号

  3. 如果不是一个形参(0个或多个),那就不能省略形参小括号

  4. 如果函数体只有一句话,那就可以省略函数体的大括号

  5. 如果函数体只有一句话,并且这一句话是return返回值,那return也要省略

    1
    2
    3
    4
    let fn1 = function (name) {
    return name + "你好吗?";
    };
    let fn1 = (name) => name + "你好吗?";
  6. 如果函数体不是一句话,那就不能省略这个大括号

1
2
3
4
5
6
7
8
9
let fn2 = function (num1, num2) {
console.log(num1 + num2);
return num1 + num2 + 30;
};

let fn2 = (num1, num2) => {
console.log(num1 + num2);
return num1 + num2 + 30;
};
  1. 无参数,一句话

    1
    2
    3
    4
    let fn1 = function () {
    console.log("你好吗");
    };
    let f1 = () => console.log("你好吗");
  2. 一个参数,一句话

    1
    2
    3
    4
    let fn2 = function (name) {
    console.log(name + "你好吗");
    };
    let fn2 = (name) => console.log(name + "你好吗");
  3. 两个参数,一句话

    1
    2
    3
    4
    let fn3 = function (name, age) {
    console.log(name + "你好吗,你的年龄是" + age);
    };
    let fn3 = (name, age) => console.log(name + "你好吗,你的年龄是" + age);
  4. 一个参数,一个return

    1
    2
    3
    4
    let fn4 = function (age) {
    return age + 10;
    };
    let fn4 = (age) => age + 10;
  5. 两个参数,多句

    1
    2
    3
    4
    5
    6
    7
    8
    let fn5 = function (name, age) {
    console.log(name + "你好吗");
    return age + 10;
    };
    let fn5 = (name, age) => {
    console.log(name + "你好吗");
    return age + 10;
    };

this指向

箭头函数的this由上下文环境决定,其原理就是将箭头函数的上下文this保存,在箭头函数内部使用这个被保存的this。使用注意:

  • 不是什么时候都使用箭头函数

  • 不要用new关键字调用箭头函数

    1
    2
    3
    4
    5
    var Fn = (name, age) => {
    this.name = name
    this.age = age
    }
    var obj = new Fn('伦哥', 10) // Fn is not a constructor

    箭头函数的this是由上下文环境决定,而不是new关键字来决定

1
2
3
4
5
6
7
8
9
10
11
12
var obj = {
name: '波波',
sayHi: function () {
console.log('我的名字是:', this.name) // 我的名字是: 波波
// 上文环境
setTimeout(() => {
console.log('我的名字是:', this.name) // 我的名字是: 波波
}, 2000)
// 下文环境
}
}
obj.sayHi()

当多层箭头函数套用时,那么里面的this指向都与最外层的this指向一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var obj = {
name: '波波',
sayHi: function () {
console.log('我的名字是1:', this.name)
// 上文环境
setTimeout(() => {
console.log('我的名字是2:', this.name)
setTimeout(() => {
console.log('我的名字是3:', this.name)
setTimeout(() => {
console.log('我的名字是4:', this.name)
}, 1000)
}, 1000)
}, 1000)
// 下文环境
}
}
obj.sayHi()

image-20200702094635888

对象成员简写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let name = "千里";
let age = 18;
let gender = "man";
let score = 10;

// es6
let obj = {
name,
age,
gender,
score,
sayHi() {
console.log("哈哈");
},
};
console.log(obj);
obj.sayHi();

image-20200701164157212

在这种写法中,如果传入一个没有赋值的变量,那么就会报错。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let name = "千里";
let age = 18;
let gender = "man";
let score = 10;

// es6
let obj = {
name,
age,
gender,
score,
// fenshu, // 会发生报错,因为外部没有此变量,可以修改为下面的写法
fenshu:score,
sayHi() {
console.log("哈哈");
},
};
console.log(obj);
obj.sayHi();

扩展(展开)运算符

对象展开

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
// 声明一个对象
let chinese = {
skin: "yellow",
hair: "black",
sayHi() {
console.log("Are you eat?");
},
};

let CXK = {
slill: "jump sing rap and play basketball",
song: "啊哈哈哈",
};
let linge = {
// skin: "yellow",
// hair: "black",
// sayHi() {
// console.log("Are you eat?");
// },
// slill: "jump sing rap and play basketball",
// song: "啊哈哈哈",
// 展开语法 等同于上方写法
...chinese,
...CXK,
};
console.log(linge);

image-20200701165348837

当新增属性时,直接添加即可。如果重新定义已经存在的,那么覆盖原来的。

1
2
3
4
5
6
let linge = {
...chinese,
...CXK,
gender: "Man",
hair: "白发苍苍",
};

image-20200701165728791

数组展开

与对象展开类似。

1
2
3
4
let arr1 = [10, 20, 30];
let arr2 = [40, 50, 60];
let arr3 = [...arr1, ...arr2, 70];
console.log(arr3);

image-20200701170324837

使用场景:

  1. 数组的拼接

  2. 求最大/小值

    1
    2
    3
    let arr1 = [10, 23, 54, 446, 56, 2];
    let max = Math.max(...arr1);
    console.log(max);

数据类型set

作用和数组类型,和数组不同的是set不能存放重复的元素。

  1. 基本使用

    1
    2
    let set1 = new Set([10, 20, 30, 40, 10, 20, 30, 40, 50]);
    console.log(set1);

    image-20200701170935727

  2. 数组去重

    1
    2
    3
    4
    let arr = [10, 20, 30, 10, 20, 30, 20, 10, 33, 200];
    let set = new Set(arr);
    let arrNew = [...set];
    console.log(arrNew);

    image-20200701171115524

    也可以改写为如下:

    1
    2
    3
    let arr = [10, 20, 30, 10, 20, 30, 20, 10, 33, 200];
    let arrNew = [...new Set(arr)];
    console.log(arrNew);

模板字符串

模板字符串会保留原样字符串格式,以及可以占位。其语法为反引号``

1
2
3
4
5
6
7
8
let author = "波波";
let str1 = `
静夜思
${author}
哈哈哈
`;
console.log(str1);

image-20200701171652048

1
2
3
4
5
6
let name = "xiaokang";
let age = 12;
function test() {
return "test";
}
console.log(`my name is ${name} and age is ${age}. ${test()}`);

image-20200701172133560

补充数组的方法

  1. forEach

    无返回值

    1
    2
    3
    4
    5
    6
    let arr = [10, 20, 30, 40];
    arr.forEach(function (item, index) {
    // item 遍历出的每一项
    // index 遍历出来的每一项对应的索引
    console.log(item, index);
    });
  2. map

    有返回值。

    1
    2
    3
    4
    5
    6
    7
    8
    let arr = [10, 20, 30, 40];
    let arrNew = arr.map(function (item, index) {
    // item 遍历出的每一项
    // index 遍历出来的每一项对应的索引
    // console.log(item, index);
    return item * item;
    });
    console.log(arrNew);
  3. filter

    1
    2
    3
    4
    5
    6
    7
    let arr = [10, 20, 11, 21, 30, 31, 23, 43];
    let arrNew = arr.filter((item, index) => {
    console.log(item, index);
    // 如果条件成立,返回当前项
    return item % 2 == 0;
    });
    console.log(arrNew); //[ 10, 20, 30 ]

数组的其他应用

  1. 数组降维

    将二维数组降维为一维数组

    1
    2
    3
    4
    5
    6
    7
    // 将二维数组将为一维数组
    var arr = [[10, 20], [30, 40, 50], [60, 79, 80]]
    var arrNew = []
    arr.forEach(v => {
    arrNew.push(...v)
    })
    console.log(arrNew); // [10, 20, 30, 40, 50, 60, 79, 80]
  2. 数组的去重(排序法)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var arr = [10, 20, 30, 23, 4, 512, 20, 10];
    var arrNew = [];
    arr.sort((a, b) => {
    return a - b;
    });
    console.log(arr); // [4, 10, 10, 20, 20, 23, 30, 512];
    arr.forEach((v, i) => {
    if (v != arr[i + 1]) {
    arrNew.push(v);
    }
    });
    console.log(arrNew); // [ 4, 10, 20, 23, 30, 512 ]
  3. 数组去重(对象法)

    原理:利用对象属性不能同名。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 使用对象法
    var obj = {};
    var arrNew = [];
    // 遍历要去重的数组
    arrNew.forEach((v) => {
    if (obj[v] == undefined) {
    arrNew.push(v); // 不存在九江这个v存起来
    obj[v] = 1; // 随意写,作为属性的值(避免undefined)
    }
    });
  4. 数组升维

    假设从后端拿到的数据为如下格式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var arr = [
    { type: "电子产品", name: "iPhone", price: 8888 },
    { type: "家具", name: "桌子", price: 100 },
    { type: "食品", name: "瓜子", price: 10 },
    { type: "家具", name: "椅子", price: 380 },
    { type: "电子产品", name: "小米手机", price: 1380 },
    { type: "食品", name: "辣条", price: 5 },
    { type: "食品", name: "咖啡", price: 50 },
    ];

    第一种:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    var obj = {}; //将测type有没有重复的
    var arrNew = []; // 升级后的二维数组
    // 1. 将type去重,找出所有的产品类型
    // 遍历这个arr一维数组
    arr.forEach((v) => {
    if (obj[v.type] == undefined) {
    obj[v.type] = 1;
    // 把这个数组放到arrNew中
    arrNew.push({
    type: v.type,
    data: [v],
    });
    } else {
    // 判断当前v输入arrNew中的哪一类
    arrNew.forEach((v2, j) => {
    if (v.type == v2.type) {
    arrNew[j].data.push(v);
    }
    });
    }
    });
    console.log(arrNew);

    第二种:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    var obj = {}; //将测type有没有重复的
    var arrNew = []; // 升级后的二维数组
    var index = 0; // 用于记录索引
    arr.forEach((v) => {
    if (obj[v.type] == undefined) {
    obj[v.type] = index++;
    // 把这个数组放到arrNew中
    arrNew.push({
    type: v.type,
    data: [v],
    });
    } else {
    var _index = obj[v.type];
    arrNew[_index].data.push(v);
    }
    });
    console.log(arrNew);

    image-20200702112619895

babel将ES6代码转为ES5

https://www.babeljs.cn/