day16JS-es6生成器函数、模块开发

1. 生成器函数声明语法

声明关键字function*

声明语法:

function *函数名(){

}

生成器函数可以退出,并在稍后重新进入,其上下文(变量绑定)会在重新进入时保存。

案例:

javascript 复制代码
        function *fn(){
            return 1;
        }
        let g=fn();//Generator对象
        console.log(g);

注意!!!

1. 箭头函数不能用来定义生成器函数

2.function 和***两个单独的标记** ,因此它们可以用空白换行符分隔。

2.生成函数的简介

function* 声明创建一个 GeneratorFunction 对象每次调用生成器函数时,它都会返回一个新的 Generator 对象,该对象符合迭代器协议。当迭代器的next() 方法被调用时,生成器函数的主体会被执行,直到遇到第一个 yield 表达式,该表达式指定了迭代器要返回的值,或者用yield* 委托给另一个生成器函数。next() 方法返回一个对象,其value 属性包含了 yield 表达式的值done 属性布尔类型,表示生成器是否已经返回了最后一个值。如果 next() 方法带有参数,那么它会恢复生成器函数的执行,并用参数替换暂停执行的 yield 表达式。

3. 生成器函数的属性与方法

  1. suspended挂起状态

  2. next():让程序从suspended挂起状态进入到执行状态,代码会继续向后执行。返回一个对象{value:值,done:布尔值}value是代码返回的值,done是表示当前函数是否执行完成next()可以传参

  3. closed关闭状态。关闭状态就是代码执行完成后。

  4. yield暂停执行并且等待传参返回遇到yield就暂停。下次代码执行从上次暂停的地方开始执行。

案例1:

javascript 复制代码
        function* fn(a, b) {//a=1,b=3
            // yield 暂停执行并且等待传参返回
            yield a;//同步阻塞,返回a的值1,done: false
            a++;//2
            yield a;//返回a的值2,done: false
            yield b;
            b++;
            yield b;
            let sum = a + b;
            yield sum;
            return sum
        }

        let g = fn(1, 3);
        //第一次调用
        //value:1,done: false
        console.log(g.next());
        //第二次调用
        //value:2,done: false
        console.log(g.next());
        //...,以此类推
        console.log(g.next());
        console.log(g.next());
        console.log(g.next());
        console.log(g.next());

案例2:

javascript 复制代码
        function* fn(a, b) {
            //a=1,b=5
            a++;//a=2
            let c = yield a;//把10传给了c,继续向下执行
            b++;//b=6
            let d = yield b;//把100传给了d,继续向下执行
            return a + b + c + d;//2+6+10+100=118
        }
        var g = fn(1, 5);
        console.log(g.next());//2
        console.log(g.next(10));//6
        console.log(g.next(100));//118

案例3:

javascript 复制代码
       // 生成器函数可以同步阻塞,可以中间传参
        function* loadImage() {
            let arr = []
            for (var i = 39; i < 44; i++) {
                let img = new Image();
                img.src = `./img/img_${i}.jpg`;
                //遇到yield阻塞,for循环就可以不一次循环完毕
                yield img.onload = function () {
                    arr.push(img);
                    //等待每一张图片加载完毕,在执行后续代码
                    g.next();
                }
            }
            loadFinish(arr);
        }

        function loadFinish(arr) {
            arr.forEach((item) => {
                console.log(item.src);
            })
        }

        let g = loadImage()
        g.next();

注意!!!

生成器函数可以同步阻塞,可以中间传参

4. 错误对象

4.1 错误类型

  1. Error(): 基础类型。
  2. EvalError():eval错误。
  3. RangeError();范围错误。
  4. ReferenceError();引用错误。
  5. SyntaxError(): 语法错误。
  6. TypeError() : 类型错误。
  7. URIError(): URI错误。

4.2 错误类型详解

1. Error() :eval()函数执行出错时会抛出EvalError错误,该类型在ES5中已不再出现,为了向后兼容,所以被保留了下来。

2.RangeError(): RangeError是一个值超过有效范围时,会抛出RangeError范围错误。例如设置数组的长度为一个负值。

javascript 复制代码
 new Array(-1);
  1. ReferenceError():ReferenceError是引用一个不存在的变量或左值时,会抛出ReferenceError引用错误。
javascript 复制代码
a;
  1. **SyntaxError() :**SyntaxError是代码解析时会抛出SyntaxError语法错误(语法不符合规则)。
javascript 复制代码
        var 1bar = 1;
--------------------------------
        function fn() {
            var a =
        }
        fn();

5.TypeError() : 执行某些操作时,类型不符合要求会导致TypeError类型错误。

javascript 复制代码
null.toString();

6. URIError():URIEror是指调用URI相关函数的参数不正确时会发生URIError错误,例如,调用decodeURl、 encodeURl、decodeURIComponent、encodeURIComponent、escape、unescape时发生的错误。

javascript 复制代码
decodeURI("%2");

4.3 throw语句

  1. throw语句用于抛出错误,后面必须指定一个值用来表示错误信息,值的类型没有要求。

  2. throw语句用来抛出一个用户自定义的异常。当前函数的执行将被停止(throw之后的语句将不会执行),并且控制将被传递到调用堆栈中的第一个catch块。如果调用者函数中没有catch块,程序将会终止。

javascript 复制代码
throw 'hello world ";

throw new Error(" something bad happened ");

throw new SyntaxError("I don\ 't like your syntax. ");
throw new TypeError(" what type of variable do you take me for? ' );
throw new RangeError(' sorry,you just don\'t have the range. ');
throw new EvalError("That doesn\'t evaluate.");
throw new URIError("URI,is that you?");
throw new ReferenceError('you didn\'t cite your references properly");

4.4 try...catch...语句

try-catch语句用于捕获和处理JavaScript中的异常try从句 定义了可能出现异常的代码块,catch从句 定义当try从句抛出异常时执行的代码。try从句中的任何代码抛出异常,都会导致代码终止执行,然后执行catch中的代码。catch从句 后面还可以跟finally从句,用于放置清理代码。无论try从句是否抛出错误,finally从句中的代码都会执行,这里代码正常执行, 即使try中出现return语句也要执行。catch和finally都是可选的,但是try从句至少要和其中一个组合成完整的语句。

javascript 复制代码
        try {
            // 这里可能会产生楼读,可能是程序偿误,可能是throw语句抛出的错误
        }
        catch (e) {
            //当try中抛出错误时这里才执行,变量e包含了错误信息

        } finally {
            //无论try是否搭出异常,这里代码正常执行。即使try中出现return语句也要执行
        }

注意!!!

在catch中抛出异常,用throw e不要用throw new Error(e),因为e本身就是一个Error对象了, (因为在try代码块中使用throw抛出的newError()是一个使用构造函数new Error()创建的错误实例对象) 具有错误的完整堆栈信息stack,new Error会改变堆栈信息,将堆栈定位到当前这一行。

案例1:

javascript 复制代码
        function fn() {
            try {
                console.log(a);
                return 10;
            } catch (error) {
                console.log(error);
                return 20;
            } finally {
                console.log("必须执行");
                return 30;
            }
        }
        let res = fn();
        console.log(res);//30

案例2:

javascript 复制代码
        try {
            console.log(a);
        } catch (error) {
            console.log(error);
            //throw error;
        } finally {
            console.log("必须执行");
        }

5. 模块化开发

5.1 es5中js的三种加载方法

  1. js的文件相对地址 都是相对html的
  2. css的文件相对地址相对css的
  3. script标签****引入外部文件既可以是同步的(默认是同步的),也可以是异步的
  4. link标签****引入外部文件既是同步的
javascript 复制代码
//使用script标签引入外部js文件,src的相对地址是html 
<script src="./js/a.js"></script>
//使用link 标签引入外部js文件,href的相对地址是谁引用就是相当于谁的
<link rel="stylesheet" href="./css/a.css" >

1. 正常模式:<script src="./js/a.js"></script>

2. async模式:script标签使用async关键字可以让**script标签执行异步操作。**async异步时不需要等待直接向后执行后续html,等待DOM渲染后再执行,不能操作DOM,减少白屏,库比较大。

javascript 复制代码
<!-- async:异步时不需要等待直接向后执行后续html,不能操作DOM,减少白屏,库比较大 -->
<script src="./js/a.js" async></script>
<script src="./js/b.js" async></script>
  1. defer模式:script标签使用defer关键字也可以让script标签执行异步操作。defer可以操作DOM,但是图片视频都没有加载完成。script 加载的完成后,立即会做预解析。

加载流程:加载html--DOM树创建--CSS树创建--DOM渲染树完成--图片加载、视频加载、defer的script执行。

javascript 复制代码
<!-- defer:js中会操作DOM,图片视频都没有加载完成-->
<script src="./js/a.js" defer></script>
<script src="./js/b.js" defer></script>

async与defer的区别:加载流程

5.2 es6中js的加载方法

module模式 :script使用module 后会加入严格模式,js加载和执行将会在DOM渲染树、图片加载、视频加载完成 后。module模式 比defer模式执行的更晚。因为module时开始不做加载DOM渲染完成才加载,加载完成后才做预解析 。所以在使用module时不要在标签上写事件。

javascript 复制代码
<script type="module" src="./js/c.js"></script>

5.3 几个加载的执行先后

正常模式 ---> asyncm模式 ---> defer模式 ---> module模式。

5.4 模块化

将 JavaScript 程序拆分为可按需导入的单独模块的机制。(就是使用script标签导入多个js文件)

1. 模块导出关键字exportexport 声明用于从 JavaScript 模块中导出值。 export 声明运行时必须将该文件解释为模块 。在 HTML 中,可通过在**<script> 标签**中添加 type="module" 或由其他模块导入来实现。模块会自动以严格模式解释。

2. 模块导入关键字import : export 导出的值可通过import 声明动态导入 来将其导入其他程序。这里的导入名字必须和导出名字相同导入多个可以使用**{ }包裹起来。如果导入多个文件中名字有重复必须使用as 关键字起别名** 。

javascript 复制代码
1. 在utils.js文件中导出
// export 导出多个
export let arr=[1,2,3];
export let obj={a:1,b:2};
export function fn(){
    console.log("fn");
}

-------------------------------
2. 在其它文件中导入
// 这里的名字必须和Utils.js中的导出名相同,导入多个
// 如果导入的名字有重复必须起别名 as 别名
import {arr as arr1,obj,fn} from "./Utils.js";
//导入后可以使用utils.js文件中的数据
console.log(arr,obj);
fn();
  1. 模块默认导出关键字export default**:默认导出一个js文件中只能有一个默认导出 。** 当一个js文件中即有默认导出也有多个导出,首先先接受默认导出,然后再接收多个导出。
javascript 复制代码
1.在Manager.js文件中
// 默认导出 一个js文件中只能有一个默认导出
export default function fns(){
    console.log("fns");
}
export let s=new Set([1,2,3]);
-----------------------------------------
2.

import {arr as arr1,obj,fn} from "./Utils.js";

// 当一个js文件中即有默认导出也有多个导出,首先先接受默认导出,然后再接收多个导出

import fns,{s} from "./Manager.js";
let arr=["a","b"]
console.log(arr,arr1);
console.log(obj);
fn();

console.log(s);
fns();

6. 动画案例

补充知识:

requestAnimationFrame(函数名)请求帧动画每帧请求下次执行该函数

cancelAnimationFrame():清除帧动画。

7. 多选框案例

相关推荐
桂月二二37 分钟前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
hunter2062062 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb2 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角2 小时前
CSS 颜色
前端·css
浪浪山小白兔3 小时前
HTML5 新表单属性详解
前端·html·html5
lee5763 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579653 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
光头程序员4 小时前
grid 布局react组件可以循数据自定义渲染某个数据 ,或插入某些数据在某个索引下
javascript·react.js·ecmascript
limit for me4 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架
浏览器爱好者4 小时前
如何构建一个简单的React应用?
前端·react.js·前端框架