ES6学习笔记

前言

这是我学习ES6的笔记,语言偏向口语化,主要是个人觉得这样会比较亲切…

由于是学习笔记,内容可能会有不够详实,存在瑕疵等诸多问题,欢迎大家在评论区批评指正

希望接下来的内容能够在大家学习ES6的过程中给予一点帮助

ES的定义
即ECMAScript,脚本语言的规范

其中的ECMA的全称是全称:European computer manufacturers association欧洲计算机制造联合会,后改名为ECMA国际

ES新特性指的是JavaScript的新特性.

为什么学ES
概括为----更方便更高能

接下来进入正题:

1.let声明

let a = 233,翻译就是让a等于233,简直语义化啊!

使用方式(就是变量声明啦)

let a;
let b, c;
let d = 100;
let e = 666, f = 'hhh', g = [];

特性

  1. 变量不能重复声明,否则报错
    (没错,var是可以重复的)
  2. 增加块级作用域
    (ES5中有三种作用域:全局、函数、严格模式中的eval)
    C/C++转过来的简直感动

举个栗子:

{
	let a = '我在一个块里面';
	console.log('这是第1个:' + a);
}

上图的运行结果:
这是第1个:我在一个块里面

    	{
    		let a = '我在一个块里面';
    	}
    	console.log('这是第2个:' + a);

上图的运行结果
报错:a没有定义
补充一点,if、else、while、for等也可以形成块级作用域

  1. 取消变量提升
        console.log('我是' + Var);
        console.log('我是' + Let);
        var Var = 'var';
        let Let = 'let';

上图运行结果:
一个报错一个undefined
(undefined是声明提升但是赋值不提升导致的)

  1. 依旧有作用域链

2.const声明

就是常量啦

使用方式

const A = "必须要初始化(赋值)";
//常量命名规范是:大写大写大写!!!

特性

  1. 一定要赋初始值
  2. 赋值完成后不可修改(毕竟声明的是常量)
  3. 也有块级作用域
  4. 对于用const声明的数组和对象,可以修改其元素

3.新特性:解构赋值

字面意思就是把结构拆解然后赋值?
关于这个东西呢直接举例子比较好
数组的解构赋值

        const ARRAY = [1,2,3,4];
        let array = [a,b,c,d] = ARRAY;
        console.log(a,b,c,d);

上图运行结果:
1 2 3 4
awsl!!!!怎么样,是不是爽的不要不要的?!
对象的解构赋值

        const MyInfo = {
            name:'Serio',
            ablity:'TouchFish',
            TouchFish:function(){
                console.log('没人比我更懂摸鱼');
            }
        };
        let InfoOfMine = {name,ablity,TouchFish} = MyInfo;
        console.log(name,ablity);
        TouchFish();

上图运行结果:
Serio TouchFish 没人比我更懂摸鱼
其中对 对象的方法 进行解构是最常用的,为了偷懒 方便
需要注意的是,各个元素的名字需要一致,否则报错。

4.新特性:模板字符串

孔丙己便涨红了脸,额上的青筋条条绽出,争辩道,“ES5不能……换行!……ES6的事,还用换行吗?”接连便是难懂的话,什么“作用域链”,什么“闭包”之类,引得众人都哄笑起来:店内外充满了快活的空气

使用方式

新旧对比

        let str = '换行昂昂昂\
                   要加上斜杠,或者加号连接'
                  + '不然会报错的';
        let strES6 = `没错,现在我们用\`(反引号,就是键盘上和~一个位置那个)
                    表示字符串惹~
                    换行很方便的~~~`;

特性

  1. 可以直接换行了
  2. 可以直接拼接变量
    (配合高贵的${})
let a = 3;
let str = `我要给这篇文章一个${a}`;
console.log(str);

上图运行结果
提前感谢
感谢各位读者,感谢一路走来给予我支持和帮助的老师和前辈…阿巴阿巴(手动狗头)

5.新特性:对象属性声明简化

使用方式

        let name = 'Serio', 
            level = '蒟蒻';
        
        function showAbility(){
            console.log('BUG + 1');
        }
   //没错,直接将变量作为自身属性
        const FEIWU = {
            name,
            level,
            showAbility,
   //函数的声明也可以不用写function了
            checkMoney(){
                console.log(`果然没钱`);
            }
        }
        FEIWU.showAbility();
        FEIWU.checkMoney();

上图运行结果:
在这里插入图片描述

特性
似乎…没啥特性

6.新特性:箭头函数

“你知道吗,箭头函数的语法糖,有四种写法”

使用方式

//第一种:()=>{}
        let fn = (a, b)=>{
            console.log(a + b);
        }
        fn('啊','是箭头函数');
//第二种:只有一个参数,省略() 
        fn = a =>{
            console.log(`笑死我${a}`);
        }
        fn(2333);
//第三种:方法体只有一条语句,省略{}
        fn = (a,b)=>console.log(a + b);
        fn(1,1);
//第四种:方法体只有一条语句且为return,直接写return的内容
        fn = (a)=>a + 1;
        console.log(fn(9));

上图运行结果
在这里插入图片描述

特性

  1. 静态this
    对于function声明的函数,谁调用this就指向谁;
    但是对于箭头函数来说,其this永远指向函数声明时的作用域下的this,并且不能被call,bind等方法改变
//写成这样方便复习上一个知识点
        let whereIsThis1 = function(){
            console.log("1普通函数" + this);
        }

        let whereIsThis2 = ()=>{
            console.log("2箭头函数" + this);
        }
        const WhereRU = {
            whereIsThis1,
            whereIsThis2
        }
        WhereRU.whereIsThis1();
        WhereRU.whereIsThis2();

上图运行结果
普通函数---this指向对象,箭头函数---this指向window
所以箭头函数适用于与this无关的情况

  1. 不能实例化对象(就是不能作为构造函数,也就是不能new)
  2. 没有arguments了(悲伤)
  3. 多种省略形式(没错就是开头的几种形式)

7.函数参数默认值

说实话看到这个新特性的时候我第一也是唯一的反应就是————
原来以前没有吗???
使用方式

//好了,现在c有默认值了
        function calc(a,b,c = 220){
            console.log(a + b + c);
        };
        calc(100,200);
        calc(100,200,1014);

上图运行结果
520 1314

8.rest参数

“arguments的离去,是rest的要求,还是es6的不挽留”
(其实arguments不仅还能用,还挺好用的)
使用方法

//...是扩展运算符 不可以省略
        function UltramanBros(a,b,...args){
            console.log(a,b,args);
        }
        show("佐菲","初代","赛文","艾斯","泰罗","雷欧");

上图运行结果
超出的四个会以数组形式保存
…是扩展运算符,能将数组展开成参数序列,
所以传入…args相当于传入了n个参数,
超出的四个参数依次对应,然后存入args中

9.Symbol类型

JS的第七种数据类型(话说前六种是啥来着)
这次我们先说特性
特性

  1. 值唯一,解决了命名冲突问题
  2. 不能与其他类型的数据进行运算
  3. Symbol类的对象不能用加强for循环(for in),但是可以用Reflect.ownKeys

我对Symbol的理解:
就是根据你传入的内容产生一个(伪)随机的、不重复的值,感觉原理就是哈希表(散列表)
(如果没错的话,那么理解哈希表会帮助理解Symbol)

使用方式

//第一种声明方式
        let s1_1 = Symbol('第一类');
        let s1_2 = Symbol('第一类');
//s1_1和s1_2依旧是不同的值
//keyFor()方法就是根据值反过来找下标        
        console.log(s1_1 === s1_2);//false
        console.log('第一类声明的索引' + Symbol.keyFor(s1_1));//undefined
//第二种声明方式
        let s2_1 = Symbol.for('第二类');
        let s2_2 = Symbol.for('第二类');
        
        console.log(s2_1 === s2_2);
        console.log('第二类声明的索引' + Symbol.keyFor(s2_1));

上图运行结果
在这里插入图片描述
第一类声明没有“记录机制”,同样的内容是不同的值,而且不能根据值反过来找索引

第二类则有“记录机制”,与第一类相反

运用
有什么用?
参考一下哈希表,至少能够用来安全、随机、可查询地在数组中存储数据…(啊,我也不知道)
(哦哦我是蒟蒻,所以我也不该知道----骄傲!)

Symbol内置值
这个对于我来说有点晦涩,而且看上去用处不是很大,
这里先暂时跳过,等我学懂了再补上…

10.迭代器

ES6中新增for-of遍历
迭代器是用来做什么的呢?就是用来遍历的,为不同的数据结构提供了同样的访问方式:
只要某种数据结构中具备iterator的接口,就可以使用迭代器遍历

首先我们来说一下两种迭代遍历:
for-in和 for-of

        const SZ3L = ['woc','NB','666'];
//普通for不用let就只能用立即执行函数了      
        for(var i = 0; i < SZ3L.length; i ++){
            (function(a){
                console.log('普通for循环',a);
            })(i);
        }

        for(let i in SZ3L){
            console.log('for-in循环:' + i);
        }
   
        for(let i of SZ3L){
            console.log('for-of循环:' + i);
        }

上图运行结果
在这里插入图片描述
可以看到,
for-in是遍历数组的下标(键),
for-of则是遍历数组的值

浅析原理
(我是废物,说不清楚)
(还得再研究一下,主要还是Symbol没学懂)
迭代器接口
迭代器工作过程简单概括为以下3步:
1.创建一个指针对象,指向当前数据结构起始位置
2.调用对象的next方法,指向下一个成员并返回一个包括value和done属性的对象
(注意是next方法返回对象)
重复这个过程,直到指向最后一个成员
3.修改done属性为true,遍历完成,停止调用next

        let iterator = SZ3L[Symbol.iterator]();

        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());

上图运行结果
在这里插入图片描述
其中,done属性是表示是否遍历完成,当访问到最后一个数据时,done的属性从false变为true,迭代器停止遍历

现在来手写一个迭代器
经过多年的研究之后,我为各位读者量身定义了reader对象,
并手写一个迭代器遍历appearance属性数组

const reader = {
            salary:"月薪10k起步",
            appearance:[
                '女美男帅',
                '墨发雪肌',
                '壮得一批'
            ],
         //迭代器
            [Symbol.iterator](){
                //先初始化一个索引
                let index = 0;
                //要返回一个类
                return{
                    //类里有next方法
                    //这里利用了箭头函数指针是静态的这一特性
                    next:()=>{
                        if(index < this.appearance.length){
                            index ++;
                            return {value:this.appearance[index], done:false};
                        }else{
                            return {value:undefined, done:true};
                        }

                    }
                }
            }
        }
        for(let i of reader.appearance){
            console.log(i);
        }

上图运行结果
女美男帅 墨发雪肌 壮的一批

11.生成器

生成器是一个特殊的函数,用于更好地解决异步编程
(虽然还是已经被更更更好的方法替代了,不过还是得学)
使用方式

//记得加星号;这不是指针;
        function * myFriends(){
            
            console.log('后端学习打卡时长排名的人数显示器');
            yield '阿波';
            console.log('明明是嵌入式的实验室却专攻后端');
            yield '陈大爷';
            console.log('算法很强的后端并且还在学Unity做游戏');
            yield '豪老板';
        } 

        let iterator = myFriends();
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());

上图运行结果
(为什么都是后端?巧合吧)
在这里插入图片描述
解析
yield相当于一条有名字的分界线,我们可以通过迭代器的next方法执行每一部分的内容

第一次调用next时,执行第一条分界线以上的内容
第二次调用next时,执行第二条以上,第一条以下的内容
以此类推…

使用方式2
生成器 和 next方法 都可以传参数

        function * gen(a){
            console.log('这是分界线1里的' + a);
            let one = yield '分界线1';
            
            console.log('分界线1的返回值' + one);
            let two = yield '分界线2';
            
            console.log('分界线2的返回值' + two);
            let three = yield '分界线3';
        }
        
        let iterator = gen('一个参数');
        console.log(iterator.next()); 
        console.log(iterator.next(233));
        console.log(iterator.next());
        console.log(iterator.next());

上图运行结果
在这里插入图片描述
生成器gen传参和普通方法一样

next方法的参数,是作为上一条分界线的返回值

比如,第二次调用next,其参数作为 yield ‘分界线1’ 的返回值
要是没有传递参数,那么yield的返回值为undefined

特性

  1. 关键字function与函数名称中间有个 *
  2. 使用了yield表达式
  3. 直接调用会返回一个迭代器对象

运用
说是优化异步编程的,那么我们来看看没有生成器的时候存在的问题:回调地狱

回调函数:将一个函数作为参数传递,但是这个函数不会立刻执行,而是会等待某个条件触发才执行
回调地狱:异步明明是没有固定执行顺序的,那么如果我们偏要它有顺序,就会出现下图这样的结构

        setTimeout(function () {  
            console.log('3s时执行第一层');
            setTimeout(function () {  
                console.log('5s时执行第二层');
                setTimeout(function () {   
                    console.log('6s时执行第三层');
                    //扶我起来,我还能继续嵌套
                }, 1000)
            }, 2000)
        }, 3000)

如果代码量少还好受,要是多了就不好说了
这种回调函数的嵌套就是回调地狱
所以我们可以通过一些方式改善这种情况,比如用生成器:

        function one(){
            setTimeout(()=>{
                console.log('3s时执行第一层');
                g.next();
            },3000)
        }
        function two(){
            setTimeout(()=>{
                console.log('5s时执行第二层');
                g.next();
            },1000)
        }
        function three(){
            setTimeout(()=>{
                console.log('6s时执行第三层');
                g.next();
            },1000)
        }
        function * gen(){
            yield one();
            yield two();
            yield three();
        }
        let g = gen();
        g.next();

上图运行结果
在这里插入图片描述
其实上面还有个一个点可以提一下,就是let明明没有了提升,g却依旧能被上面的函数访问,
和别人讨论了一下觉得应该是由于function声明的时候函数体不会展开,此时g也就没有被访问;等到g.next执行,one,two,three依次执行的时候,才依次展开,此时就可以通过作用域链向上访问到g从而能再次调用g.next…阿巴阿巴(反正大概就是那个意思)

12.Promise

promise是一个构造函数,可以用来封装异步操作,并获取到其成功和失败的结果然后据此作出反应
使用方法

//一个promise对象有三种状态:初始化状态、成功状态、失败状态
        const p = new Promise(function(resolve, reject){
            //里面要封装一个的操作
            //(大多数是异步,大多数是异步,但是你要同步也可以)
            setTimeout(function(){            
//执行resolve方法之后,p变为‘成功’状态
                let data1 = '成功了!';
                resolve(data1);//promise实例化对象的状态就会变成成功
            
//执行reject方法之后,p变为‘失败’状态
                let data2 = '失败了!';                
                reject(data2);
            },1000);
        });

       
        //成功的话执行第一个函数,失败的话执行第二个函数
        p.then(function(value){
            console.log('这是成功了:' + value);
        }, function(reason){
            console.log('这是失败了:' + reason);
        })

上图运行结果
在这里插入图片描述
从结果来看,似乎在遇到resolve方法之后就结束了而不是继续往下执行
(Promise的状态一旦变化,就不会再改变了)
另外介绍一下catch方法

        //catch方法大体上就相当于只写then方法的后半部分
        p.catch(function(reason){
            console.log('这也是失败了,不过语法糖比较甜对吧' + reason);
        })

运用
首先我们来回忆一下原生JS的AJAX
现在准备一个这样的JSON文件

{
    "key":"NB"
}

然后(这里是同一目录下)写AJAX

            httpRequest = new XMLHttpRequest();
            if (!httpRequest) {
                alert("创建请求失败");
            }
            httpRequest.open("GET", "./JSONtest.json");
            
            //莫得后端,孤寡前端人只能本地玩单机
            
            httpRequest.send();
            httpRequest.onreadystatechange = function () {
                if (httpRequest.readyState === 4) {
                    if (httpRequest.status === 200) {
                        var data = JSON.parse(httpRequest.responseText);
                        console.log('AJAX' + data['key']);
                        //别忘了和data.key的区别
                    }
                    else {
                        console.error('请求失败');
                    }
                }
            }

上图运行结果
AJAXNB

接下来我们来演示一次传说中的封装!!!

            const  P = new Promise((resolve, reject)=>{
                const xhr = new XMLHttpRequest(); 
                if(!xhr){
                    console.error('创建请求失败');
                }
    
                xhr.open("GET","./JSONtest.json");
    
                xhr.send();
    
                xhr.onreadystatechange = function(){
                    if(xhr.readyState === 4){
                        if(xhr.status === 200){
                            let data = JSON.parse(xhr.responseText)['key'];
                            resolve(data);
                        }else{
                            reject(xhr.status);
                        }
                    }
                }
            }
            );
            P.then(function(data){
                console.log('你的AJAX生了,是个' + data);
            },function(reason){
                console.log('你的AJAX是个男的' + reason);
            })

“就这?就这?这不就是把ajax装进Promise里面吗?我人傻了”
“大家懂的都懂,这种博主老水怪了
上图运行结果

本地运行,请求失败
服务器上运行,请求成功

特性(写这个的时候有点困,估计很多问题,后面再改改,现在大家看看就行)

  1. Promise.then方法的返回值:不写return默认返回一个Promise对象(是被处理之前的Promise)
    第一种:内部 回调函数 返回非Promise类型
        const P = new Promise((resolve,reject) => {
            resolve('abab');
        });

        const result = P.then(value => {
            console.log(value);
            return '我是第一种返回值(非Promise类型)';
        },reason => {
  		})

        console.log(result);

上图运行结果
在这里插入图片描述
第二种:内部 回调函数 返回Promise类型

        const P = new Promise((resolve,reject) => {
            resolve('abab');
        });

        const result = P.then(value => {
            console.log(value);
            //套娃,返回一个Promise
            return new Promise((resolve, reject) => {
            //reject使返回的这个Promise的状态为‘失败’
                reject('第二种类型:最内部promise的状态决定最终的状态')
            })
        },reason => {
        })

        console.log(result);

上图运行结果
在这里插入图片描述
第三种:throw

        const P = new Promise((resolve,reject) => {
            resolve('abab');
        });

        const result = P.then(value => {
            console.log(value);
            return new Promise((resolve, reject) => {
                reject('第三种类型:抛出错误');
            })
        },reason => {
        })

        console.log(result);

上图运行结果
在这里插入图片描述
通过观察以上三种情况,我们发现:这形成了一个链…也就避免了回调地狱的情况…

(今天写不动了…好困…团队的人还在商量着今晚去吃自助的事情…又困又饿…以后找个时间一定把这里补起来)

(时隔几天,考完了高数…promise剩下的内容以后补充)

13.Set对象

那个橘子味的夏天,少年回忆起了蝉鸣和STL类库…

特性

  1. 拥有iterator接口,可以使用迭代器和扩展运算符(…)
  2. 类似于数组,但是具有唯一性,即元素不重复

属性/方法

  1. size 返回元素个数
  2. add 增加一个新元素,返回增加元素后的集合
  3. delete 删除元素,返回一个布尔值
  4. has 查询是否包含某个元素,返回一个布尔值
  5. clear 清空,没有返回值(或者说返回undefined)

代码实例
先单独说一下add

    let s = new Set();
    //可以传入一个可迭代对象作为参数,参数用于初始化这个集合
    let s2 = new Set(['甲', '乙',  '丙', '乙', '甲']);

    console.log(s2);
    //add方法
    s2.add('one','two');
    s2.add(['a','b']);
    s2.add(...['1','2']);
    console.log(s2);

上图运行结果
在这里插入图片描述
都没什么特别的,
需要提一下的就是如果传入多个参数,只有第一个有效**(不仅局限于add,delete,has等也是如此)**

    let s = new Set();
    //可以传入一个可迭代对象作为参数,参数用于构造这个集合
    let s2 = new Set(['甲', '乙',  '丙', '乙', '甲']);

    // console.log(s2);
    s2.add('one','two');
    s2.add(['a','b']);
    s2.add(...['1','2']);
    // console.log(s2);
    
    //参数 乙 无效
    console.log(s2.delete('甲','乙'));
    console.log(s2.delete('不存在的元素'));
    console.log(s2.add('520'));
    console.log(s2.size);
    //参数666无效
    console.log(s2.has('丙','666'));

    console.log(s2.clear(),s2);

上图运行结果
在这里插入图片描述
运用
1.数组去重

   let arr = [1,2,3,3,2,1];
   //用arr创建一个集合,然后展开得到1,2,3再放进数组
   let s = [...new Set(arr)];
   console.log(s);

上图运行结果
1 2 3
2.求交集
这里顺便介绍:

14.filter

过滤器,遍历每个元素进行筛选
代码实例

     let arr = [1,2,3,2,1];
     //可以传三个参数,
     //顾名思义,结合输出结果不难理解
     let arr2 = arr.filter((value,key,arr)=>{
         console.log('这是value',value);
         console.log('这是key',key);
         console.log('这是arr',arr);

         return value > 2 ? true : false;
     })
     console.log('这是过滤之后的结果',arr2);

数组长度是5,函数执行了5次遍历了每个元素,筛选出了大于2元素
遍历5次,结果只剩一个3

好了我们继续看我们的求交集

    let arr = [1,2,3,4,3,2,1];
    let arr2 = [1,2,1];
    let s2 = new Set(arr2);

    let s1 = new Set(arr.filter((value)=>{
        return s2.has(value) ? true : false;
    }));
    
    console.log(s1);

1 2
3.求并集
这个就没啥说的了

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

在这里插入图片描述
4.求补集
其实也就和求交集一个意思

    let arr = [1,2,3,4];
    let arr2 = [1];
    let s2 = new Set(arr2);

    let s = new Set(arr.filter((value)=>{
        return s2.has(value) ? false : true;
    }));

    console.log(s);

不过这里有八十岁老爷爷看了都说牛逼的简化:

    let arr = [1,2,3,4];
    let arr2 = [1];

    let s = new Set(arr.filter((value)=>{
        return !new Set(arr2).has(value);
    }));

    console.log(s);

2 3 4

15.map对象

其实就是键值对
特性

  1. 又是一个自带iterator接口的

属性/方法

  1. size 长度
  2. set 添加元素
  3. has 查询是否存在
  4. clear 清空
  5. get 通过键传入值
  6. delete 通过键删除元素

代码实例

    let m = new Map();
    m.set(233,'键233的值');

    let obj = {name:'一个对象'};
    m.set(obj,'键对象的值');
    console.log('m.get(233):', m.get(233));
    console.log('m.get(obj):', m.get(obj));
    console.log('m.has(obj)',m.has(obj));
    
    console.log('m.size:',m.size);

    console.log('clear之前:',m);
    m.clear();
    console.log('clear之后:',m);

在这里插入图片描述

16.class类

先回顾一下构造函数实例化对象

    function Person1(name, age){
        this.name = name;
        this.age = age;
    }

    Person1.prototype.speak = function(){
        console.log('I\'m the ' + this.name +' DEEP! DARK! FANTASY♂!');
    }

    let somebody1 = new Person1('黑暗之王',18);
    
    somebody1.speak();

在这里插入图片描述

class类实例化对象(javar狂喜)

    class Person2{
        //构造器
        constructor(name, age){
           this.name = name;
           this.age = age;
        }
        speak(){
            console.log('我是' + this.name + ',我是不朽的');
        }
    }

    let somebody2 = new Person2('玛尔加尼斯',5);
    somebody2.speak();

在这里插入图片描述
static静态
不论新旧,都有这样一手操作:

    class Coder1{
        //什么都没有哦
    }
    function Coder2(){
        //意思是程序员一无所有[bushi
    }
    Coder1.name = '知鑫';
    Coder2.name = '雨溪';
    

    let coder1 = new Coder1();
    let coder2 = new Coder2();
    
    console.log('红尘作伴,代码潇潇洒洒~');
    console.log(coder1.name,coder2.name);

快快乐乐,昂第佛爱德~
两个undefined
通过上述方式添加的成员,只属于构造函数而不属于实例化对象.

上述写法相当于
(static只能在class类里面合法)

    class Coder3{
        static name = '日娃';
    }
    let coder3 = new Coder3();
    console.log('无名英雄,程序员:' + coder3.name);

无名英雄的名字当然是undefined啊!
undefined
继承
又让我们先回顾构造函数如何继承吧
(JS高级的原型链…说实话我也快忘完了)

    function Win10(info, bugs){
        this.info = info;
        this.bugs = bugs;
    }
    function Win11(info, bugs, moreBugs){
        Win10.call(this,info,bugs);
        this.moreBugs = moreBugs;
    }

    Win11.prototype = new Win10;
    Win11.prototype.constructor = Win11;//纠正Win11的构造函数 

    Win11.prototype.start = function(){
        console.log('绿屏了');
    }

    let newSystem = new Win11('最后一代?从来没说过','挺多','更多了');

    console.log(newSystem);
    newSystem.start();

在这里插入图片描述
啥?为啥方法要写到prototype里面而不是直接写到对象里面?(上一节static静态才说了

class继承

    class Win10{
        constructor(info,bugs){
            this.info = info;
            this.bugs = bugs;
        }
    }

    class Win11 extends Win10{
        constructor(info,bugs,moreBugs){
            super(info,bugs);
            moreBugs = moreBugs;
        }

        start(){
            console.log('绿屏了');
        }
    }

    let mySystem = new Win11('谁说win10是最后一代了?','有bug','更多bug!');
    mySystem.start();
    console.log('mySystem:',mySystem);

运行结果
虽然看上去和JAVA差不多了,但是实际上还是原型链的封装
子类对父类方法的重写也一样,其实只是原型链的知识…

17.get与set

    class Coder{
        get whyWeLive(){
            console.log('为了吃饭');
            return false;
        }

        set whyWeLive(dream){
            console.log('为了理想');
            return true;
        }
    }
    
    let us = new Coder();
    let ans = us.whyWeLive; //访问,触发get部分
    console.log(ans);
    us.whyWeLive = '为更多的人创造更好的世界';//修改,触发set部分

注意whyWeLive是属性不是方法,
get修饰是指,在该属性被访问的时候,调用后面的函数
set修饰是指,在该属性被修改的时候,调用后面的函数

在这里插入图片描述
人生来不是为了吃饭,我们还有理想

18.数值扩展

感觉这部分也没什么好说的,了解一下就行

    //1.误差(最小精度)
        console.log('0.1 + 0.2 === 0.3', 0.1 + 0.2 === 0.3);
        function equal(a, b){
            return Math.abs(a - b) < Number.EPSILON ? true : false;
            //EPSILON是一个极其小的数字
        }
        console.log('equal(0.1 + 0.2, 0.3):', equal(0.1 + 0.2, 0.3));
    //2.更多的进制
    let a = 20;
    let b = 0b10100;
    let c = 0o24;
    let d = 0x14;
    console.log('十进制', a, '二进制', b, '八进制', c, '十六进制', d);
    //3.更多方法
    console.log('Number.isNaN(100 / 0):', Number.isNaN(100 / 0));
    console.log('Number.isFinite(100 / 0):', Number.isFinite(100 / 0));
    console.log('Number.isInteger(2.3):', Number.isInteger(2.3));
    console.log('Number.parseInt(\'2333ababa66\'):', Number.parseInt('2333ababa66'));
    console.log('Number.parseFloat(\'1.7321abcd\'):', Number.parseFloat('1.7321abcd'));
    console.log('Math.trunc(4.33):', Math.trunc(4.33),'Number.parseInt(\'4.33\'):', Number.parseInt(4.33));
    console.log('Math.sign(0):',Math.sign(0),'Math.sign(-666):',Math.sign(-666));
 

唯一需要注意的是这里的equal方法是用EPSILON属性实现的,不是JS自带的方法
在这里插入图片描述

19.Object方法扩展

    //1.Object.is 判断两个值是否完全相等
    console.log('Object.is(NaN, NaN)',Object.is(NaN, NaN),'NaN === NaN',NaN === NaN);
    
    //2.Object.assign 合并对象
    function A(name, age){
        this.name = name;
        this.age = age;
    }

    function B(name,sex){
        this.name = name;
        this.sex = sex;

    }

    let a = new A('A',18);
    let b = new B('B','女');

    console.log('Object.assign(a,b)',Object.assign(a,b));
  
    //3.Object.setPrototypeOf 设置原型对象
    //4.Object.getPrototypeof 获取原型对象
    let C = {
       name: 'C'
    };
    let D ={
        age: 33
    }
    Object.setPrototypeOf(C, D);
    console.log('Object.setPrototypeOf(C, D):' , C);
    console.log('Object.getPrototypeOf(C):' , Object.getPrototypeOf(C));

在这里插入图片描述
在这里插入图片描述

20.module模块化

把丑陋的代码实现包起来,只留出接口给外面看
(比如写一个冒泡排序,接口名字叫做快速排序,别人调用的时候就会觉得————好耶)

而且模块之间的内容是互不影响的,避免了污染

首先在同一目录下创建一个moduleTest.js文件,内容是

其中export修饰的内容会被暴露

export let date = '2021/07/05';

export function myRecentLife(){
    console.log('还在进行因为疫情被推迟的军训..');
    console.log('我想躺着写代码啊!!!');
    console.log('我想吃肉!!!');
}

然后另一边,我们这样写

<script type="module">
    //模块化必须在服务器上测试
    //(本地折腾半天没有输出...)
    import {date} from "./moduleTest.js";
    console.log(date);
    import * as m from './moduleTest.js';
    //这个语句很像SQL,语义化也很强
    //*是啥?参考一下css的*就知道了
    console.log(m);
    m.myRecentLife();
</script>

上图运行结果(一定要在服务器上运行啊!不然没有反应的
在这里插入图片描述
注意事项
假如引入的两个模块中有重名内容,
比如
在这里插入图片描述
那么我们可以使用关键字as操作一手:

import {date} from "./moduleTest.js";
import {date as date2} from "./moduleTest2.js";

console.log("date:",date,"\ndate2:",date2);  

(记得要在服务器上运行啊!!!)
在这里插入图片描述

后记

ES6大概就这样结束了,不过我还是想写下这多余的话

ES6更新了很多东西,这篇笔记是我一边学习一遍写代码做记录产生的,也是第一次接触到其中一些内容,所以难免有漏掉部分知识点,和理解分析不到位的情况,希望大家包涵谅解

后面如果有机会的话,我也会继续做ES相关的内容

祝大家能够不断进步

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

碳苯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值