前端工程化15-邂逅ES6的语法规范

4、ES6邂逅

3.1、什么是ECMA

ECMA(European Computer Manufacturers Association)中文名为欧洲计算机制造商协会,这个组织的目标是评估、开发和认可电信和计算机标准。1

994年后该组织改名为Ecma国际。

3.2、什么是ECMAScript

ECMAScript 是由Ecma国际通过ECMA-262标准化的脚本程序设计语言

3.3、什么是ECMA-262

Ecma国际制定了许多标准,而ECMA-262只是其中的一个,所有标准列表查看

http://www.ecma-international.org/publications/standards/Standard.htm

3.4、ECMA262历史

ECMA-262(ECMAScript)历史版本查看网址

第1版 1997年 制定了语言的基本语法
第2版 1998年 较小改动
第3版 1999年 引入正则、异常处理、格式化输出等。IE开始支持
第4版 2007年 过于激进,未发布
第5版 2009年 引入严格模式、JSON,扩展对象、数组、原型、字符串、日期方法
第6版 2015年 模块化、面向对象语法、Promise、箭头函数、let、const、数组解构赋值等等
第7版 2016年 幂运算符、数组扩展、Async/await关键字
第8版 2017年 Async/await、字符串扩展
第9版 2018年 对象解构赋值、正则扩展
第10版 2019年 扩展对象、数组方法
ES.next 动态指向下一个版本

注:从ES6开始,每年发布一个版本,版本号比年份最后一位大1

3.5、谁在维护ECMA262

TC39(Technical Committee 39)是推进 ECMAScript 发展的委员会。其会员都是公司(其中主要是浏览器厂商,有苹果、谷歌、微软、因特尔等)。TC39 定期召开会议,会议由会员公司的代表与特邀专家出席

3.6、为什么要学习ES6

ES6的版本变动内容最多,具有里程碑意义

ES6加入许多新的语法特性,编程实现更简单、高效

ES6是前端发展趋势,就业必备技能

3.8、ES6兼容性

https://compat-table.github.io/compat-table/es6/ 可查看兼容性

3.9、ES6的Let关键字

let关键字用来声明变量,使用let声明的变量有几个特点:

  • 不允许重复声明
  • 块儿级作用域
  • 不存在变量提升

应用场景:以后声明变量使用let就对了

代码实战

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>let</title>
</head>
<body>
    <script>
        //let 声明变量
        let a;          //字母数字下划线, 首字母不能为数字, 严格区分大小写, 不能使用关键字   驼峰
        let b = 100;
        let c,d,e;
        let f=100,g=200,h=300;

        //let 声明特点
        //1. 不允许重复声明
        // let star = '罗志祥';
        // let star = '小猪';
        
        //2. 块儿级作用域  if(){}  else {}  for(){}   {}   function(){}
        // if(true){
        //     let girlFriend = '周扬青';
        // }
        // console.log(girlFriend);

        //3. 不存在变量提升
        // console.log(song);
        // let song = '狐狸精';

        //4. 不影响作用域链
        // function fn(){
        //     let dance = '精武门';
        //     function b(){
        //         console.log(dance);
        //     }
        //     b();
        // }
        // fn();
        
    </script>
</body>
</html>

3.1、let实践案例

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>点击 DIV 换色</title>
    <style>
        .item {
            width: 100px;
            height: 50px;
            border: solid 1px rgb(42, 156, 156);
            float: left;
            margin-right: 10px;
        }
    </style>
</head>

<body>
    <div class="container">
        <h2 class="page-header">点击切换颜色</h2>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
    </div>
    <script>
        //获取元素对象
        let items = document.querySelectorAll('.item');

        //用this实现
        // for(var i=0;i<items.length;i++){
        //     //绑定事件
        //     items[i].onclick = function(){
        //         //
        //         this.style.background = 'pink';
        //     }
        // }

        //遍历并绑定事件
        // for(let i=0;i<items.length;i++){
        //     //绑定事件
        //     items[i].onclick = function(){
        //         //
        //         items[i].style.background = 'pink';
        //     }
        // }

        // ES5 模拟实现
        for(var i=0;i<items.length;i++){
            (function(i){
                //绑定事件
                items[i].onclick = function(){
                    //
                    items[i].style.background = 'pink';
                }
            })(i)
        }
    </script>
</body>

</html>

3.4、ES6的const关键字

const 关键字用来声明常量,const声明有以下特点

  • 声明一定要赋初始值

  • 不允许重复声明

  • 值不允许修改

  • 块儿级作用域

注意:对象属性修改和数组元素变化不会出发const错误

应用场景:声明对象类型使用const,非对象类型声明选择let

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>const 定义常量</title>
</head>
<body>
    <script>
        //const 用来声明一个常量(值不变) let a
        //0. 格式
        // const a = 100;  
        //1. 声明的时候一定要赋初始值
        const PLAYER = 'UZI';
        //2. 常量的名称一般为 『大写』  潜规则
        const RESOLVED = 'resolved';
        //3. 不能修改常量的值
        // PLAYER = '小狗';
        //4. 不允许重复声明
        // const PLAYER = 'abc';
        //5. 块儿级作用域
        // {
        //     const A = 100;
        // }
        // console.log(A);
        //6. 关于数组和对象的元素的修改
        // const TEAM = ['UZI','MLXG','LETME'];
        // TEAM.push('XIYE');
        // console.log(TEAM);
        // const BIN = {
        //     name: 'BIN'
        // }
        // BIN.name = '阿斌';
        // console.log(BIN);
    </script>
</body>
</html>

3.5、ES6变量的结构赋值

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

注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>变量的解构赋值</title>
</head>
<body>
    <script>
        //解构赋值
        // const arr = ['宋小宝','刘能','赵四','小沈阳'];
        // let [song, liu, zhao, xiao] = arr;
        // console.log(song, liu, zhao, xiao);

        //对象解构赋值
        const star = {
            name: '于谦',
            tags: ['抽烟','喝酒','烫头'],
            say: function(){
                console.log('我可以说相声');
            }
        };
        let {name, tags:[chou,he,tang], say} = star;

        // console.log(name);
        // console.log(tags);
        // console.log(say);

        console.log(chou)
        console.log(he)
        console.log(tang)

        
    </script>
</body>

</html>

3.6、模板字符串

模板字符串(template string)是增强版的字符串,用反引号(`)标识,

特点:

  • 字符串中可以出现换行符
  • 可以使用 ${xxx} 形式输出变量
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>模板字符串</title>
</head>
<body>
    <script>
        //1. 直接使用换行符
        let str = `<ul>
                <li>沈腾</li>
                <li>马丽</li>
                <li>艾伦</li>
                <li>魏翔</li>
            </ul>`;
            
        //2. 字符串中进行变量拼接
        let star = '魏翔';
        let str2 = `我特别喜欢 ${star}, 搞笑风格诡异`;

        console.log(str2);
    </script>
</body>
</html>

3.7、简化对象写法

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

注意:对象简写形式简化了代码,所以以后用简写就对了

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>简化对象写法</title>
</head>
<body>
    <script>
        let name = '茂昌';
        let pos = '邯郸';
        let change = function(){
            console.log('改变');
        }
        
        //简写前
        const renOne = {
            name:name,
            pos:pos,
            change:change,
            improve:function(){
                console.log('提升');
            }
        }
        //简写后 
        const renTwo = {
            name,
            pos,
            change,
            improve(){
                console.log('提升');
            }
        }
        console.log(renOne)
        console.log(renTwo)

    </script>
</body>
</html>

3.8、箭头函数

ES6 允许使用「箭头」(=>)定义函数。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>箭头函数</title>
</head>
<body>
    <script>
        // ES6 允许使用「箭头」(=>)定义函数。
        //1. 声明格式 
        // let add = (a,b,c) => {
        //     let result = a + b + c;
        //     return result;
        // };
        //2. 函数调用
        // console.log(add(1,2,3));
        // console.log(add.call({}, 1,2,3));
        // console.log(add.apply({}, [1,2,3]));

        // 箭头函数特点 
        // 1. this 的值是静态的. (指向声明时所在作用域下this的值)
        // let getName2 = () => {
        //     console.log(this);
        // }
        // getName2.call({}); 外层作用域下的this值

        // 2. 不能作为构造函数使用
        // const Person = () => {}
        // let me = new Person();

        // 3. 不能使用 arguments 
        // const fn = () => {
        //     console.log(arguments);
        // }
        // fn(1,3,5,8,10);

        // 4. 箭头函数简写
        // 一 不写小括号, 当形参有且只有一个的时候
        // 二 不写花括号, 当代码体只有一条语句的时候, 并且语句的执行结果为函数返回值的 (如果不写花括号的话, return 也不能写)
        // let pow = num =>  num * num * num;
        let rand = (m,n) => Math.ceil(Math.random() * (n-m+1)) + m-1;

        // console.log(pow(9));
        console.log(rand(1,100));
    </script>
</body>
</html>

箭头函数的注意点:

  • 箭头函数this指向声明时所在作用域下 this 的值

  • 箭头函数不能作为构造函数实例化

  • 箭头函数内没有arguments

  • 如果形参只有一个,则小括号可以省略

  • 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果

3.9、箭头函数的最佳实现

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>箭头函数实践</title>
    <style>
        div {
            width: 200px;
            height: 200px;
            background: #58a;
        }
    </style>
</head>
<body>
    <div id="ad"></div>
    <script>
        //需求-1  点击 div 2s 后颜色变成「粉色」
        const ad = document.getElementById('ad');
        //绑定事件
        ad.onclick = function(){
            //保存 this 的值  that  self  _this
            // let that = this
            // setTimeout(function(){
            //     that.style.background = 'pink';
            // }, 2000);

            setTimeout(() => {
                this.style.background = 'pink';
            }, 2000)
        }

        //需求-2  从数组中返回偶数的元素
        const arr = [1,2,31,2,321,41,24,12,51,24,12,43,145,1,51,5,43,5,43,6,436];

        //遍历  filter 过滤
        // const result = arr.filter(function(item){
        //     //判断是否为偶数
        //     if(item % 2 === 0){
        //         return true;
        //     }else{
        //         return false;
        //     }
        // });

        const result = arr.filter(item => item % 2 === 0);

        console.log(result);

        //如果回调与this的值是相关的, 则不能使用箭头函数
        //1. 事件的回调
        // ad.onclick = () => {
        //     console.log(this);
        // }
        //2. 对象的方法
        // let f = () => {
        //     console.log(this);
        // };
        // var obj = {
        //     run: function(){
        //         console.log(this);
        //     },
        //     run2: f
        // }
        // // obj.run();
        // obj.run2();

        //如果回调与 this 是无关的
        //1. 定时器
        //2. 数组方法回调  filter  forEach  map

    </script>
</body>

</html>

3.1、函数参数默认值

注意: 参数直接设置默认值 具有默认值的参数, 位置一般要靠后(潜规则)

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>函数参数默认值</title>
</head>
<body>
    <script>
        //ES6 允许给函数参数赋值初始值
        //1. 参数直接设置默认值  具有默认值的参数, 位置一般要靠后(潜规则)  ---很重要
        function add(a,b=10,c){
            console.log(a + b + c);
        }
        // add(1,2,4);
        // add(1,2);

        //2. 与解构赋值结合使用   结构赋值的形式先后顺序不影响
        function connect({host="127.0.0.1", port, pass, dbname}){
            console.log(host);
            console.log(port);
            console.log(pass);
            console.log(dbname);
        }

        connect({
            port: 27017,
            pass: 'root',
            dbname: 'project'
        });
        
    </script>
</body>
</html>

3.2、rest参数

主要是用来替代arguments获取实参的

注意事项,出现a,b,...args写到最后,

什么时候用rest参数:出现不定个数参数的函数比如求最大值最小值,你也不知道传递多少个参数进来,那我们就用rest参数来接收

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>rest参数</title>
</head>
<body>
    <script>
        //arguments
        function main(...args){
            //1. 使用 arguments 获取实参
            console.log(arguments); //对象
            //2. rest 参数
            console.log(args); //数组
        }
        main(1,5,10,20,25);// 1,5,10,20,25  => ...[1,5,10,20,25] => 1,5,10,20,25

        //2. 如果有多个参数,rest参数必须放到最后
        // function fn(a,b,...args){
        //     console.log(a);
        //     console.log(b);
        //     console.log(args);
        // }
        // fn(1,2,3,4,5,6,7);
    </script>
</body>
</html>

3.3、spread扩展运算符

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>扩展运算符 ****</title>
</head>
<body>
    <script>
        //数组的展开  
        const arr = ['王源','易烊千玺','王俊凯'];
        function fn(){
            console.log(arguments);
        }
        fn(...arr);// ...arr  => ...['王源','易烊千玺','王俊凯']  =>  '王源','易烊千玺','王俊凯'
        //fn('王源','易烊千玺','王俊凯');

        //对象的展开   ...skillOne =>  q:'天音波'
        // const skillOne = {
        //     q: '天音波',
        //     f:'闪现'
        // };
        // const skillTwo = {
        //     w: '金钟罩'
        // };
        // const skillThree = {
        //     e: '天雷破'
        // };
        // const skillFour = {
        //     r: '猛龙摆尾',
        //     q: 'xxx'
        // };
        
        //把对象的属性加入到一个新对象中    
        //const mangseng = {...skillOne, ...skillTwo, ...skillThree, ...skillFour};

       // console.log(mangseng);
        
    </script>
    
</body>
</html>

3.4、spread扩展运算符应用

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>扩展运算符应用</title>
</head>
<body>
    <div></div>
    <div></div>
    <div></div>
    <script>
        //1. 数组的合并 
        // const kuaizi = ['肖央','王太利'];
        // const chuanqi = ['曾毅','玲花'];
        // const zuhe = [...kuaizi, ...chuanqi];
        // console.log(zuhe);
        //2. 新数组克隆
        // const jinhua = ['e','g','m'];//
        // const s = [...jinhua,'x','y','z'];
        // console.log(s);
        //3. 将伪数组转为真正的数组
        const divs = document.querySelectorAll('div');
        //
        const result = [...divs];

        console.log(result);
    </script>
</body>
</html>

3.5、symbol

ES6中的数据类型总共有七中

1、boolean(布尔型)2、null(空类型)3、undefined(未赋值类型)

4、number(数值类型)5、string(字符串类型)6、symbol(独一无二类型)7、object(对象类型)。

ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。

Symbol特点

  • Symbol的值是唯一的,用来解决命名冲突的问题
  • Symbol值不能与其他数据进行运算
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>symbol</title>
</head>
<body>
    <script>
        //ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值
        
        //1. 创建 Symbol
        let s1 = Symbol();
        console.log(s1, typeof s1);
        //2. 创建 Symbol
        // let s2 = Symbol('品牌');
        // let s3 = Symbol('品牌');
        // console.log(s2 === s3);
        //3. 创建 Symbol ----函数对象
        let s4 = Symbol.for('200826');
        let s5 = Symbol.for('200826');
        console.log(s4 === s5);

       // symbol 不能与其他类型数据进行运算
        // const result = s1 + 123;

    </script>
</body>
</html> 

3.6、symbol的使用场景

注意:Symbol类型唯一合理的用法是用变量存储 symbol的值,然后使用存储的值创建对象属性

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Symbol 创建对象属性</title>
</head>
<body>
    <script>
        //向对象中添加方法 up down 
        let method = {
            up: Symbol(),
            down: Symbol()
        }
        let str = 'run';

        //未知的对象,直接添加方法会有风险,因为可能已经存在了对应的方法
        //直接添加会造成属性的冲突和覆盖
        let game = {
            name:'俄罗斯方块' ,
            up: function(){

            },
            //内部添加方法
            [str]: function(){
                
            },
            //内部添加方法用up
            [method.up]: function(){
                console.log('UP UP UP');
            }
        };

        // console.log(game);
        game[method.up]();

        

        //添加 up 方法
        // game[method.up] = function(){
        //     console.log('向上移动');
        // }
        // game[method.up]();

    </script>
</body>
</html>

3.7、Symbol内置属性

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Symbol内置属性</title>
</head>
<body>
    <script>
        // Symbol.replace
        let obj = {
            [Symbol.replace]: function(){
                console.log('我被replace方法调用了');
            }
        }
        //声明字符串
        let str = 'i love you';
        //调用 replace 方法
        let result = str.replace(obj, 'xxx');
    </script>
</body>
</html>

被动调用的、我没有进行手动的触发

Symbol.hasInstance 当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法
Symbol.isConcatSpreadable 对象的Symbol.isConcatSpreadable属性等于的是一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开。
Symbol. unscopables 该对象指定了使用with关键字时,哪些属性会被with环境排除。
Symbol.match 当执行str.match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值。
Symbol.replace 当该对象被str.replace(myObject)方法调用时,会返回该方法的返回值。
Symbol.search 当该对象被str. search (myObject)方法调用时,会返回该方法的返回值。
Symbol.split 当该对象被str. split (myObject)方法调用时,会返回该方法的返回值。
Symbol.iterator 对象进行for...of循环时,会调用Symbol.iterator方法,返回该对象的默认遍历器
Symbol.toPrimitive 该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。
Symbol. toStringTag 在该对象上面调用toString方法时,返回该方法的返回值
Symbol.species 创建衍生对象时,会使用该属性

3.8、迭代器

迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。

  • ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费
  • 原生具备iterator接口的数据(可用for of遍历)
    • Array
    • Arguments
    • Set
    • Map
    • String
    • TypedArray
    • NodeList
  • 工作原理
    • 创建一个指针对象,指向当前数据结构的起始位置
    • 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
    • 接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
    • 每调用next方法返回一个包含value和done属性的对象

注意: 需要自定义遍历数据的时候,要想到迭代器。

ctrl+shift+i 打开控制台

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>迭代器</title>
</head>
<body>
    <script>
        const arr = ['刘德华','黎明','郭富城','张学友'];

        //for...of 遍历
        for(let v of arr) {
            console.log(v);
        }

        //得到 iterator     
        const iterator = arr[Symbol.iterator]();

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

        // {value: '', done: true}

        // for(let i in arr){
        //     console.log(i);
        // }
        
    </script>
</body>
</html>

for of 和for in的区别 前置拿到的是值,后者拿到的是下标

3.9、迭代器自定义遍历数据

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自定义遍历数据</title>
</head>
<body>
    <script>
        const team = {
            name: '终极一班',
            members: [
                'xiaoming',
                'xiaoning',
                'xiaotian',
                'knight'
            ],
            //添加 Symbol.iterator
            [Symbol.iterator]: function(){
                let index = 0;
                return {
                    next: () => {
                        //声明对象
                        const result = {value: this.members[index], done: false};
                        //判断下标 修改 『done』 属性的值
                        if(index >= this.members.length){
                            result.done = true;
                        }
                        //下标自增
                        index++;
                        //返回结果
                        return result;
                    }
                }
            }
        }
        
        //需求
        for(let v of team){
            console.log(v);
        }

        //可以
        for(let v of team.members){}

        //可以--为啥要费劲的去实现这个需求  -->面向对象编程思想--满足
        team.members.forEach();
        
    </script>
</body>

</html>

4.1、set集合

ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,可以使用『扩展运算符』和『for...of...』进行遍历,

集合的属性和方法:

  • size 返回集合的元素个数
  • add 增加一个新元素,返回当前集合
  • delete 删除元素,返回boolean 值
  • has 检测集合中是否包含某个元素,返回boolean值
  • clear 清空集合,返回undefined
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>集合</title>
</head>
<body>
    <script>
        //声明集合
        // const s = new Set();
        const s2 = new Set([1,5,9,13,17,1,5]);

        //1. 元素个数
        // console.log(s2.size);
        //2. 添加
        // s2.add(21);
        //3. 删除
        // s2.delete(5);
        //4. 检测集合中是否包含某个元素  has  有
        // console.log(s2.has(90));
        //5. clear 清空
        // s2.clear();

        // console.log(s2);
        //6. for...of 遍历
        // for(let v of s2){
        //     console.log(v);
        // }
    </script>
</body>
</html>

4.2、set集合实战

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>实践</title>
</head>
<body>
    <script>
        //1. 数组去重  
        const arr = ['大事儿','小事儿','好事儿','坏事儿','小事儿'];
        //集合
        // const s = new Set(arr);
        // const result = [...s];
        // console.log(result);

        //2. 交集
        const arr1 = [1,2,3,4,5,1,2];
        const arr2 = [3,4,5,4,5,6];

        // const result = [...new Set(arr1)].filter(item => {
        //     return (new Set(arr2)).has(item);
        // });
        // console.log(result);

        //3. 并集
        // const result = [...new Set([...new Set(arr1),...new Set(arr2)])];

        //4. 差集
        const result = [...new Set(arr1)].filter(item => {
            return !(new Set(arr2)).has(item);
        });
        console.log(result);

    </script>
</body>
</html>

4.3、Map集合

ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是"键"的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator接口,所以可以使用『扩展运算符』和『for...of...』进行遍历。

Map的属性和方法:

  • size 返回Map的元素个数
  • set 增加一个新元素,返回当前Map
  • get 返回键名对象的键值
  • has 检测Map中是否包含某个元素,返回boolean值
  • clear 清空集合,返回undefined
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Map</title>
</head>
<body>
    <script>
        //缓存--->比如搜索栏存第一次的推荐搜索数据
        //声明 Map    m.name = 'xiaohua';
        const m = new Map();
        //添加元素
        let key = {};
        m.set('mei', '小橙子');
        m.set(key, 'atguigu');
        //获取元素
        // console.log(m.get('mei'));
        // console.log(m.get(key));
        //删除元素
        // m.delete('mei');
        //检测
        // console.log(m.has('meix'));
        //元素个数
        // console.log(m.size);
        //清空
        // m.clear();
        // console.log(m);
    </script>
</body>
</html>

4.4、class介绍与类创建

ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>对象声明</title>
</head>
<body>
    <script>
        //创建对象的方式 new Object  {}  工厂函数  构造函数  Object.create
        // function Phone(brand, price){
        //     this.brand = brand;
        //     this.price = price;
        // }
        // //添加方法
        // Phone.prototype.call = function(someone){
        //     console.log(`我可以给 ${someone} 打电话`);
        // }
        // Phone.prototype.sendMessage = function(someone){
        //     console.log(`我可以给 ${someone} 发送短信`);
        // }

        // //实例化对象
        // const nokia = new Phone('诺基亚', 223);

        //语法
        class Phone {
            //构造方法--名字必须为这个
            constructor(brand, price){
                this.brand = brand;
                this.price = price;
            }
            //方法
            call(someone){
                console.log(`我可以给 ${someone} 打电话`);
            }
            sendMessage(someone){
                console.log(`我可以给 ${someone} 发送短信`);
            }
        }

        const jinli = new Phone('金立', 599);
        console.log(jinli);


        
        //1.构造方法不是必须的
        class A{
            //2. 构造方法只能有一个
            constructor(){}
            constructor(){}
        }

        let a = new A();

        console.log(a);

    </script>
</body>
</html>

4.5、对象的静态属性和方法

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>静态成员</title>
</head>
<body>
    <script>
        //
        // function Phone(brand){
        //     //为实例对象添加属性
        //     this.brand = brand;
        // }
        // //为函数对象添加属性
        // Phone.name = '手机';//又称之为 静态成员
        // Phone.change = function(){
        //     console.log('改变了世界');
        // }
        // //
        // let nokia = new Phone('诺基亚');
        // console.log(nokia);
        // console.dir(Phone);

        class Phone{
            //static 静态的
            static name = '手机';
            static change(){
                console.log("我改变了世界");
            }
        }

        console.log(Phone.name);
        Phone.change();

    </script>
</body>
</html>

4.6、ES5中如何实现继承

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>对象继承</title>
</head>
<body>
    <script>
        //父类
        function Phone(brand, price){
            this.brand = brand;
            this.price = price;
        }
        //添加原型方法
        Phone.prototype.call = function(someone){
            console.log(`我可以给 ${someone} 打电话`);
        }
        //添加原型方法
        Phone.prototype.sendMessage = function(someone){
            console.log(`我可以给 ${someone} 发送短信`);
        }

        //小手机
        function SmartPhone(brand, price, storage, pixel){
            //调用父类的函数  属性的初始化
            Phone.call(this, brand, price);
            //初始化
            this.storage = storage;
            this.pixel = pixel;
        }
        //子类的prototype应该等于父类的示例
        SmartPhone.prototype = new Phone;
        //添加子类自己的构造方法
        SmartPhone.prototype.constructor = SmartPhone;
        //添加子类特有的方法
        SmartPhone.prototype.playGame = function(){
            console.log('我可以用来玩游戏');
        }
        SmartPhone.prototype.takePhoto = function(){
            console.log('可以拍照');
        }
        //实例化
        const mate4 = new SmartPhone('华为', 7000, '256G','2000w');
        console.log(mate4);



    </script>
</body>
</html>

4.7、ES6实现对象继承

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>对象继承</title>
</head>
<body>
    <script>
        class Phone {
            //构造方法
            constructor(brand, price){
                this.brand = brand;
                this.price = price;
            }
            //方法
            call(someone){
                console.log(`我可以给 ${someone} 打电话`);
            }
            sendMessage(someone){
                console.log(`我可以给 ${someone} 发送短信`);
            }
        }

        //子类  extends 继承  多态
        class SmartPhone extends Phone{
            //构造方法
            constructor(brand, price, storage, pixel){
                //调用父类的构造方法 属性初始化
                super(brand, price);//super 超级
                this.storage = storage;
                this.pixel = pixel;
            }
            //子类对象的方法
            playGame(){
                console.log('我可以用来玩游戏');
            }
            takePhoto(){
                console.log('可以拍照');
            }
        }

        //实例化对象
        const onePlus = new SmartPhone('小米10', 4299, '128G','一个亿');

        console.log(onePlus);
        // onePlus.call('孙俪');
    
    </script>
</body>
</html>

4.8、ES6对象的get 和 set方法

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>get 和 set </title>
</head>
<body>
    <script>
        class Phone{
            get price(){
                // console.log('我被获取了');
                return 2999;
            }

            set price(v){
                this.jiage = v;
            }   

            static get size(){
                return '5.5inch';
            }

            static set size(value){
                this.chicun = value;
            }

        }
        let chuizi = new Phone();
        //属性的获取
        // console.log(chuizi.price);
        //属性的设置
        // chuizi.price = 1599;
        //属性的获取
        // let res = Phone.size;
        // console.log(res);
        //静态属性的设置
        Phone.size = '6inch';
        console.dir(Phone);

    </script>
</body>
</html>

4.9、ES6的数值扩展

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>数值扩展</title>
</head>
<body>
    <script>
        //1. 二进制和八进制    4 (16)  8(256)   16(65536)
        // let n = 0b1111;// 
        // let n2 = 0o666;
        // let n3 = 1024;// 顶  赞
        // let n4 = 0xff;
        // console.log(n4);

        //2. Number.isFinite  检测一个数值是否为有限数
        // console.log(Number.isFinite(10));
        // console.log(Number.isFinite(Math.PI));
        // console.log(Number.isFinite(1/0));
        
        //3. Number.isNaN 检测一个数值是否为 NaN  isNaN
        // console.log(Number.isNaN(NaN));

        //4. Number.parseInt 字符串转整数 
        // console.log(Number.parseInt('5211314love'));
        // console.log(Number('5211314love'));

        //5. Math.trunc 将数字的小数部分抹掉 
        // console.log(Math.trunc(3.1415926));

        //6. Number.isInteger 判断一个数是否为整数 is 是否 integer 整型
        // console.log(Number.isInteger(3.2));
        // console.log(Number.isInteger(3));

        //7. 幂运算  (ES7)    Math.pow()
        console.log(3 ** 10);

    </script>
</body>
</html>

4.1、ES6的对象拓展

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>对象扩展</title>
</head>
<body>
    <script>
        //1. 判断两个值是否完全相等  ===  Object.is
        // let n = 100;
        // let n2 = 200;
        // console.log(Object.is(n, n2));
        // console.log(Object.is(NaN, NaN));// NaN === NaN

        //2. Object.assign 对象的合并
        // const A = {
        //     name: 'lsy'
        // }

        // const B = {
        //     pos: ["北京",'上海','深圳'],
        //     name: '后茂昌'
        // }

        // const C = {
        //     name: 'hmc'
        // }

        // const res = Object.assign(A, B, C);
        // console.log(res === A);
        // console.log(A);

        //3. 直接修改 __proto__ 设置原型
        // const A = {
        //     name: '父级'
        // }
        // const B = {
        //     test: '测试'
        // }
        // B.__proto__ = A;

        // console.log(B);
       
    </script>
</body>
</html>

4.2、ES6数据的浅拷贝

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>浅拷贝</title>
</head>
<body>
    <script>
        //拷贝 就是 复制   对象和数组
        //1. 直接复制
        // let arr = [1,2,3,4];
        // const newArr = arr;
        // //测试
        // newArr[0] = 521;
        // console.log(arr);
        // console.log(newArr);
        //2. 数组  
            let arr = [{name:'atguigu'},2,3,4];
            // 1> concat
            // let newArr = [].concat(arr);
            // newArr[0].name = '尚硅谷';
            // console.log(arr)
            // console.log(newArr)
            // 2> slice 
            // let newArr = arr.slice(0);
            // newArr[0].name = '尚硅谷';
            // console.log(arr)
            // console.log(newArr)
            // 3> 扩展运算符
            // let newArr = [...arr];
            // newArr[0].name = '尚硅谷';
            // console.log(arr)
            // console.log(newArr)
        //3. 对象
            //使用 assign 方法创建对象 (assign 对象的合并)
            const school = {
                name: "尚硅谷",
                pos: ['北京','上海','深圳']
            }

            const newSchool = Object.assign({}, school);

            // newSchool.name = 'atguigu';
            newSchool.pos[0] = 'beijing';

            console.log(school);
            console.log(newSchool);
    </script>
</body>
</html>

4.3、深拷贝-JSON

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>深拷贝-JSON</title>
</head>
<body>
    <script>
        //JSON 实现深拷贝
        // * stringify 将 JS 对象转化为 JSON 格式的字符串
        // * parse    将 JSON 格式的字符串转化为 JS 对象
        //缺陷: 不能复制方法
        const school = {
            name: '朱岗子',
            pos: ['北京','上海','深圳'],
            founder: {
                name: 'lsy'
            },
            change: function(){
                console.log('改变');
            }
        }

        //将 对象转为 JSON 格式的字符串
        let str = JSON.stringify(school);
        //将对象转为JS对象
        let newSchool = JSON.parse(str);

        //测试
        newSchool.pos[0] = 'beijing';

        console.log(school);
        console.log(newSchool);
        // console.log(str);
        // console.log(typeof str);



    </script>
</body>

</html>

4.4、递归深拷贝的原理

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>递归实现深拷贝 - 思路</title>
</head>
<body>
    <script>    
        const school = {
            name: '尚硅谷',
            pos: ['北京','上海','深圳'],
            founder: 
            {
                name: '刚哥'
            },
            change: function(){
                console.log('改变');
            }
        }

        //创建数据容器
        const newSchool = {};
        //name
        newSchool.name = school.name;
        //pos
        newSchool.pos = school.pos;
        newSchool.pos = [];
        newSchool.pos[0] = school.pos[0];
        newSchool.pos[1] = school.pos[1];
        newSchool.pos[2] = school.pos[2];
        //founder
        newSchool.founder = {};
        newSchool.founder.name = school.founder.name;
        //方法
        newSchool.change = school.change.bind(newSchool);

        newSchool.pos[0] = 'beijing';

        console.log(school);
        console.log(newSchool);

    </script>
</body>
</html>

4.5、封装实现递归深拷贝

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>递归深拷贝实现</title>
</head>
<body>
    <script>
        //封装一个函数
        function deepClone(data){
            //创建一个容器  typeof
            // console.log(typeof data);
            let container;
            //判断
            let type = getDataType(data);// Object Array
            if(type === 'Object'){
                container = {};
            }
            if(type === 'Array'){
                container = [];
            }
            //遍历数据  for...in
            for(let i in data){
                //获取键值的类型
                let type = getDataType(data[i]);// Array
                //判断
                if(type === 'Array' || type==='Object'){
                    //????  递归调用 deepClone 即可
                    container[i] = deepClone(data[i]);
                }else{
                    //如果键值为非引用类型数据  则『直接复制』
                    container[i] = data[i];
                }
            }
            //container
            return container;
        }
        
        //待克隆的数据
        const school = {
            name: '尚硅谷',
            pos: ['北京','上海','深圳'],
            founder: {
                name: '刚哥'
            },
            change: function(){
                console.log('改变');
            }
        }
        //调用函数完成深拷贝
        const newSchool = deepClone(school);

        newSchool.pos[0] = 'beijing';
        console.log(school);
        console.log(newSchool);



        //封装一个函数 用来获取数据的类型
        function getDataType(data){
            return Object.prototype.toString.call(data).slice(8, -1);
        }

        
    </script>
</body>
</html>

4.6、ES11的可选链操作符号

html 复制代码
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>可选链操作符</title>
</head>
<body>
    <script>
      //?.
      function main(config){
       // const dbHost=config&&config.db&&config.db.host;

        const dbHost=config?.db?.host; //避免做层层判断
        console.log(dbHost);
      }
   
      main({
            db:{
                host:'127.0.0.1',
                username:"root"
            },
            caches:{
                host:'127.0.0.1',
                username:"admin"
            }  
        }
      )
    </script>
</body>
</html>

世之奇伟瑰丽,非常之观,常在于险远,只有难才能不断突破进步

相关推荐
FungLeo3 分钟前
node 后端和浏览器前端,有关 RSA 非对称加密的完整实践, 前后端匹配的代码演示
前端·非对称加密·rsa 加密·node 后端
雪芽蓝域zzs13 分钟前
JavaScript splice() 方法
开发语言·javascript·ecmascript
不灭锦鲤13 分钟前
xss-labs靶场第11-14关基础详解
前端·xss
不是吧这都有重名39 分钟前
利用systemd启动部署在服务器上的web应用
运维·服务器·前端
霸王蟹40 分钟前
React中巧妙使用异步组件Suspense优化页面性能。
前端·笔记·学习·react.js·前端框架
Maỿbe1 小时前
利用html制作简历网页和求职信息网页
前端·html
森叶1 小时前
Electron 主进程中使用Worker来创建不同间隔的定时器实现过程
前端·javascript·electron
霸王蟹1 小时前
React 19 中的useRef得到了进一步加强。
前端·javascript·笔记·学习·react.js·ts
霸王蟹1 小时前
React 19版本refs也支持清理函数了。
前端·javascript·笔记·react.js·前端框架·ts
繁依Fanyi1 小时前
ColorAid —— 一个面向设计师的色盲模拟工具开发记
开发语言·前端·vue.js·编辑器·codebuddy首席试玩官