一、ES6中新增的let与var的区别:

1.用let声明变量的时候不可以重复声明,但是var可以。

1
2
3
4
5
let a=0;
let a=1; //会报错

var b=0;
var b=1; //不会报错

2.新增了块级作用域,可以只在代码块中起作用,外部访问不到。其他的还有全局作用域、函数作用域、eval与var保持一致。

1
2
3
4
{
let a=6;
}
console.log(a); //会报错

3.let不存在变量提升的特性,这点与var不同。

4.不影响作用域链。

二、Const常量

1.定义常量的时候一定要赋初始值

2.常量的变量名一般都要大写(习惯)

3.常量,顾名思义,它的值是不可更改的

4.与新增的let一样,也是块级作用域

5.如果定义数组或者对象为常量,对其元素进行修改则不会报错

原因:因为修改其中的元素并不会导致该数组或对象的地址发生改变,所以不会报错。

1
2
3
4
5
const TEAM = [1,2,3];
TEAM.push(4); //不会报错

//但是如果进行如下修改就会报错了
TEAM = 1//报错

三、数组和对象的解构赋值

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

1.数组的解构赋值

按照顺序进行一一对应进行赋值。

1
2
3
4
5
6
const F4 = ['小杰','小民','小蔡','小红'];
let [li,wang,cai,yu] = F4;
console.log(li); //小杰
console.log(wang); //小民
console.log(cai); //小蔡
console.log(yu); //小红

2.对象的解构赋值

按照属性名进行赋值。

1
2
3
4
5
6
7
8
9
10
11
12
13
const LI = {
name:'小杰',
age: 22,
apex: function(){
console.log('我是APEX猎杀');
}
};

let {name, age, apex} = LI;
console.log(name); //小杰
console.log(age); //22
console.log(apex); //f()={console.log(我是APEX猎杀)}
apex(); //我是APEX猎杀

四、新增的字符串字面量:``

1.新的字符串声明方式

1
2
let str1 = `我是新增的字符串字面量`;
console.log(str1, typeof str1); //我是新增的字符串字面量 String

2.内容中可以出现换行符,其他的不支持

1
2
3
4
5
6
let str2=`<ul>
<li>小红</li>
<li>小杰</li>
<li>小蔡</li>
<li>小民</li>
</ul>`;

3.变量拼接

在ES6之前的字符串拼接方法

1
2
3
var he = 'hello';
var name = he + '小蔡';
console.log(name); //hello小蔡

ES6新增拼接方法

1
2
3
let gun1 = `R301`;
let gun2 = `${gun1} R99`;
console.log(gun2); //R301 R99

五、简化对象写法

1.ES6之前的写法

1
2
3
4
5
6
7
8
let name = '小红';
let fn = function(){
console.log(123);
}
const SCHOOL = {
name: name,
fn: fn
}

2.ES6的简化写法

1
2
3
4
5
6
7
8
9
let name = '小红';
let fn = function(){
console.log(123);
}
//名字必须与之前的属性名一致
const SCHOOL= {
name,
fn
}

六、箭头函数

1.ES6允许使用箭头(=>)来定义函数

1
2
3
let fn = () => {
console.log(123)
}

2.箭头函数中的this是静态的,始终指向函数声明时所在作用域下的this的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 用之前的方法声明函数x1
function x1(){
console.log(this.name);
}
// 用箭头函数声明x2
let x2 = () => {
console.log(this.name);
}
// 在window下定义一个name
window.name = 'window';
const OBJ = {
name: 'this'
}
//直接调用
x1(); //window
x2(); //window
//使用call方法改变this指向之后调用
x1.call(OBJ); //this
x2.call(OBJ); //window

3.箭头函数不能作为构造函数实例化对象

1
2
3
4
5
6
let Person = (name, age) => {
this.name = name,
this.age = age
}
let me =new Pesron('xiaohong',22);
console.log(me); //Uncaught TypeError: Person is not a constructor

4.不能使用arguments变量

1
2
3
4
let fn = () => {
console.log(arguments);
}
fn(1,2,3) //Uncaught ReferenceError: arguments is not defined

5.箭头函数可以缩写

(1).省略小括号,当形参有且只有一个的时候

1
2
3
4
let add = n => {
return n+ n;
}
console.log(add(9)); //18

(2).省略花括号,代码里只有一条语句的时候,return也必须省略

1
2
let pow = (n) => n*n;
console.log(pow(8)); //64

6.箭头函数的一些应用场景

(1).点击id为ad的块,让其2s后变为粉色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let ad = document.geiElementById(ad);
ad.addEventListener('click', function(){
let that = this;
setTimeout(function(){
//因为计时器是属于window的方法,所以this指向window,但是window没有style这个属性,所以会报错
//所以需要用that来保存之前this的指向
that.style.background = 'pink'
}, 2000);
})
//使用箭头函数
ad.addEventListener('click', function(){
setTimeout(() => {
this.style.background = 'pink'
}, 2000);
})

(2).从数组中返回偶数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const ARR = [1,2,3,4];
//filter()函数是将给定数组中满足条件的元素返回到新的数组里
const RESULT = ARR.filter(function(item){
if(item % 2 === 0){
return true;
}
else{
return false;
}
});
console.log(RESULT); //[2,4]
//使用箭头函数来实现
const RESULT = ARR.filter(item => {
if(item % 2 === 0){
return true;
}
else{
return false;
}
})
const RESULT = ARR.filter(item => item % 2 === 0);
console.log(RESULT); //[2,4]

箭头函数适合与this无关的回调,定时器,数组的方法回调
不适合与this有关的回调,事件回调,对象的方法

七、ES6允许给函数参数赋初始值

1.给形参赋初始值

1
2
3
4
5
function add(a,b,c=10){
return a+b+c;
}
let result = add(1,2);
console.log(result); //13

2.可以与解构赋值结合使用

1
2
3
4
5
6
7
8
9
10
11
function connect({host="127.0.0.1", username, password, port}){
console.log(host);
console.log(username);
console.log(password);
console.log(port);
}
connect({
username: 'root',
password: 'root',
port: 3306
})

八、rest参数(用来替代无法在箭头函数中使用的arguments参数)

两者区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function data(){
console.log(arguments);
}
data(1,2,3); //Arguments(3)
// ES6获取实参的方法 rest参数
function data2(...args){
console.log(args);
}
data2(3,4,5);
// rest参数必须放到参数最后
function fn(a,b,...arg){
console.log(a);
console.log(b);
console.log(arg);
}
fn(1,2,3,4,5); //1 2 (3)[3,4,5]

九、扩展运算符…(能将数组转化为逗号分割开的参数序列)

1.数组的拼接

1
2
3
4
const APEX = ['狗子','G7人','命脉'];
const LOL = ['亚索','劫'];
const HB = [...APEX, ...LOL];
console.log(HB); //Array(5)['狗子','G7人','命脉','亚索','劫']

2.数组的克隆

1
2
3
4
const A = [666,777];
const CA = [...A];
console.log(CA); //Array(2)[666,777]
// 克隆只是一个浅拷贝(就是拷贝变量所存的值,如果是引用变量,拷贝的就是它里面的地址)

3.将伪数组转换为真正的数组

1
2
3
<div></div>
<div></div>
<div></div>
1
2
3
const DIVS = document.querySelectorAll('div');
const DIVARR = [...DIVS];
console.log(DIVARR); //Array(3)[div,div,div]

十、ES6引入了一种新的原始数据类型Symbol,表示独一无二的值,是JS中第七种数据类型

1.Symbol的特点

(1).Symbol的值是唯一的,用来解决命名冲突问题
(2).Symbol的值不能与其他数据进行运算
(3).Symbol给对象定义的属性不能使用for in进行遍历

2.创建Symbol

1
2
3
4
5
6
7
8
9
10
11
12
13
let s = Symbol();
console.log(s, typeof s); //Symbol() "symbol"

let s2 = Symbol('小红');
let s3 = Symbol('小红');
console.log(s2, typeof s2); //Symbol(小红) symbol
console.log(s2 === s3); //false,里面只是一个标志
// 使用Symbol.for创建
let s4 = Symbol.for('小红');
let s5 = Symbol.for('小红');
console.log(s4 === s5); //true

console.log(s4, typeof s4); //Symbol(小红) 'symbol'

3.使用场景

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
let game = {
up: 213
}

let methods = {
up: Symbol(),
down: Symbol()
};
// 安全的向game对象中添加一些属性
game[methods.up] = function(){
console.log('我可以改变形状');
}
game[methods.down] = function(){
console.log('我可以快速下降');
}

console.log(game);

let youxi = {
name: 'bf',
[Symbol('say')]: function(){
console.log('我可以说话');
},
[Symbol('sing')]: function(){
console.log('我可以唱歌');
}
}
console.log(youxi);

4.Symbol的内置值(可以当作属性使用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// hasInstance的特点,可以自己控制类型检测
class Person{
static [Symbol.hasInstance] (){
console.log('我被用来检测类型了');
return true; //在这个地方如果是true,下面instanceof就会返回true,反之一样
}
}
let o = {};
console.log(o instanceof Person);

const ARR = [1,2,3];
const ARR2 = [4,5,6];
// concat将两数组连接起来,该方法不会改变原有数组,只会返回一个新数组的副本
ARR2[Symbol.isConcatSpreadable] = false; //控制ARR2不可以展开
console.log(ARR.concat(ARR2)); //[1,2,3,Array(3)]

十一、迭代器(Iterator)

1.什么是迭代器

(1)迭代器是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署了Iterator接口(其实就是一个对象的属性),就可以完成遍历操作。
(2)ES6创造了一种新的遍历命令for…of循环,Iterator接口主要供for…of使用。
(3)原生具备Iterator接口的数据:
Array, Arguments, Set, Map, String, TypedArray, NodeList

2.for of 和 for in

1
2
3
4
5
6
7
8
9
const AR = ['M4','AK','MP7'];
// 使用for of遍历该数组
for(let v of AR){
console.log(v); //M4,AK,MP7
}
// 使用for in遍历数组
for(let w in AR){
console.log(w); //0,1,2
}

所以由此可知,使用for in的时候,w中保存的是下标,使用for of中,v保存的是值
迭代器的原理:
1.先创建一个指针对象,指向当前数据结构的起始位置。
2.第一次调用对象的next方法,指针自动指向数据结构的第一个成员。
3.接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员。
4.每调用next方法返回一个包含value和done属性的对象。
5.value就是值,done表示是否遍历完成,若为ture则表示已经全部遍历完了。

3.迭代器的应用:自定义迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const CLASS = {
name: '15',
stus: [1,2,3,4],
[Symbol.iterator](){
let index = 0;
let that = this;
return {
next: function(){
if(index < that.stus.length){
const result = {value:that.stus[index],done:false}
index++;
return result;
}
else{
return {value:undefined, done:true}
}
}
}
}
}
for(let x of CLASS){
console.log(x);
}

十二、生成器

生成器本身是一个函数,是ES6提供的一种异步编程解决方案

1.定义函数,在function和函数名之间加一个*

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
// yield可以看作代码的分割符,执行到yield就会暂停
function * gen(){
console.log(111);
yield '666';
console.log(222);
yield 'lll';
console.log(333);
yield 'hhhh'
console.log(444);
}
let iterator = gen();
// 需要调用next方法才能执行函数,且遇到yield就会暂停执行,再次调用next函数就会接着往下执行
iterator.next(); //111
iterator.next(); //222
iterator.next(); //333
iterator.next(); //444
for(let v of gen()){
console.log(v);
}
// 生成器函数参数
function * x(arg){
console.log(arg); //'AAA'
let one = yield 111;
console.log(one); //'BBB'
let two = yield 222;
console.log(two); //'CCC'
let three = yield 333;
console.log(three); //'DDD'
}

let iterator1 = x('AAA');
console.log(iterator1.next()); //这个不填参数,作为启动函数的操作
console.log(iterator1.next('BBB')); //参数作为第一个yield的返回值
console.log(iterator1.next('CCC')); //参数作为第二个yield的返回值
console.log(iterator1.next('DDD')); //参数作为第三个yield的返回值

2.生成器的函数实例:1s后控制台输出111,2s后输出222,3s后输出333

(1).使用回调函数,会造成回调地狱的现象

什么是回调地狱?
回调地狱会造成代码可复用性不强,可阅读性差,可维护性(迭代性差),扩展性差等等问题。

1
2
3
4
5
6
7
8
9
let timer = setTimeout(() => {
console.log(111);
setTimeout(() => {
console.log(222);
setTimeout(() => {
console.log(333);
}, 3000)
}, 2000);
}, 1000);

(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
function one(){
setTimeout(() => {
console.log(111);
iterator.next();
},1000);
}
function two(){
setTimeout(() => {
console.log(222);
iterator.next();
},2000);
}
function three(){
setTimeout(() => {
console.log(333);
iterator.next();
},3000);
}
function * gen(){
yield one();
yield two();
yield three();
}
let iterator = gen();
iterator.next();

十三、Promise

1.功能

(1)Promise是ES6引入的异步编程的新解决方案。
(2)语法上Promise是一个构造函数。
(3)用来封装异步操作并可以获取其成功或失败的结果。

2.声明一个Promise函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const p = new Promise(function(resolve, reject){    //参数的名字可以随便起
setTimeout(function(){
let data = '数据库中用户的数据';
// 数据调用成功调用resolve,然后会调用p.then中的第一个回调函数
// resolve(data);
// 数据读取失败调用reject,然后会调用p.then中的第二个回调函数
let err = '数据读取失败';
reject(err);
}, 1000)
})

// 调用Promise对象的then方法
p.then(function(value){
console.log(value);
}, function(reason){
console.log(err);
})

3.Promise.then

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
const p = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('用户数据');
// reject('出错了');
}, 1000);
})

// 调用then方法,then方法返回的结果是Promise对象,对象状态由回调函数的执行结果决定。
// 1.如果回调函数中返回的结果是非Promise属性类型,状态为成功。
// 2.如果回调函数中返回的结果是Promise属性类型,状态为返回的Promise的状态。
// 3.抛出错误,状态为出错。

const result = p.then(value => {
console.log(value);
// return 123; //非Promise对象,状态为成功
return new Promise((resolve, reject)=>{
// resolve('ok'); //Promise对象,状态为成功
// reject('error')' //Promise对象,状态为出错
throw new Error('出错啦'); //抛出错误,状态为出错
})
}, reason => {
console.warn(reason);
})

console.log(result);

// 也可以进行链式调用
p.then(value => {}, reason => {}).then(value => {}, reason=> {});

十四、集合与API

1.简介

(1)ES6提供了一种新的数据结构SET(集合)。类似于数组,但成员的值都是唯一的。
(2)集合实现了Iterator接口,所以可以使用扩展运算符和for of进行遍历。
(3)集合的属性和方法:
size 返回集合的元素个数
add 增加一个新元素,返回当前集合
delete 删除特定元素,返回boolean值
has 检测集合中是否包含某个元素,返回boolean值

2.声明集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let s = new Set();
let s2 = new Set([1,2,3,4,5,3,2]);
// 传入的数组会自动进行去重
console.log(s2); //1,2,3,4,5
// 返回去重后的元素个数
console.log(s2.size); //5
// 添加新的元素
s2.add(9);
console.log(s2); //1,2,3,4,5,9
// 删除特定元素
console.log(s2.delete(9)); //true
console.log(s2); //1,2,3,4,5
// 检测是否包含某个元素
console.log(s2.has(1)); //true
console.log(s2.ha2(10)); //false
// 清空集合
// s2.clear();
console.log(s2); //set(0) {size:0}

for(let v of s2){
console.log(v); //1 2 3 4 5
}

3.集合实践

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let arr = [1,2,3,5,6,8,8,4,5,1,2];
// 1.数组去重,因为result的结果不是数组,所以需要用到扩展运算符转化为数组

let result = [...new Set(arr)];
console.log(result); //Array(7)[1,2,3,4,5,7,8]

// 2.交集

let arr2 = [4,5,6,6];
let result = [...new Set(arr2)].filter(item => new Set(arr2).has(item));
console.log(result); //[4,5]

// 3.并集

let union = [...new Set([...arr, ...arr2])];
console.log(union); //[1,2,3,4,5,6,8]

// 4.差集

let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
console.log(diff); //[1,2,3,7,8]

十五、Map

1.Map简介

(1)ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值都可以当作键。
(2)Map也实现了iterator接口,所以可以使用扩展运算符和for of。
(3)属性和方法:
size 返回Map元素的个数
set 增加一个新元素,返回当前Map
get 返回键名对象的键值
has 检测Map中是否包含某个元素,返回boolean值
clear 清空集合,返回undefined

2.声明一个Map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let m = new Map();
// 添加元素
m.set('name','小红');
let key = {
school : 'GEO'
}
m.set(key, [1,2,3]);
console.log(m); //{Object => Array(3)} key:{school : 'GEO'}, value: [1,2,3]
// size
console.log(m.size); //2
// 删除元素
m.delete('name');
console.log(m);
// 获取特定元素
console.log(m.get(key)); //[1,2,3]
// 清空Map
// m.clear()
// 遍历
for(let v of m){
console.log(v);
}

十六、Class

1.简介

(1)ES6提供了更接近传统语言的写法,引入了Class(类)这个概念。
(2)作为对象的模板,通过Class关键字,可以定义为类。
(3)它的绝大部分功能ES5都可以做到,新的写法只是让原型写法更加清晰。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ES5的构造方法
function Phone(brand, price){
this.brand = brand;
this,price = price;
}

// 添加方法
Phone.prototype.call = function(){
console.log('我可以打电话');
}
// 实例化对象
let Huawei = new Phone('华为', 5999);
Huawei.call(); //我可以打电话
console.log(Huawei); //brand:华为 price: 5999
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Class
class Phone{
// 构造方法名字是固定的不能更改
constrctor(brand, price){
this.brand = brand;
this.price = price;
}

// 添加方法必须使用该语法,不能使用ES5的对象完整形式
call(){
console.log('我可以打电话');
}
}

let OnePlus = new Phone('1+', 1999);
console.log(OnePlus); //brand:'1+' price: 1999

2.Class的静态成员

(1).ES5中

1
2
3
4
5
6
7
8
9
10
11
12
function(){

}

Phone.name = '手机';
Phone.change = function(){
console.log('666');
}
Phone.prototype.size = '6';
let nokia = new Phone();
console.log(nokia.name); //undefined,说明实例对象没有构造函数对象上的属性
console.log(nokia.size); //6,可以读取到原型对象上的属性和方法

(2).Class的静态对象

1
2
3
4
5
6
7
8
9
10
Class Phone(){
static name = '手机';
static change(){
console.log('666');
}
}

let nokia = new Phone();
console.log(nokia.name); //undefined,如果去掉static就是手机
console.log(Phone.name); //手机

十七、构造函数继承

1.ES5使用构造函数继承

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
function Phone(brand, price){
this.brand = brand;
this.price = price;
}

Phone.prototype.call = function(){
console.log('我可以打电话');
}

function SmartPhone(brand, price, color, size){
Phone.call(this, brand, price);
this.color = color;
this.size = size;
}

// 设置子集构造函数的原型
SmartPhone.prototype = new Phone;
SmartPhone.prototype.constructor = SmartPhone;

// 声明子类的方法
SmartPhone.prototype.photo = function(){
console.log('我可以拍照');
}
SmartPhone.prototype.play = function(){
console.log('我可以玩游戏');
}

const chuizi = new SmartPhone('锤子', 2499, '黑色', 5.5)
console.log(chuizi);

2.ES6使用类进行继承

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
class Phone{
constructor(brand, price){
this.brand = brand;
this.price = price;
}

// 父类的成员属性
call(){
console.log('我可以打电话');
}
}

class SmartPhone extends Phone {
// 子类的构造方法
constructor(brand, price, color, size){
super(brand, price); //Phone.call(this, brand, price)
this.color = color;
this.size = size;
}

photo(){
console.log('我可以拍照');
}
play(){
console.log('我可以玩游戏');
}
// 子类对父类方法的重写(覆盖)
call(){
console.log('我可以进行视频通话');
}
}

const xiaomi = new SmartPhone('小米', 799, '黑色', 8);
console.log(xiaomi);
xiaomi.call(); //我可以进行视频通话

十八、Class中的get和set

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// get和set
class Phone{
get price(){ //只要读取了price属性,就会执行这里面的代码
console.log('价格属性被读取了');
return '666';
}

set price(newVal){ //只要修改了price属性,就会执行这里面的代码
console.log('价格属性被修改了');
}
}

// 实例化对象
let s = new Phone();
console.log(s.price); //价格属性被读取了 /n 666
s.price = 'free'; //价格属性被修改了

十九、数值扩展

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
39
40
41
42
43
44
// 1.Number.EPSILON是JS表示的最小精度
// EPSILON属性的值接近于2.2204460492503130808472633361816E-16
console.log(0.1 + 0.2 === 0.3); //false,因为浮点数运算不准确,所以需要如下调整
function equal(a,b){
if(Math.abs(a-b) < Number.EPSILON){
return true;
}
else{
return false;
}
}
console.log(equal(0.1+0.2,0.3)); //true

// 2.二进制(0b开头)和八进制(0o开头)和十六进制(0x开头)
let b =0b1010;
console.log(b); //10
let o =0o777;
console.log(o); //511
let x = 0xff;
console.log(x); //255

// 3.Number.isFinite,检测一个数值是否为有限数
console.log(Number.isFinite(100)); //true
console.log(Number.isFinite(100/0)); //false

// 4.Number.isNaN,检测一个数值是否为NaN
console.log(Number.isNaN(123)); //false

// 5.Number.parseInt Number.parseFloat字符串转整数、浮点数
console.log(Number.parseInt('531dawd')); //531
console.log(Number.parseFloat('3.152135asd')); //3.152135

// 6.Number.isInteger判断一个数是否为整数
console.log(Number.isInteger(5)); //true
console.log(Number.isInteger(2.5)); //false

// 7.Math.trunc将数字的小数部分抹掉
console.log(Math.trunc(3.5)); //3

// 8.Math.sign检测一个数是正负数
console.log(Math.sign(100)); //1 代表正数
console.log(Math.sign(-10)); //-1 代表负数
console.log(Math.sign(0)); //0 代表0
console.log(Math.sign(-0)); //-0

二十、ES6对象方法扩展

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
// 1.Object.is  判断两个值是否完全相等
console.log(Object.is(120, 121)); //false
// 区别于 ===
console.log(Object.is(NaN, NaN)); //true
console.log(NaN === NaN); //false

// 2.Object.assign 对象的合并
const config1 = {
host: 'localhost',
port: 3306,
name: 'root',
pass: 'root',
test: 'test'
}
const config2 = {
host: 'http://atguigu.com',
port: 33060,
name: 'atguigu.com',
pass: '666'
}

// config2会将config1的重名属性覆盖掉,不重名的则保留
console.log(Object.assign(config1, config2));

// 3.Object.setPrototypeOf 设置原型对象
const school = {
name: '尚硅谷'
}
const cities = {
xiaoqu: ['北京','上海','深圳']
}
Object.setPrototypeOf(school,cities);
console.log(school);

33行控制台运行结果

二十一、模块化

1.模块化是将一个很大的程序文件,拆分成许多小的文件(即模块),然后再将小文件组合起来

(1).模块化的好处

Ⅰ.防止命名冲突
Ⅱ.提高代码复用性
Ⅲ.高维护性

(2).ES6模块化语法

Ⅰ.模块功能主要由两个命令组成:export和import
Ⅱ.export命令用于规定模块的对外接口
Ⅲ.import命令用于输入其他模块提供的功能

2.模块使用方式

外部模块文件m1.js

1
2
3
4
5
// 分别暴露
export let school = '尚硅谷';
export function teach(){
console.log('我们可以教给你开发技能');
}

外部模块文件m2.js

1
2
3
4
5
6
7
// 统一暴露
let school = '小红';
function findjob(){
console.log('我们可以帮你找工作');
}

export {school, findjob};

外部模块文件m3.js

1
2
3
4
5
6
7
// 默认暴露
export default {
name: '晓杰',
change: function(){
console.log('我们可以');
}
}

调用模块的主程序文件

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
// script type="module"
// 1.通用的导入方式
// 引入m1.js的模块,分别暴露
import * as m1 from "./m1.js";
console.log(m1);
m1.teach();

// 引入m2.js模块的内容,统一暴露
import * as m2 from "./m2.js";
console.log(m2);
console.log(m2.school);

// 引入m3.js模块的内容,默认暴露
import * as m3 from "./m3.js";
console.log(m3);
console.log(m3.default.name);

2.解构赋值形式导入
import {school, teach} from "./m1.js";
// 因为重名了,所以需要用as起一个别名
import {school as SC, findjob} from "./m2.js";
import {default as m3} from "./m3.js";
console.log(school);
console.log(SC);
console.log(teach);
console.log(m3);

3.简便形式 针对默认暴露
import m3 from "./m3.js";
console.log(m3);

分别暴露的控制台输出内容