ES6 | (二)ES6 新特性(下) | 尚硅谷Web前端ES6教程

文章目录

学习链接:尚硅谷Web前端ES6教程

📚迭代器

🐇定义

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

  • ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供for...of使用。

  • 原生具备 iterator 接口的数据(可用for of 遍历):ArrayArgumentsSetMapStringTypedArrayNodeList

    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>
            //使用next()方法遍历原生自带iterator接口的数据
            // 遍历 Map
            const mp = new Map();
            mp.set('a', 1);
            mp.set('b', 2);
            mp.set('c', 3);
            let iter1 = mp[Symbol.iterator]();
            console.log(iter1.next()); 
            console.log(iter1.next()); 
            console.log(iter1.next()); 
            console.log(iter1.next()); 
            // 遍历数组
            let xiyou = ['唐僧','孙悟空','猪八戒','沙僧'];
            let iter2 = xiyou[Symbol.iterator]();
            console.log(iter2.next()); 
            console.log(iter2.next()); 
            console.log(iter2.next()); 
            console.log(iter2.next()); 
    
            //实际上直接使用 for...of 方法遍历即可
            const mp2 = new Map();
            mp2.set('a', 1);
            mp2.set('b', 2);
            mp2.set('c', 3);
            for (let [k, v] of mp) {
                console.log(k, v);
            }
        </script>
    </body>
    </html>


🐇工作原理

  • 创建一个指针对象,指向当前数据结构的起始位置。
  • 第一次调用对象的next方法,指针自动指向数据结构的第一个成员。
  • 接下来不断调用`next方法,指针一直往后移动,直到指向最后一个成员。
  • 每调用next方法返回一个包含valuedone属性的对象。
  • 应用场景:需要自定义遍历数据的时候,要想到迭代器。

🐇自定义遍历数据

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 youyi = {
            uname: '右一',
            course: [ '可视化', '信息检索', '大数据安全', '类脑' ],
            // 通过自定义 [Symbol.iterator]() 方法
            [Symbol.iterator]() {
                // 初始指针对象指向数组第一个
                let index = 0;
                // 保存 youyi 的 this 值
                let _this = this;
                return {
                    next: function () {
                        // 不断调用 next 方法,直到指向最后一个成员
                        if (index < _this.course.length) {
                            return { value: _this.course[index++], done: false };
                        } else {
                            // 每调用next 方法返回一个包含value 和done 属性的对象
                            return { value: undefined, done: true };
                        }
                    }
                }
            }
        }
        // for...of直接遍历达到目的
        for (let v of youyi) {
            console.log(v);
        }
    </script>
</body>

</html>

📚生成器函数

🐇声明和调用

  • 生成器函数是 ES6 提供的一种 异步编程解决方案,语法行为与传统函数完全不同。

  • *的位置没有限制

    • 使用function * gen()yield可以声明一个生成器函数。生成器函数返回的结果是迭代器对象,调用迭代器对象的next方法可以得到yield语句后的值。
    • 每一个yield相当于函数的暂停标记,也可以认为是一个分隔符,每调用一次next(),生成器函数就往下执行一段。
    • next方法可以传递实参,作为yield语句的返回值。
    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 * gen(){
                console.log(111);
                yield '一只没有耳朵';
                console.log(222);
                yield '一只没有尾部';
                console.log(333);
                yield '真奇怪';
                console.log(444);
            }
    
            let iterator = gen();
            console.log(iterator.next());
            console.log(iterator.next());
            console.log(iterator.next());
            console.log(iterator.next());
    
            // 遍历
            for(let v of gen()){
                console.log(v);
            }
        </script>
    </body>
    </html>


🐇生成器函数的参数传递

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* generator(arg) {
            console.log(arg); // 生成器第 1 段
            let one = yield 111;
            console.log(one); // 生成器第 2 段
            let two = yield 222;
            console.log(two); // 生成器第 3 段
            let three = yield 333; 
            console.log(three); // 生成器第 4 段
        }

        let iter = generator('aaa'); // 传给生成器第 1 段
        console.log(iter.next());
        console.log(iter.next('bbb')); // 传给生成器第 2 段,作为这一段开始的 yield 语句返回值
        console.log(iter.next('ccc')); // 传给生成器第 3 段,作为这一段开始的 yield 语句返回值
        console.log(iter.next('ddd')); // 传给生成器第 4 段,作为这一段开始的 yield 语句返回值
    </script>
</body>
</html>

🐇生成器函数案例

  • 需求:1s 后控制台输出 111 2s后输出 222 3s后输出 333。

  • 传统方式:嵌套太多,代码复杂

    js 复制代码
    setTimeout(() => {
    	console.log(111);
    	setTimeout(() => {
    		console.log(222);
    		setTimeout(() => {
    			console.log(333);
    		}, 3000);
    	}, 2000);
    }, 1000);
  • 生成器实现:结构简洁明了

    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 one(){
                setTimeout(()=>{
                    console.log(111);
                    iterator.next();
                },1000)
            }
    
            function two(){
                setTimeout(()=>{
                    console.log(222);
                    iterator.next();
                },2000)
            }
    
            function three(){
                setTimeout(()=>{
                    console.log(333);
                    iterator.next();
                },3000)
            }
    
            function * gen(){
                yield one();
                yield two();
                yield three();
            }
    
            //调用生成器函数
            let iterator = gen();
            iterator.next();
        </script>
    </body>
    
    </html>

📚Promise

以下简单过一下 Promise,更多还要进一步深入学习,后续补充

  • Promise的定义和使用

    • Promise 是 ES6 引入的异步编程的新解决方案。

    • 语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果

    • 一个 Promise 必然处于以下几种状态之一

      • 待定(pending):初始状态,既没有被兑现,也没有被拒绝。
      • 已兑现(fulfilled):意味着操作成功完成。
      • 已拒绝(rejected):意味着操作失败。
    • Promise 的使用

      • Promise 构造函数:new Promise((resolve, reject)=>{})
      • Promise.prototype.then方法:该方法用于指定当前Promise对象状态改变时的回调函数。它接收两个参数,第一个参数是状态改变为Fulfilled时的回调函数,第二个参数(可选)是状态改变为Rejected时的回调函数。当Promise对象的状态已经是Fulfilled时调用then方法,回调函数会立即执行。
      • Promise.prototype.catch方法:该方法用于指定当前Promise对象状态变为Rejected时的回调函数。它和then方法的用法类似,但只接收一个参数,即状态变为Rejected时的回调函数。如果Promise对象的状态已经是Rejected,再调用catch方法时,回调函数会立即执行。catch方法返回一个新的Promise对象,可以链式调用后续的then方法。
      html 复制代码
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Promise基本语法</title>
      </head>
      <body>
          <script>
              //实例化 Promise 对象
              const p = new Promise(function(resolve, reject){
                  // 使用 setTimeout 模拟请求数据库数据操作
                  setTimeout(function(){
                      // 这个异步请求数据库数据操作是否正确返回数据
                      let isRight = true;
                      if (isRight) {
                          let data = '数据库中的数据';
                          // 设置 Promise 对象的状态为操作成功
                          resolve(data);
                      } else {
                          let err = '数据读取失败!'
                          // 设置 Promise 对象的状态为操作失败
                          reject(err);
                      }
                  }, 1000);
              });
      
              //调用 promise 对象的 then 方法
              p.then(function(value){
                  console.log(value);
              }, function(reason){
                  console.error(reason);
              })
          </script>
      </body>
      </html>
  • Promise封装读取文件

    js 复制代码
    //1. 引入 fs 模块
    const fs = require('fs');
    
    //2. 调用方法读取文件
    // fs.readFile('./resources/为学.md', (err, data)=>{
    //     //如果失败, 则抛出错误
    //     if(err) throw err;
    //     //如果没有出错, 则输出内容
    //     console.log(data.toString());
    // });
    
    //3. 使用 Promise 封装
    const p = new Promise(function(resolve, reject){
        fs.readFile("./resources/为学.md", (err, data)=>{
            //判断如果失败
            if(err) reject(err);
            //如果成功
            resolve(data);
        });
    });
    
    p.then(function(value){
        console.log(value.toString());
    }, function(reason){
        console.log("读取失败!!");
    });

📚Set

🐇Set的定义与使用

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

  • 定义一个 Set 集合:

    js 复制代码
    let st1 = new Set();
    let st2 = new Set([可迭代对象]);
  • 集合(这里假设有一个集合 st)的属性和方法:

    • st.size:返回集合个数
    • st.add(item):往集合中添加一个新元素 item,返回当前集合
    • st.delete(item):删除集合中的元素,返回 boolean 值
    • st.has(item):检测集合中是否包含某个元素,返回 boolean 值
    • st.clear():清空集合
    • 集合转为数组:[...st]
    • 合并两个集合:[...st1, ...st2]
    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>
            //声明一个 set
            let s = new Set();
            let s2 = new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿']);
    
            //元素个数
            console.log(s2.size);
            //添加新的元素
            s2.add('喜事儿');
            //删除元素
            s2.delete('坏事儿');
            //检测
            console.log(s2.has('糟心事'));
            for(let v of s2){
                console.log(v);
            }
            //清空
            s2.clear();
            console.log(s2);
        </script>
    </body>
    </html>

🐇集合实践

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Set 实践</title>
</head>
<body>
    <script>
        let arr = [1,2,3,4,5,4,3,2,1];
        //1. 数组去重
        let result = [...new Set(arr)];
        console.log(result);
        //2. 交集
        let arr2 = [4,5,6,5,6];
        let result2 = [...new Set(arr)].filter(item => new Set(arr2).has(item));
        console.log(result2);

        //3. 并集
        let union = [...new Set([...arr, ...arr2])];
        console.log(union);

        //4. 差集
        let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
        console.log(diff);
    </script>
</body>

</html>

📚Map

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

  • 定义一个map

    js 复制代码
    let mp1 = new Map();
    mp1.set('aaa', 111);
    mp1.set('bbb', 222);
    mp1.set('ccc', 333);
    
    let mp2 = new Map([
        ['aaa', 111],
        ['bbb', 222],
        ['ccc', 333]
    ]);
    
    console.log(mp1['aaa']); // 111
    console.log(mp2.get('bbb')); // 222
  • Map 的属性和方法:(k 为键,v为值)

    • size:返回 Map 的元素(键值对)个数。
    • set(k, v):增加一个键值对,返回当前 Map。
    • get(k):返回键值对的键值。
    • has():检测 Map 中是否包含某个元素。
    • clear():清空集合,返回 undefined。

📚class类

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

  • function构造函数的继承

    js 复制代码
    //手机
    function Phone(brand, price){
        this.brand = brand;
        this.price = price;
    }
    
    Phone.prototype.call = function(){
        console.log("我可以打电话");
    }
    
    //智能手机
    function SmartPhone(brand, price, color, size){
        Phone.call(this, brand, price);
        this.color = color;
        this.size = size;
    }
    
    //设置子级构造函数的原型
    SmartPhone.prototype = new Phone;
    // 矫正 constructor 指向
    SmartPhone.prototype.constructor = SmartPhone;
    
    //声明子类的方法
    SmartPhone.prototype.photo = function(){
        console.log("我可以拍照")
    }
    
    SmartPhone.prototype.playGame = function(){
        console.log("我可以玩游戏");
    }
    
    const chuizi = new SmartPhone('锤子',2499,'黑色','5.5inch');
    
    console.log(chuizi);
  • extends类继承和方法的重写

    • ES6 中直接使用 extends 语法糖(更简洁高级的实现方式)来实现继承,同时可以重写父类的方法,直接在子类中重新写一次要重写的方法即可覆盖父类方法。

      js 复制代码
      class Phone{
        //构造方法
         constructor(brand, price){
             this.brand = brand;
             this.price = price;
         }
         //父类的成员属性
         call(){
             console.log("我可以打电话!!");
         }
      }
      
      class SmartPhone extends Phone {
         //构造方法
         constructor(brand, price, color, size){
             super(brand, price);// Phone.call(this, brand, price)
             this.color = color;
             this.size = size;
         }
      
         photo(){
             console.log("拍照");
         }
      
         playGame(){
             console.log("玩游戏");
         }
      
         call(){
             console.log('我可以进行视频通话');
         }
      }
      
      const xiaomi = new SmartPhone('小米',799,'黑色','4.7inch');
      console.log(xiaomi);
      xiaomi.call();
      xiaomi.photo();
      xiaomi.playGame();
  • getter和setter 🔥

    • 当属性拥有 get/set 特性时,属性就是访问器属性。代表着在访问属性或者写入属性值时,对返回值做附加的操作。而这个操作就是 getter/setter 函数。

    • 使用场景 : getter 是一种语法,这种 get 将对象属性绑定到 查询该属性时将被调用的函数。适用于某个需要动态计算的成员属性值的获取。setter 则是在修改某一属性时所给出的相关提示。

      js 复制代码
      // get 和 set  
      class Phone{
          get price(){
              console.log("价格属性被读取了");
              return 'iloveyou';
          }
      
          set price(newVal){
              console.log('价格属性被修改了');
          }
      }
      
      //实例化对象
      let s = new Phone();
      
      console.log(s.price);
      s.price = 'free';

📚数值扩展

  • Number.EPSILON是 JavaScript 表示的最小精度,一般用来处理浮点数运算。例如可以用于两个浮点数的比较。

    js 复制代码
    let equal = (x, y) => Math.abs(x - y) < Number.EPSILON;
    console.log(0.1 + 0.2 === 0.3); // false
    console.log(equal(0.1 + 0.2, 0.3)); // true
  • Number.isFinite检测一个数值是否为有限数。

    js 复制代码
    console.log(Number.isFinite(100)); // false
    console.log(Number.isFinite(100 / 0)); // true
    console.log(Number.isFinite(Infinity)); // false
  • ES6 给 Number 添加了 parseInt 方法,Number.parseInt 完全等同于 parseInt,将字符串转为整数,或者进行进制转换。Number.parseFloat 则等同于 parseFloat()。

  • Number.isInteger() 判断一个数是否为整数。

  • Math.trunc() 将数字的小数部分抹掉。

  • Math.sign 判断一个数到底为正数 负数 还是零

📚对象方法扩展

  • Object.is比较两个值是否严格相等,与『===』行为基本一致。
  • Object.assign对象的合并,将源对象的所有可枚举属性,复制到目标对象。
  • __proto__setPrototypeOfsetPrototypeOf可以直接设置对象的原型。

📚ES6模块化

  • 模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
  • 模块化的好处
    • 防止命名冲突
    • 代码复用
    • 高维护性
  • ES6模块化语法 :模块功能主要由两个命令构成:exportimport
    • export命令用于规定模块的对外接口。
    • import命令用于输入其他模块提供的功能。

🐇模块导出数据语法

  • 单个导出

    js 复制代码
    // 单个导出
    export let uname = 'Rick';
    export let sayHello = function () {
        console.log('Hi, bro!');
    }
  • 合并导出

    js 复制代码
    let uname = 'Rick';
    let sayHello = function () {
        console.log('Hi, bro!');
    }
    // 合并导出
    export { uname, sayHello };
  • 默认导出

    js 复制代码
    // 默认导出
    export default {
        uname: 'Rick',
        sayHello: function () {
            console.log('Hi, bro!');
        }
    }

🐇模块导入数据语法

  • 通用导入

    js 复制代码
    import * as m1 from './js/m1.js';
    import * as m2 from './js/m2.js';
    import * as m3 from './js/m3.js';
  • 解构赋值导入

    js 复制代码
    import { uname, sayHello } from './js/m1.js';
    // 有重复名可以设置别名
    import { uname as uname2, sayHello as sayHello2 } from './js/m2.js';
    console.log(uname);
    // 配合默认导出
    import {default as m3} from "./src/js/m3.js";
  • 简便方式导入,针对默认暴露

    js 复制代码
    import m3 from "./src/js/m3.js";
相关推荐
格子软件8 小时前
2026年GEO优化系统源码级状态机与多模型调度拆解
java·前端·vue.js·人工智能·vue·geo
HUMHSX8 小时前
Vue 项目启动全流程解析:从入口文件到全局指令注册与页面渲染
前端·javascript·vue.js
有颜有货8 小时前
PMC生产排产的4种算法,一次讲清
java·服务器·前端
小虎牙0079 小时前
Android kotlin图片库Coil源码详解
android·前端
随风一样自由9 小时前
【前端领域】前端开发核心应用场景与落地实践
前端·前端框架
an317429 小时前
弹窗数据流设计的两种高阶架构实践
前端·vue.js·架构
谢尔登9 小时前
【React】 状态管理方案
前端·react.js·前端框架
用户21366100357210 小时前
Vue商品详情与放大镜组件
前端·javascript
半个落月10 小时前
从Tapas小Demo理清localStorage、事件与this
前端·javascript
李明卫杭州10 小时前
Vue2 中 v-model 处理不同数据结构的技巧
前端·javascript·vue.js