美文网首页工作生活
ES6学习笔记(三)

ES6学习笔记(三)

作者: 彼得朱 | 来源:发表于2019-07-04 18:51 被阅读0次
6.png

十一、类和继承

1、版本

ES5以前的:

function Person(){

​ this.name = 'aaa';

}

Person.prototype.showName = function(){};

ES6中变形:

(形式1)

class Person{

​ constructor(){

​ this.name = 'aaa';

​ } //这里不能加逗号

​ showName(){}

}

(形式2)

const Person = class{

​ constructor(){

​ this.name = 'aaa';

​ } //这里不能加逗号

​ showName(){}

}

注意:constructor和方法之间不要随意加逗号

// 以前的
// 方法1
function Person(name,age){
    this.name = name;
    this.age = age;
}

Person.prototype.showName = function(){
    return `名字为${this.name}`;
};
Person.prototype.showAge = function(){
    return `年龄为${this.age}`;
};
let p1 = new Person('张三',18);
//输出为  名字为张三 年龄为18
console.log(p1.showName(),p1.showAge());  

// 方法2
function Person2(name2,age2){
    this.name2 = name2;
    this.age2 = age2;
}
Object.assign(Person2.prototype,{
    showName(){
        return `名字为${this.name2}`;
    },
    showAge(){
        return `年龄为${this.age2}`;
    }
});
let p2 = new Person2('李四',20);
//输出为  名字为李四 年龄为20
console.log(p2.showName(),p2.showAge());  
//  现在的
class Person {
    constructor(name, age) { 
        //构造方法(函数),调用new,自动执行
        this.name = name;
        this.age = age;
    }
    showName() {
        return `名字为${this.name}`;
    }
    showAge() {
        return `年龄为${this.age}`;
    }

}

let p1 = new Person('张三', 18);
// 输出为 名字为张三 年龄为18
console.log(p1.showName(),p1.showAge());

2、注意事项

注意:1、ES6 类中属性名可以用表达式

let aaa = 'a';
let bbb = 'b'
class Person {
    [aaa+bbb](){
        return '随便啦》》》';
    }

}
let p1 = new Person();
console.log(p1[aaa+bbb]());   //  输出  随便啦》》》

​ 2、ES6 里面 class 没有提升功能,在ES5,用函数模拟可以,默认函数提升

​ 3、ES6 里面this指向 比以前轻松多了

​ 矫正this:

​ a)fn.call(this指向谁,args1,args2......)

​ b)fn.apply(this指向谁,[args1,args2.......])

​ c)fn.bind()

class Person{
    constructor(){
        this.name = 'strive';
        // 因为下面加了let {showName} = p1;,this将指向不明确,所以需要矫正this
        this.showName = this.showName.bind(this);//矫正this
    }
    showName(){
        console.log('this',this);
        return `名字为${this.name}`;
    }
}
let p1 = new Person();
let {showName} = p1;  //这句话纯属没事找事,把this指向弄乱了
console.log(showName());

3、class

(1)getter 和 setter

class Person{
    constructor(){

    }
    set aaa(val){
        console.log(`设置aaa属性,值为:${val}`);
    }
    get aaa(){
        return `aaa的属性`;
    }
}
let p1 = new Person();
p1.aaa = '123';
console.log(p1.aaa);  //输出   aaa的属性

(2)静态方法static

(3)继承

//以前的
// 父类
function Person(name){
    this.name = name;
}
Person.prototype.showName = function(){
    return `名字为${this.name}`; 
}
// 子类
function Student(name,skill){
    Person.call(this,name);    //继承属性
    this.skill = skill;
}
Student.prototype = new Person();  //继承方法

//调用
let stu1 = new Student('strive','逃学');
console.log(stu1.showName());    //输出为  名字为strive
//现在的
// 父类
class Person{
    constructor(name){
        this.name = name;
    }
    showName(){
        console.log('父级的showName,'+`名字为${this.name}`);//输出  父级的showName,名字为strive
        return `名字为${this.name}`; 
    }
}
// 子类
class Student extends Person{
    constructor(name,skill){
        super(name);
        this.skill = skill;
    }
    showSkill(){
        return `哥们的技能为:${this.skill}`;
    }
    showName(){//这样做会覆盖掉父集的方法,要想父集方法也被调用,用下面这句
        super.showName();
        return `子类的showName,名字为${this.name}`;
    }
}

//调用
let stu1 = new Student('strive','逃学');
console.log(stu1.showName());    //输出为  子类的showName,名字为strive
console.log(stu1.showSkill());   //输出为  哥们的技能为:逃学

(4)继承案例(拖拽div)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    

    <style>
        .box{
            width: 100px;
            height: 100px;
            background:red;
            position: absolute;
            top: 0;
        }
        .left{
            left: 0;
        }
        .right{
            right: 0;
        }
    </style>
</head>

<body>
    <div id="div1" class="box left"></div>
    <div id="div2" class="box right"></div>
    <script>
            // 普通的拖拽,父类
            class Drug{
                constructor(id){
                    this.oDiv = document.querySelector(id);
                    this.disX = 0;
                    this.disY = 0;
                    this.init();
                }
                init(){
                    this.oDiv.onmousedown = function(ev){
                        this.disX = ev.clientX - this.oDiv.offsetLeft;
                        this.disY = ev.clientY - this.oDiv.offsetTop;
    
                        document.onmousemove = this.fnMove.bind(this);
                        document.onmouseup = this.fnUp.bind(this);
                        
                        return false;
                    }.bind(this);
                }
                fnMove(ev){
                    this.oDiv.style.left = ev.clientX - this.disX +'px';
                    this.oDiv.style.top = ev.clientY - this.disY +'px';
                }
                fnUp(){
                    document.onmousemove = null;
                    document.onmouseup = null;
                }
            }

            //子类,限制范围
            class limitDrug extends Drug{
                fnMove(ev){
                    super.fnMove(ev);  //继承父类的方法
                    // 这里做自己的事情,限制范围
                    if(this.oDiv.offsetLeft<=0){
                        this.oDiv.style.left = 0;
                    }
                }
            }

            //调用
            new Drug('#div1');
            new limitDrug('#div2');
        </script>
</body>

</html>

十二、Symbol & generator

1、Symbol

之前 typeof 出来的数据类型有 : number、string、undefined、function、boolean

​ Object

Symbol 使用情况一般,typeof 出来的是 symbol

定义:let syml = Symbol('aaa');

注意:(1) Symbol 不能 new

​ (2)Symbol 返回是一个唯一值,坊间传说,定义一些唯一或者私有一些东西

​ (3)Symbol 是一个单独的数据类型,就叫symbol

​ (4)如果用 symbol 作为key,用for in 循环,出不来

//   当作 key
let syml = Symbol('Strive');

let json = {
    a:'apple',
    b:'banana',
    [syml]:'aaa'
}
// 当作key
console.log(json[syml]);  // 输出 aaa 

//  如果用 symbol  作为key,用for in 循环,出不来    
let syml = Symbol('Strive');
let json = {
    a:'apple',
    b:'banana',
    [syml]:'aaa'
}
for(let key in json){
    console.log(key);   // 输出 a  b  ,最后一个出不来
}

2、generator

解决异步深度嵌套的问题

(1)语法

generator函数,注意 * 左右有无空格无所谓

function * show(){

​ yield

}

定义和调用如下例:

// 定义
function * gen(){
    yield 'welcome';
    yield 'to';
    yield 'mmr';
}

// 调用
let g1 = gen();
console.log(g1.next());  //  输出  {value: "welcome", done: false}
console.log(g1.next());  //  输出  {value: "to", done: false}
console.log(g1.next());  //  输出  {value: "mmr", done: false}
console.log(g1.next());  //  输出  {value: undefined, done: true}

(2)配合使用

配合使用的有:for...of、解构、扩展运算符、Array.from、axios

上述调用,手动调用,麻烦,下面用了for...of自动遍历generator,但是注意的是return的东西,它不会遍历

// for...of
// 定义
function * gen(){
    yield 'welcome';
    yield 'to';
    yield 'mmr';
    return '测试return'
}

// 调用
let g1 = gen();
for(let val of g1){
    console.log(val)  // 输出 welcome to mmr  ,return的东西,它不会遍历
}

// 解构、扩展运算符、Array.from
// 定义
function * gen(){
    yield 'welcome';
    yield 'to';
    yield 'mmr';
    return '测试return'
}

// 调用
// 解构 1
let [a,b,c] = gen();
console.log(a,b,c);  // 输出 welcome to mmr
// 解构 2
let [d,...e] = gen();
console.log(d,e);    // 输出 welcome ["to", "mmr"]
//扩展运算符
console.log(...gen());// 输出 welcome to mmr
//Array.from
console.log(Array.from(gen())); // 输出 ["welcome", "to", "mmr"]

// generator 结合 axios 数据请求
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
    // generator 结合 axios 数据请求
    function * gen(){
    let val = yield 'piterzhuhui';
    yield axios.get(`https://api.github.com/users/${val}`);
}
let g1 = gen();
let username = g1.next().value;
console.log(username);
g1.next(username).value.then(res=>{
    console.log(res.data); //这里返回的是自己github信息
})
</script>

补充知识:

异步:不连续,上一个操作没有执行完,下一个操作照样开始

同步:连续执行,上一个操作没有执行完,下一个操作没法开始。

关于异步,解决方案:

​ (a)回调函数

​ (b)事件监听

​ (c)发布/订阅

​ (d)Promise对象

十三、async、await

1、async、await

ES2017 ,规定 async ,async 告诉 程序这是一个异步程序,await 等待,配套使用

async function fn(){ //表示异步,这个函数里面有异步任务

​ let result = await XXX // 表示后面结果需要等待

}

例子:读取文件: fs.readFile (nodeJs)

(1)promise

(2)generator

(3)async

(1)promise

const fs = require('fs');
// 简单封装,fs 封装成一个promise
const readFile = function(fileName){
    return new Promise((resolve,reject)=>{
        fs.readFile(fileName,(err,data)=>{
            if(err) reject(err);
            resolve(data);
        });
    });
}

// promise
readFile('data/a.txt').then(res=>{
    console.log(res.toString());
    // 这里可以返回数据,然后继续调用
    return readFile('data/b.txt');
}).then(res=>{
    console.log(res.toString());
    // 这里可以返回数据,然后继续调用
    return readFile('data/c.txt');
}).then(res=>{
    console.log(res.toString());
})

从文件中读出来的:

1.png

(2)generator

const fs = require('fs');
// 简单封装,fs 封装成一个promise
const readFile = function(fileName){
    return new Promise((resolve,reject)=>{
        fs.readFile(fileName,(err,data)=>{
            if(err) reject(err);
            resolve(data);
        });
    });
}

//generator
function * gen(){
    yield readFile('data/a.txt');
    yield readFile('data/b.txt');
    yield readFile('data/c.txt');
}
let g1 = gen();

g1.next().value.then(res=>{
    console.log(res.toString());
    return g1.next().value;
}).then(res=>{
    console.log(res.toString());
    return g1.next().value;
}).then(res=>{
    console.log(res.toString());
})

执行和上面一致,也是在终端用 node 命令:node .\generator.js

(3)async

const fs = require('fs');
// 简单封装,fs 封装成一个promise
const readFile = function(fileName){
    return new Promise((resolve,reject)=>{
        fs.readFile(fileName,(err,data)=>{
            if(err) reject(err);
            resolve(data);
        });
    });
}

//async
// 定义
async function fn(){
    let f1 = await readFile('data/a.txt');//返回的值就是文件的内容
    console.log(f1.toString());
    let f2 = await readFile('data/b.txt');
    console.log(f2.toString());
    let f3 = await readFile('data/c.txt');
    console.log(f3.toString());
}
//调用
fn();

执行和上面一致,也是在终端用 node 命令:node .\async.js

(4)async特点

(a) await 只能放到 async 函数中

(b) 相比 generator 语义性更强

(c) await 后面可以是一个promise对象,也可以是数字,字符串,布尔。。。。(它会转成promise对象)

(d) async 函数返回的是一个 promise 对象

(e) 只要 await语句后面的 promise 状态变成reject,那么整个async 函数会中断执行

// async 函数返回的是一个 promise 对象
async function fn(){
    return 'Welcome'
}
console.log(fn());   //输出 Promise {<resolved>: "Welcome"}
fn().then(res=>{
    console.log(res); // 输出 Welcome
})

// 只要 await语句后面的 promise 状态变成reject,那么整个async 函数会中断执行
async function fn4(){
    let a = await Promise.resolve('成功');
    console.log(a);     // 输出  成功
    await Promise.reject('出现问题了');
    let b = await Promise.resolve('成功2');// 注意这里不会执行,因为上一句有reject,函数就被中断执行了
    console.log(b);
}
fn4().then(res=>{
    console.log(res);
}).catch(err=>{
    console.log(err); // 输出 出现问题了
})

注意:如何解决async 函数中抛出错误,影响后续代码,让它不影响

第一种:用 try——catch

​ try{

​ }catch(e){

​ }

第二种:用promise本身的catch

async function fn4(){
    await Promise.reject('出现问题了').catch(err=>{
        console.log(err);    // 输出 出现问题了
    });
    let b = await Promise.resolve('成功2');
    console.log(b);          // 输出 成功2
}
fn4().then(res=>{
    console.log(res);
}).catch(err=>{
    console.log(err);
})


注意:建议所有的 await try_catch 把之前读文件例子改一下

//async
// 定义
async function fn(){
    try{
        let f1 = await readFile('data/a.txt');
        let f2 = await readFile('data/b.txt');
        let f3 = await readFile('data/c.txt');
    }catch(e){

    }
    
}
//调用
fn();

注意:当 await 的东西之间相互不影响时,可以用 Promise.all([]) 来做处理。

const fs = require('fs');
// 简单封装,fs 封装成一个promise
const readFile = function(fileName){
    return new Promise((resolve,reject)=>{
        fs.readFile(fileName,(err,data)=>{
            if(err) reject(err);
            resolve(data);
        });
    });
}

//async
// 定义
// 当三个过程没关联的时候可以这样用
async function fn(){
    let [a,b,c] = await Promise.all([
        readFile('data/a.txt'),
        readFile('data/b.txt'),
        readFile('data/c.txt')
    ]);
    console.log(a.toString());  //输出  aaaa
    console.log(b.toString());  //输出  bbbb
    console.log(c.toString());  //输出  cccc
}
//调用
fn();

十四、set和WeakSet

1、set

概念:类似数组,但是里面不能有重复值

set用法 : 定义: new Set(['a','b'])

​ 添加: arr.add(元素)

​ 删除: arr.delete(元素)

​ 判断: arr.has(元素)

​ 大小:arr.size //返回个数

​ 循环:for...of arr //默认是values值

​ for...of arr.keys()

​ for...of arr.values()

​ for...of arr.entries()

​ arr.forEach

​ 类似链式操作:let setArr = new Set().add('a').add('b').add('c');

​ 数组去重:把数组变成set,再由set数据结构变成数组

​ [...set]

​ set里面用map :转成数组,map处理之后再转成set

​ eg: set3 = new Set([...set3].map(val=>val*2));

​ set里面用filter:转成数组,filter处理之后再转成set

​ eg: set4 = new Set([...set4].filter(val=>val%2==0));

注意:set和WeakSet的区别是,set([]),WeakSet({})

​ set里面可以放对象,但是大多数不用,用WeakSet

​ 确认:初始往里面添加对象,是不行的,最好用 add

// 定义
let arr = ['a','b','c','a'];
console.log(arr);  //输出  (4) ["a", "b", "c", "a"]

let setArray = new Set(['a','b','c','a','b']);
console.log(setArray);  //输出  Set(3) {"a", "b", "c"}


// 添加
let setArr = new Set();
setArr.add('a');
setArr.add('b');
console.log(setArr); // 输出 Set(2) {"a", "b"}


// 删除
setArr.delete('b');
console.log(setArr); // 输出 Set(1) {"a"}

// 判断元素是否存在
console.log(setArr.has('a'));  // 输出 true
console.log(setArr.has('b'));  // 输出 false

// set大小
console.log(setArr.size);   // 输出  1

// 清除所有
setArr.clear();
console.log(setArr.size);   // 输出  0

//循环
let setArr = new Set(['a','b','c']);
// 循环 默认
for(let item of setArr){
    console.log(item); //  循环输出   a  b  c  
}
//for...of    arr.keys()
for(let item of setArr.keys()){
    console.log(item); //  循环输出   a  b  c 
}
//for...of    arr.values()
for(let item of setArr.values()){
    console.log(item); //  循环输出   a  b  c  
}
//for...of    arr.entries()
for(let item of setArr.entries()){
    console.log(item); //  循环输出   ["a", "a"]  ["b", "b"]  ["c", "c"]
}
for(let [k,v] of setArr.entries()){
    console.log(k,v); //  循环输出   a a   b b  c c
}
//arr.forEach   (建议使用)
setArr.forEach((v,i)=>{
    console.log(v,i); //  循环输出   a a   b b  c c
})

// set用map
// 以前
let set = new Set([1,2,3]);  //注意括号里面是[]
let set2 = new Set();
for(let item of set.values()){
    set2.add(item*2);
}
console.log(set2);   // 输出  Set(3) {2, 4, 6}

let set3 = new Set([1,2,3]);
set3 = new Set([...set3].map(val=>val*2));
console.log(set3);   // 输出 Set(3) {2, 4, 6}

// set 用filter
let set4 = new Set([1,2,3]);
set4 = new Set([...set4].filter(val=>val%2==0));
console.log(set4);   // 输出 Set(1) {2}

// set()  里面存对象,但是注意不能直接往()里面放对象
let set = new Set();

let json = {
    a:1,
    b:2
}
let json2 = {
    a:'apple',
    b:2
}
set.add(json);
set.add(json2);
set.forEach((item)=>{
    console.log(item.a);  // 输出  1 apple
})
console.log(set.size);    // 输出  2

2、WeakSet()

存储 json ,这种写法不靠谱,WeakSet没有size,有没有clear

但是有 add(),has(),delete()

let wSet = new WeakSet();
let json = {
    a: 1,
    b: 2
}
let json2 = {
    a: 'apple',
    b: 2
}
wSet.add(json);
wSet.add(json2);
console.log(wSet); //输出  WeakSet {{…}}
console.log(wSet.size);// 输出 undefined

总结:以后用 set。

相关文章

网友评论

    本文标题:ES6学习笔记(三)

    本文链接:https://www.haomeiwen.com/subject/bafdhctx.html