1.Proxy的实现
(1)New创建的proxy(不可撤销)
var pro = new Proxy(person,{
get:function(target,property){
return 'ls'
}
set:function(target,property,value){
return ''
}
})
get方法:target参数表示所要拦截的目标对象,property表示属性
set方法:三个属性,target,property,value(属性值)
ownKeys:拦截操作,拦截过滤Object.keys()对对象的属性遍历
let person = {name:'老王',age:40,height:1.8}
let proxy = new Proxy(person,{
ownKeys:function(target){
return ['name','age']
}
})
Object.keys(proxy); //结果:[“name”,”age”]
ownKeys得到的只是被过滤后的结果:[“name”,”age”]。
has方法:拦截key in object的操作,结果会返回一个布尔值,has( )方法用于是判断是否含有指定的键值对,有,就返回true,否则返回false
(2)函数代理:apply调用
(3)proxy.revocable方法(可撤销的)
Proxy.revocable( )(可废止的,可撤回的;)函数来实现,它会返回一个对象
有一个属性revoke,它是一个方法,用于取消代理。
let obj = Proxy.revocable(person,{})
obj.revoke();
Proxy.revocable( )方法返回的结果是一个对象
2.for...of使用
(1)for…of使用
for...of 一种用于遍历数据结构的方法。它可遍历的对象包括数组,字符串,set和map结构等具有iterator 接口的数据结构。(不包含对象)
传统的遍历数组的方式以及它们的缺陷:
1.for循环来遍历数组的缺点:代码不够简洁
2.forEach循环代码量少了很多,写法更加简洁,缺点就是:无法中断停止整个循环。
3. for...in循环更常用于对象的循环,如果用于数组的循环,那么就要注意了,上述代码中每次循环中得到的i是字符串类型,而不是预料中的数字类型,要想对它进行运算,那得先要进行类型转换,造成不方便。
for...of的优势:for(let value of arr){}
可以用break来终止整个循环,或者continute来跳出当前循环,继续后面的循环;
但直接获取的是值而不是索引。
结合keys( )获取到循环的索引,并且是数字类型,而不是字符串类型。
//得到数字类型索引
var arr = [1,2,3,4,5]
for(let index of arr.keys()){
console.log(index); //0,1,2,3,4
}
//得到 [值,索引]
for(let [i,value] of arr.entries()){
console.log([i,value]); //[1,0] [2,1] [3,2] [4,3] [5,4]
}
//遍历字符串
let str = '我是前端'
for (let s of str) {
console.log(s); //依次打印:我 是 前 端
}
3.Iterator遍历器
(1)Object对象的原型上没有Symbol.iterator,所以for...of不能遍历对象(object)
(2)Iterator原理:原型上有[Symbol.iterator]方法,这个方法返回一个迭代器对象Iterator,这个对象有一个next属性,属性值又是一个函数,函数返回一个对象,对象有两个属性done表示完成状态,value是属性值
(3)自定义Iterator遍历器
let obj = { 'age': 18, 'name': 'zs', 'height': 180 }
obj[Symbol.iterator] = function () {
let list = Object.keys(obj)
let num = -1;
return {
next: function () {
num++
// let value=obj[list[num]]
let value = {};
value[list[num]] = obj[list[num]]
let done = list.length === num
return {
done,
value
}
}
}
}
for (let value of obj) {
console.log(value); //{age:18} {name:'zs'} {height:180}
}
4.Generator函数
(1)普通函数和Generator函数的区别
普通函数用function来声明,Generator函数用function*声明。
Generator函数函数内部有新的关键字:yield( 产出)暂停,下一次调用从当前位置继续执行,普通函数没有。
(2)调用Generator函数
function* Hello(name) {
yield `hello ${name}`;
yield `How are you?`;
yield `bye`;
}
let ite1 = Hello('前端君')
console.log(ite1.next()); //{value: 'hello 前端君', done: false}
console.log(ite1.next()); //{value: 'How are you?', done: false}
console.log(ite1.next()); //{value: 'bye', done: false}
console.log(ite1.next()); //{value: undefined, done: true}
(3)yield语句的使用
yield在这里相当于暂停执行并且返回信息。有点像传统函数的return的作用,但不同的是普通函数只能return一次,但是Generator函数可以有很多个yield。
(4)next方法接收参数
next( )方法还可以接收一个参数,它的参数会作为上一个yield的返回值,
function* Hello() {
let res = yield `hello`;
yield res;
}
let iterator = Hello(); //结果:一个生成器对象
console.log(iterator.next()); //结果:{value: "hello", done: false}
console.log(iterator.next("前端君")); //结果:{value: "前端君", done: false}
(5)关键字‘yield*’
Generator函数里面,如果我们想调用另一个Generator函数,就需要用到的关键字是:yield*。
function* gen1() {
yield "gen1 start";
yield "gen1 end";
}
//声明Generator函数:gen2
function* gen2() {
yield "gen2 start";
yield "gen2 end";
}
//声明Generator函数:start
function* start() {
yield "start";
yield* gen1();
yield* gen2();
yield "end";
}
//调用start函数
var ite = start();
//创建一个生成器
ite.next(); //{value: "start", done: false}
ite.next(); //{value: "gen1 start", done: false}
ite.next(); //{value: "gen1 end", done: false}
ite.next(); //{value: "gen2 start", done: false}
ite.next(); //{value: "gen2 end", done: false}
ite.next(); //{value: "end", done: false}
如果一个Generator函数A执行过程中,进入(调用)了另一个Generator函数B,那么会一直等到Generator函数B全部执行完毕后,才会返回Generator函数A继续执行。
(6)Generator函数的用途
它可以控制函数的内部状态,依次遍历每个状态;可以根据需要,轻松地让函数暂停执行或者继续执行。
根据这个特点,我们可以利用Generator函数来实现异步操作的效果。
5.类基本用法
1.必须使用new关键字来创建类的实例对象
2.先声明定义类,再创建实例,否则会报错
类的静态方法:如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”
类的继承,ES6使用extends关键字来实现子类继承父类
用super来引用父类,访问父类的方法
在子类中调用父类的say方法的话,使用super.方法名( )即可实现。
class Animal{
constructor(name){
this.name=name;
}
say(){
console.log('This is a '+this.name);
}
static food(){
console.log('喜欢吃什么?');
}
}
//1.必须使用new关键字来创建类的实例对象
// 2.先声明定义类,再创建实例,否则会报错
let dog=new Animal('dog');
console.log(dog.name); //dog
dog.say() //This is a dog
// 如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,
// 而是直接通过类来调用,这就称为“静态方法”
Animal.food(); //喜欢吃什么?
// dog.food() //报错:dog.food is not a function
//类的继承,ES6使用extends关键字来实现
class Dog extends Animal{
constructor(name,color){
//用super来引用父类,访问父类的方法
super(name)
this.color=color;
}
say(){
super.say()
console.log('汪汪叫');
}
}
let myDog=new Dog('小黄','yellow')
myDog.say(); //This is a 小黄 汪汪叫