16.Set 数据集合
学习要点:
1.Set 数据集合
本节课我们来开始学习 ES6 新增的 Set 数据集合的用法;
一.Set 数据集合
1.ES6 之前只有数组一种数据结构,而现在提供了 Set 和 Map 两种集合;
严格来说,对象不算是一种数据结构
先来打印看看它是什么
let set = new Set();
console.log(set);
2.Set 集合是一种无重复元素的列表,使用 new Set()方法创建 Set 集合
//创建一个 Set 集合
let set = new Set();
set.add(1);
set.add(2);//这两个合并成一个了
set.add(2);
set.add('2');
set.add('c');
console.log(set); //Set {1,2,'2','c'}
console.log(set.size); //长度 4
3.我们也可以通过构造函数传递参数的方式进行初始化集合,比如接受一个数组
//通过构造参数初始化集合
let set = new Set([1, 2, 2, 3, 3, 4, 5]);
console.log(set); //Set {1, 2, 3, 4, 5}
4.使用 has()方法查找是否存在指定元素,注意 2 和’2’是两个元素,不会隐式转换
let set = new Set([1, 2, 2, 3, 3, 4, 5]);
console.log(set.has(2)); //true
console.log(set.has('2')); //false
5.还可以使用 delete()删除指定元素、clear()清空元素
let set = new Set([1, 2, 2, 3, 3, 4, 5]);
console.log(set); //{ 1, 2, 3, 4, 5 }
console.log(set.delete(2)); //true
console.log(set); //{ 1, 3, 4, 5 }
console.log(set.clear());//undefined
console.log(set);//{}
6.我们可以使用…语法,将 Set 集合转换为数组
let set = new Set([1, 2, 2, 3, 3, 4, 5]);
let array = [...set];
console.log(array);
7.我们可以使用 for 或者 forEach 来遍历 Set 集合
let set = new Set([1, 2, 2, 3, 3, 4, 5]);
for (let i of set){
console.log(i);
}
let set = new Set([1, 2, 2, 3, 3, 4, 5]);
//forEach 变量
//在 Set 集合中 key 和 value 都是值
//s 表示 set 集合本身
set.forEach(function (key, value, s) {
console.log(value);
});
8.Set 集合还提供针对对象的 Weak Set 集合,添加非对象类型会报错
let ws = new WeakSet([1,2,3])
9.Weak Set 集合支持 add()、has()和 delete()方法
10.Weak Set 不支持遍历,内部隐藏(无法查看内容),不支持 foreach 和 size;
11.对于应用场景来说,存放对象的弱引用,不用担心对象被回收后引发的问题;
//强引用
let set = new Set(),
obj = {1:1};
set.add(obj);
console.log(set); //引用存在
//移出引用
obj = null;
console.log(set); //引用依然存在
//弱引用
let ws = new WeakSet(),
obj = {1:1};
ws.add(obj);
console.log(ws.has(obj)); //引用存在,因为弱引用它是无法查看内部的情况的,只能通过这个方式查看是否存在
//移出引用
obj = null;
console.log(ws.has(obj)); //随着销毁而释放
17.Map 数据集合
学习要点:
1.Map 数据集合
本节课我们来开始学习 ES6 新增的 Map 数据集合的用法;
一.Map 数据集合
1.ES6 提供了 Map 数据集合,是一种以键值对存储的有序列表;
let map = new Map();
console.log(map);
//创建 Map 集合
let map = new Map();
map.set('name', 'Mr.Lee'); //.set 添加,支持.set(...).set(...)
map.set('age', 100);
console.log(map);
console.log(map.get('name')); //.get 获取
2.我们也可以通过构造函数传递参数的方式进行初始化集合,比如接受一个数组
//通过构造参数初始化集合
let map = new Map([
['name', 'Mr.Lee'],
['age', 100]
]);
console.log(map);
3.使用 has()检测、delete()删除、clear()清空等对 Map 集合的操作
let map = new Map([
['name', 'Mr.Lee'],
['age', 100]
]);
console.log(map.has('name')); //true
console.log(map.size); //2
map.delete('name'); //删除
map.clear(); //清空
4.我们可以使用 forEach 来遍历 Map 集合,至于 for 遍历,下个章节说
let map = new Map([
['name', 'Mr.Lee'],
['age', 100]
]);
map.forEach((value, key, m) => {
console.log(key + '-' + value);
console.log(m);
});
5.Map 集合还提供针对对象的 Weak map 集合,添加非对象类型会报错
let wm = new WeakMap();
wm.set('1');
console.log(wm);
6.Weak Map 不支持遍历,内部隐藏(无法查看内容),不支持 foreach 和 size;
let wm = new WeakMap(),
obj = {};
wm.set(obj);
console.log(wm);
7.对于应用场景来说,存放对象的弱引用,不用担心对象被回收后引发的问题
和weak set一样
18.迭代器和生成器
学习要点:
1.迭代器和生成器
2.默认迭代接口
本节课我们来开始学习 ES6 新增的迭代器和生成器的用法。
一.迭代器和生成器
1.迭代器(Iterator),用于给数据结构提供统一的访问遍历的机制
2.ES6 之前的迭代器比较麻烦,而现在引入了生成器对象,让迭代器更加容易
3.首先创建一个生成器方法,方法名前面加上*号,迭代的内容之前使用 yield;
//生成器
function *cit() {
yield 1;
yield 2;
yield 3;
}
PS:1,2,3 是我们要遍历的值;下面我们要创建迭代器;
4.迭代器对象的.next()方法,类似指针,每次执行将下移一行;
//迭代器
let it = cit();
//每执行一次.next()将下移一行
console.log(it.next()); //1, false
console.log(it.next()); //2, false
console.log(it.next()); //3, false
console.log(it.next()); //undefined, true
PS:属性 value 得到值,没有返回 undefined,当没有值了,done 则返回 true;
5.生成器结合循环语句,并且进行传递数组进行迭代
function *cit(items) {
for (let i = 0 ; items.length; i++) {
yield items[i]
}
}
let it = cit([1,2,3,4,5]);
console.log(it.next().value);
console.log(it.next().value);
console.log(it.next().value);
console.log(it.next().value);
console.log(it.next().value);
console.log(it.next().value);
PS:如果作为匿名函数使用:let cit = function *(items);
二.默认迭代接口
1.很多数据结构类型拥有默认迭代接口,比如:Array、Map、Set 等等
2.对于原生就支持迭代器的数据结构,我们不用自己编写生成器迭代器
3.对于 Array 数组类型,它提供了有关三个方法:keys()、values()和 entries()
let items = [1, 2, 3, 4, 5];
console.log(items.keys()); //key, Object [Array Iterator]
console.log(items.values()); //value, Object [Array Iterator]
console.log(items.entries());//key+value, Object [Array Iterator]
4.最简单的迭代方式,就是使用 for…of 迭代语句去遍历即可
let items = [1, 2, 3, 4, 5];
//for..of 遍历得到 value 值
for (let i of items.values()) {
console.log(i);
}
5.虽然 for…of 特别方便,不过你想要用.next()语法也是支持的
let items = [1, 2, 3, 4, 5];
let values = items.values();
console.log(values.next());
PS:下节课,我们把其它几种数据类型的默认迭代都演示一遍;
19.异步 Promise
学习要点:
1.Promise 介绍
2.实例测试
本节课我们来开始学习 ES6 新增的 Promise 异步通信方案的功能。
一.Promise 介绍
1.Promise:即异步通信编程的一种解决方案,它比传统回调式更加的强大
2.ES6 之前非常多层次嵌套的同步、异步,执行顺序混乱且不好维护
3.Promise 就很好的解决了这些问题,我们先了解一下它的语法
//创建一个 Promise 实例
let p = new Promise((resolve, reject) => {
//一顿异步通信操作后,返回成功或失败
//然后判断成功或失败去执行 resolve 或 reject
if (true) {
//console.log('异步通信执行成功!');
resolve('执行成功!');
} else {
//console.log('异步通信执行失败!');
reject('执行失败!');
}
});
//then 方法可执行 resolve 的回调函数
//catch 方法可执行 reject 的回调函数
// p.then((value) => {
// console.log(value);
// }).catch((reason) => {
// console.log(reason);
// });
//或者这种一体化语法也行
p.then((value) => {
console.log(value);
},(reason)=>{
console.log(reason);
});
PS:如果你有过很多层异步通信实战基础,上面提供的方法会突然感觉清晰很多;
PS:因为它把多层嵌套的回调函数给分离出来,通过 then 和 catch 来实现;
3.通过上面例子的语法,我们发现 p 作为 Promise 实例,可以进行连缀链式操作
4.当执行了 then 方法后,本身依旧返回了当前的 Promise 实例,方便链式
5.注释中也说明了,通过构造方法的两个参数去执行回调函数,并传递参数
6.事实上,catch()方法还可以作为 then 第二参数进行存在,方便多层回调
...
p.then((value) => {
console.log(value);
},(reason)=>{
console.log(reason);
});
二.实例测试
1.我们做个模拟多层异步通信的实例测试,要异步多个内容,并按指定顺序执行
2.先给出不进行 Promise 异步,看它执行的顺序
//模拟异步 1
setTimeout(() => {
console.log('1.返回异步通信');
}, 3500);
//模拟异步 2
setTimeout(() => {
console.log('2.返回异步通信');
}, 800);
//模拟异步 3
setTimeout(() => {
console.log('3.返回异步通信');
}, 1500);
PS:这里不管你怎么调节,最终输出结果总是:2,3,1。需求顺序要:1,2,3;
3.将上面模拟异步通信,通过 Promise 进行改装,再看看执行结果
let p1 = new Promise((resolve, reject) => {
//模拟异步 1
setTimeout(() => {
//console.log('1.异步通信');
resolve('1.返回异步通信');
}, 3500);
});
let p2 = new Promise((resolve, reject) => {
//模拟异步 2
setTimeout(() => {
//console.log('2.异步通信');
resolve('2.返回异步通信');
}, 800);
});
let p3 = new Promise((resolve, reject) => {
//模拟异步 3
setTimeout(() => {
//console.log('3.异步通信');
resolve('3.返回异步通信');
}, 1500);
});
//执行回调
p1.then((value) => {
console.log(value);
return p2;
}).then((value) => {
console.log(value);
return p3;
}).then((value) => {
console.log(value);
});
20.Promise 状态特点
学习要点:
1.状态特点
2.更多方法
本节课我们来开始学习 ES6 新增的 Promise 异步通信方案的状态特点
一.状态特点
1.回顾上一节:Promise 解决了异步多层回调混乱,且执行顺序的问题
2.本节课,了解一下 Promise 对象异步操作的三种状态
(1) .Pending(进行中)
(2) .Fulfilled(已成功)
(3) .Rejected(已失败)
3.当异步操作执行后,它得到的结果来决定其状态,其它任何操作都无法改变
4.Promise 状态只有两种运行方式:从 Pending 到 Fulfilled 或 Rejected;
5.而当状态已经固定后,此时就变成 Resolved(已完成)。关键字详解:请搜索;
pending -> resolve 方法 -> fulfilled -> resolved
pending -> reject 方法 -> rejected -> resolved
PS:测试当前状态,在浏览器环境下比较直观直接:console.log(p1),在不同阶段执行;node环境下看得不明显,用浏览器测试
let p1 = new Promise((resolve, reject) => {
//模拟异步 1
setTimeout(() => {
//console.log('1.异步通信');
resolve('1.返回异步通信');
}, 3500);
});
let p2 = new Promise((resolve, reject) => {
//模拟异步 2
setTimeout(() => {
//console.log('2.异步通信');
resolve('2.返回异步通信');
}, 800);
});
let p3 = new Promise((resolve, reject) => {
//模拟异步 3
setTimeout(() => {
//console.log('3.异步通信');
resolve('3.返回异步通信');
}, 1500);
});
console.log(p1);
//执行回调
p1.then((value) => {
console.log(p1);
console.log(value);
return p2;
}).then((value) => {
console.log(value);
return p3;
}).then((value) => {
console.log(value);
});
二.更多方法
1.上一节课,我们使用了三组 Promise 实例完成三段异步的排序输出问题
但是那个看起来还是太长了,下面有好的解决方案
2.Promise 提供了一个 all()方法,可以简化多个实例调用输出排序
let p1 = new Promise((resolve, reject) => {
//模拟异步 1
setTimeout(() => {
//console.log('1.异步通信');
resolve('1.返回异步通信');
}, 3500);
});
let p2 = new Promise((resolve, reject) => {
//模拟异步 2
setTimeout(() => {
//console.log('2.异步通信');
resolve('2.返回异步通信');
}, 800);
});
let p3 = new Promise((resolve, reject) => {
//模拟异步 3
setTimeout(() => {
//console.log('3.异步通信');
resolve('3.返回异步通信');
}, 1500);
});
console.log(p1);
//执行回调
// p1.then((value) => {
// console.log(p1);
// console.log(value);
// return p2;
// }).then((value) => {
// console.log(value);
// return p3;
// }).then((value) => {
// console.log(value);
// });
//all方法,可以解决上面那一大堆, p1,p2,p3 是三个 Promise 实例,数组元素顺序即输出顺序
let p = Promise.all([p1, p2, p3]);
//将三个 Promise 实例的回调组合成数组输出
p.then(value => {
console.log(value);
})
PS:虽然 p1,p2,p3 都是异步操作,但最终要等待所有异步完成,才可以输出;
PS:只要 p1,p2,p3 中有一个出现了 Rejected,则会执行失败回调
3.Promise 提供了一个 race()方法,只输出第一个改变状态的实例
//p1,p2,p3 只要有一个改变状态,即回调
let p = Promise.race([p1, p2, p3]);
//所以,这里只输出 p2
p.then(value => {
console.log(value);
});
4.Promise 提供了 resolve()和 reject(),直接返回一个成功或失败的实例
//直接返回成功或失败的 Promise 实例
let ps = Promise.resolve('成功');
let pj = Promise.reject('失败');
ps.then(value => {
console.log(value);
return pj;
}).catch(reason => {
console.log(reason);
})
等价于
new Promise(resolve => resolve('成功'));
那这样的快捷语法糖有什么用呢?下面是一个例子
function getP() {
if (false) {
return new Promise(resolve => {
resolve('异步成功');
})
} else {
return 0; //强制类型一致保证程序正确性 Promise.resolve(0)
}
}
getP().then(value => {
console.log(value);
});
这样就可能出问题,因为你很有可能会读取失败,我们要保持返回类型的一致性,就可以通过这种语法糖快速调用 resolve回调
function getP() {
if (false) {
return new Promise(resolve => {
resolve('异步成功');
})
} else {
//return 0; //强制类型一致保证程序正确性 Promise.resolve(0)
return Promise.resolve(0);
}
}
//这里你调用.then就肯定可以成功
getP().then(value => {
console.log(value);
});
21.代理 Proxy
学习要点:
1.代理能力
本节课我们来开始学习 ES6 新增的 Proxy 代理方法。
一.代理能力
1.什么是代理?即:给目标对象封装一层拦截,外界访问必须先通过这层拦截
2.举个例子:猎头招聘,你自己发布招聘会暴露自身信息,而通过中介则安全的多
3.首先,我们先来看下代理 Proxy 的语法
//目标对象
let obj = {
name : 'Mr.Lee',
age : 100,
gender : '男'
};
//创建一个代理,参数 1 拦截的目标对象,参数 2 拦截行为
//参数 2 如果是空对象,代理直接会调用目标对象
let p = new Proxy(obj, {
//get 方法用于拦截某个属性的读取操作
//这里直接 return,通过代理对象无论访问目标对象的任何属性都是 fail
get(target, property) {
return 'fail';
},
});
//代理对象访问 name 为 fail
console.log(p.name);
4.如果想让代理对象公布出合适的信息,可以通过 get()两个参数来实现
//目标对象
let obj = {
name : 'Mr.Lee',
age : 100,
gender : '男'
};
//创建一个代理,参数 1 拦截的目标对象,参数 2 拦截行为
//参数 2 如果是空对象,代理直接会调用目标对象
let p = new Proxy(obj, {
//get 方法用于拦截某个属性的读取操作
get(target, property) {
if (property === 'age') {
return target[property] - 80;
}
},
});
console.log(p.name);//undefined
console.log(p.age);//20
console.log(p.abc);//不存在的属性 undefined
4.我们也可以通过 set()方法来对代理对象的属性进行赋值,有三个参数
//目标对象
let obj = {
name : 'Mr.Lee',
age : 100,
gender : '男'
};
//创建一个代理,参数 1 拦截的目标对象,参数 2 拦截行为
//参数 2 如果是空对象,代理直接会调用目标对象
let p = new Proxy(obj, {
//get 方法用于拦截某个属性的读取操作
get(target, property) {
if (property === 'age') {
return target[property];
}
},
//set 可以拦截某个属性的赋值操作,比 get 多了参数 3
set(target, property, value) {
if (property === 'age') {
if (!Number.isInteger(value) || value > 150) {
throw new TypeError('年龄数据不合法!');
}
target[property] = value;
}
}
});
p.age = 150;
// p.age = 200;//年龄数据不合法!
console.log(p.age);//150
console.log(obj.age); //150 目标对象属性也被更改
PS:代理并不是复制克隆目标对象,只是拦截目标对象更改默认行为;
PS:代理可以使用 set()和 get()方法,对目标对象的数据进行过滤和验证;
PS:代理对象中任何未公开或不存在的属性,可自定义返回内容,比如:fail 或已屏蔽;
PS:代理也可以阻止赋值的默认行为:直接 return false,就禁止赋值了;
set(target, property, value) {
return false;
}
22.异步 async
学习要点:
1.async 语法
本节课我们来开始学习 ES8 新增的异步 async 方法。
一.async 语法
1.async 也是处理异步的,它是对 Promise 的一种扩展,让异步更加方便
2.优势:async 是基于 Promise 的,虽然是异步操作,但看上去像同步
3.首先,我们先来看下 async 的基本语法
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('1.返回异步通信');
}, 3500);
});
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('2.返回异步通信');
}, 800);
});
let p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('3.返回异步通信');
}, 1500);
});
//创建一个 async 函数,执行异步操作
//await 关键字:等待异步执行完毕后回调;
let as = async () => {
let result = await p1;
console.log(result);
};
//执行 async 函数
as();
PS:上面语法,用 ES5 过渡一下,帮助理解,具体如下:
async function as() {}
let as = async function () {}
let obj = {async as() {}}; //也支持对象方式
4.如果有三个异步需要列队输出,我们用 async 语法来处理一下
//多个异步,按输出顺序加载,没有 then,清晰很多
async function as() {
let r1 = await p1,
r2 = await p2,
r3 = await p3;
console.log(r1);
console.log(r2);
console.log(r3);
}
as();
PS:await 关键字只能在 async 函数内部,否则不可识别;
PS:从上面的例子中,能感受到语义和清晰度都得到了很大提升,更像同步代码;
5.批量异步列队,类似 Promise.all()
async function as() {
let all = [await p1, await p2, await p3];
console.log(all);
}
as();
6.async 函数如果设置了返回值,这个值是 Promise 对象
//返回值是 Promise 对象
//相当于 Promise.resolve()
async function as() {
return 'hello, async!';
}
//所以还需要 Promise 对象的then
as().then(value => {
console.log(value);
});
7.如果 return await p;这种,会导致提前输出 pending 状态,还是需要 then;
async function as() {
return await p1;
}
console.log(as()); //得到的是 Promise 对象的 pending 状态
as().then(value => { //这里还是需要 then
console.log(value);
});
23.类 class 实现
学习要点:
1.类 class
2.getter 和 setter
本节课我们来开始学习 ES6 新增的类 class 的实现方法。
一.类 class
1.在 ES6 之前,JavaScript 不能像其它语言(PHP,Java)等有完整的类支持;
2.我们采用了原型链实现了面向对象的功能,但从 ES6 开始,提供了真正的类语法
3.当然,虽然说是真正的类语法,而本质上内部实现和原型链还是一样的;
4.对于面向对象和类的基础概念,这里不再赘述,学到这里不可能没这个基础的
5.首先,我们创建一个基本的类,并创建构造函数(构造方法),具体如下
//创建一个类
class Person {
//构造函数(构造方法)
constructor(name) {
//this.name 是类的属性
//name 是构造参数赋值给属性
this.name = name;
}
//普通方法
run() {
console.log('类的方法输出!' + this.name);
}
}
//实例化一个 Person 对象
let p = new Person('Mr.Lee');
//执行 run()方法
p.run();
//给成员属性赋值
p.name = 'Mr.wang';
//输出对象的属性
console.log(p.name);
//判断 p 是否是 Person 对象
console.log(p instanceof Person);
//判断类的类型:function
console.log(typeof Person);
6.除了上面的 class Person 这种常规类的写法外,ES6 还支持表达式写法
注意:这里是javascropt才有的写法
//No.1
let Per = class Person {};
//此时 new Person 会报错
let p = new Per('Mr.Lee');
//No.2
let Person = class {};
//No.3
let p = new class {}('Mr.Lee');
p.run();
二.getter 和 setter
1.根据面向对象的三大定律中成员属性,我们需要对它进行封装,变成私有属性
2.而目前的 this.name,基本是对外公开的,可以在类外取值和赋值
3.当我们假设类的属性是私有的,那么需要通过 get()和 set()方法实现
// //创建一个类
// class Person {
// //构造函数(构造方法)
// constructor(name) {
// //this.name 是类的属性
// //name 是构造参数赋值给属性
// this.name = name;
// }
// //普通方法
// run() {
// console.log('类的方法输出!' + this.name);
// }
// }
//
// //实例化一个 Person 对象
// let p = new Person('Mr.Lee');
// //执行 run()方法
// p.run();
//
// //给成员属性赋值
// p.name = 'Mr.wang';
//
// //输出对象的属性
// console.log(p.name);
// //判断 p 是否是 Person 对象
// console.log(p instanceof Person);
// //判断类的类型:function
// console.log(typeof Person);
//创建一个类
class Person {
#name; //提案,浏览器暂时不支持
//构造函数(构造方法)
constructor(name) {
this.#name = name; //私有属性,类外无法访问
}
get name() {
return this.#name;
}
set name(value) {
this.#name = value;
}
}
let p = new Person('Mr.Lee');
//
// // p.#name = 'Mr.Wang'; // Private field '#name' must be declared in an enclosing class 直接不给修改
//
// p.name = 'Mr.Wang';
// console.log(p.name); //为什么这两句可以呢?
//因为上面两句,其实它并没有访问私有成员属性,而是自己创建了一个属性name,就相当于下面的代码
// let obj = {};
// obj.name = 'Mr.wang';
// console.log(obj.name);
//所以这就是容易混淆的地方,此时我们应该访问的是 #name, 那么#name 是私有的属性,那么我们应该怎么访问和修改呢?同时又要拦截外部 name的访问?
//利用 get set 同时名字取成和name相同的名字,就可以防止外部修改了。
24.类 class 继承
学习要点:
1.类的继承
本节课我们来开始学习 ES6 新增的类 class 的继承功能
一.类的继承
1.ES6 也支持子类继承父类,使用 extends 关键字实现
class Person {
constructor(name) {
this.name = name;
}
get user() {
return this.name;
}
set user(value){
this.name = value;
}
run() {
return 'name:' + this.name;
}
}
class Son extends Person {
}
//可以使用父类的构造
let c = new Son('Mr.li');
console.log(c.name);
//get,set 以及方法均可使用
c.user = 'Mr.Wang';
console.log(c.user);
console.log(c.run());
2.继承之后,一般来说,我们需要覆写父类,然后对子类进行增强
class Person {
constructor(name) {
this.name = name;
}
get user() {
return this.name;
}
set user(value){
this.name = value;
}
run() {
return 'name:' + this.name;
}
}
class Son extends Person {
//子类继承
constructor(name, age) { //覆写构造
super(name); //执行父类构造并传参
this.age = age;
}
run() { //覆写方法
return super.run() + this.age; //执行父类方法并返回内容
}
}
//覆写
let son = new Son('Mr.Lee', 100);
console.log(son.age);//子类构造自己传递进来的age
console.log(son.run());//先执行父类的方法,然后再执行子类自己的处理
3.可以使用 Object.getPrototypeOf()判断子类是否继承了父类
console.log(Object.getPrototypeOf(Children) === Person);
4.ES6 的类支持静态属性和方法,也支持静态被子类继承
class Person {
static gender = '男';
static go() {
return 'GO GO GO !' + Person.gender;//类名调用静态属性
}
}
class Children extends Person {
static gender = '女'; //覆写静态
static go() {
return 'o o o ' + Person.gender;//这里使用 Person 和 Children 是不一样的 如果这里使用 this.就等于Children类
}
}
console.log(Person.gender);//男
console.log(Person.go());//调用Person的静态方法
console.log(Children.gender);
console.log(Children.go());
拓展:es5演示静态方法和实例方法
let Animal = function (type) {
this.type = type
}
// 动态方法
Animal.prototype.walk = function(){
// 调用静态方法
Animal.eat()
console.log('I am walking')
}
// 静态方法
Animal.eat = function (food) {
console.log(`I am eating`);
}
let cat = new Animal('cat')
cat.walk()
cat.eat()
25.Module 模块化
学习要点:
1.浏览器加载
2.Node 加载
本节课我们来开始学习 ES6 新增的模块化导入导出的方法。
一.ES6 模块化
0.在以前我们是怎么做的?
1.ES6 支持模块化设计,也能其它后端语言一样使用导入导出的功能
2.我们首先,创建一个要被导入的模块 module.js,具体如下
export let name = 'Mr.Lee'; //导出这个变量
PS:里面有很多变量,导出那个那个才可以用,其它不可见
3.再创建一个普通的.js 文件,比如 25.js,然后导入 module.js;
import {name} from './module.js';
console.log(name);
4.最后一步,在.html 文件要加载 25.js 文件,才有小,注意 type 格式;
<script type="module" src="js/25.js"></script>
PS:注意,这种导入导出的方式属于 ES6 模块,仅支持浏览器模式;
如果不设置type="module"则会报错
5.除了导出变量、常量之外,还可以导出函数、类等功能
export let name = 'Mr.Lee';
export function sum(x, y) {
return x + y;
}
export class Person {
constructor(name) {
this.name = name;
}
run() {
return 'name : ' + this.name;
}
}
import {name, sum, Person} from './module.js';
console.log(name);
console.log(sum(10, 20));
console.log((new Person('Mr.Lee')).run());
6.也支持使用*号,将所有导出的内容全部加载进来
import * as obj from './module.js';
console.log(obj.name);
console.log(obj.sum(10, 20));
console.log((new obj.Person('Mr.Lee')).run());
7.支持别名设定,设定别名后,源名即失效了
import {name as user} from './module.js';
console.log(user); //name 无效了
8.统一导出方案,不需要再每一个导出的内容设置 export
let name = 'Mr.Lee';
function sum(x, y) {
return x + y;
}
class Person {
constructor(name) {
this.name = name;
}
run() {
return 'name : ' + this.name;
}
}
export {
name,
sum,
Person
}
9.可以给导出设置一个默认值,导入部分就可以不用花括号了
export default name;
import name from './module.js';//导入得时候直接name就可以了
import name, {sum, Person} from './module.js';//如果还要引入别的,逗号,+花括号
二.Node 加载
1.Node 下有自己的导出和导入的加载模式:CommonJS 规范
新建common.js
文件
let name = 'Mr.Lee';
module.exports = {
name : name,
};
const name = require('./common.js');
console.log(name);