精华内容
下载资源
问答
  • lenet5卷积神经网络实现MNIST手写数字识别。代码分为前向传播、反向传播、模型测试三个部分,有详细的注释
  • 针对高校大学生创新意识、团队精神和工程实践能力的培养,通过分析工程训练的现状,阐述了模块化项目驱动工程训练模式在现代工程训练中应用的必要性,重点从模块化的课程体系构建、过程管理和项目的实施过程等方面...
  • 模块化开发,是当下最重要的前端开发范式之一。模块化只是一个思想、一个理论。 笔记来源:拉勾教育 大前端高薪训练营 阅读建议:内容较多,建议通过左侧导航栏进行阅读 模块化过程 早期模块化完全依靠约定。 文件...

    项目说明

    模块化开发,是当下最重要的前端开发范式之一。模块化只是一个思想、一个理论。

    笔记来源:拉勾教育 大前端高薪训练营
    阅读建议:内容较多,建议通过左侧导航栏进行阅读

    模块化过程

    早期模块化完全依靠约定。

    文件划分方式

    缺点:

    • 1,污染全局作用域;
    • 2,命名冲突问题;
    • 3,无法管理模块依赖关系。

    命名空间方式

    命名空间方式,将所需变量包裹进全局对象内。

    IIFE

    IIFE,自执行函数,将变量设为私有成员。

    模块化规范

    模块化规范,是指 模块化标准 + 模块加载器。

    CommonJs 规范

    CommonJs 是针对 NodeJs 的规范,是以同步模式加载模块,约定如下:

    • 1,一个文件就是一个模块;
    • 2,每个模块都有单独的作用域;
    • 3,通过 module.exports 导出成员;
    • 4,通过 require 函数载入模块。

    AMD + Require.js

    AMD(Asynchronous Module Definition),异步的模块定义规范,是针对浏览器的规范,它是通过 Require.js 进行实现的,Require.js 是一个非常强大的模块加载器。

    缺点

    • 1,AMD 使用起来相对复杂;
    • 2,模块 JS 文件请求频繁

    Require.js API

    define()

    每一个模块都要通过 define() 函数进行定义。

    传递三个参数

    • 第一个参数,是一个字符串,表示模块名,方便后期通过模块名进行使用;

    • 第二个参数,是一个数组,用来声明这个模块的一些依赖项,此参数按需添加,可有可无;

    • 第三个参数,是一个函数,函数的参数与前面数组中的依赖项一一对应,每一项分别为依赖项导出的成员,用来为当前模块提供私有空间,通过 return 向外部导出成员

      语法示例如下:

        define('module_name', [], function() { return ... })
      

    require()

    require() 函数,用来载入一个模块,内部会自动创建script标签,执行相应的代码。

    传入两个参数

    • 第一个参数,是一个数组,表示所引入模块的组合

    • 第二个参数,是一个函数,函数的参数与前面数组中的模块一一对应,可以使用 模块名.xx 的方式访问模块中导出的成员

      语法示例如下:

        require(['module_name', ...], function(module_name){
           // module_name.xx 
        })
      

    CMD + Sea.js

    CMD(Common Module Definition),通用的模块定义规范,类似 CommonJs 规范。Sea.js 是由淘宝推出的库,遵循CMD规范。

    ES Modules

    ES Modules 规范 是在 ECMAScript2015(ES6)中提出的 Module 模块标准。通过给 script 添加 type = module 的属性,就可以以 ES Module 的标准执行其中的 JS 代码。

    基本特性

    • 1,ESM 自动采用严格模式,忽略 ‘use strict’

        <script type="module">
            console.log(this); // undefined this在严格模式下,为 undefined
        </script>
      
    • 2,每个 ES Module 都是运行在单独的私有作用域中

        <script type="module">
            var foo = 100   // 不会造成全局作用域污染问题
            console.log(foo) // 100
        </script>
        <script type="module">
            console.log(foo) // Uncaught ReferenceError: foo is not defined
        </script>
      
    • 3,ESM 是通过 CORS 的跨域请求方式请求外部 JS 模块的

        <script type="module" src="https://umpkg.com/jquery@3.4.1/dist/jquery.min.js"> 		
        	// 需要服务端支持 CORS ,否则会出现跨域问题
        </script>
      
    • 4,ESM 的 script 标签会延迟执行脚本,相当于 script 的 defer 属性

        <script type="module" src="./demo.js">
            // 等待网页的渲染过后,再去执行脚本,不会阻碍页面的显示
        </script>
        <p>需要显示的内容</p>
      

    导入和导出

    导出 (export)

    export 是在模块内去对外暴露接口。

    导出语法

    • 1,直接成员导出,变量、函数、类等都可以导出。

      导出方式如下:

        export var name = 'foo module'   // 导出变量
        
        export function hello () { }     // 导出函数
        
        export class Person { }          // 导出类  
      
    • 2,成员集中导出,可以更加直观的看到向外部导出了哪些成员

      导出方式如下:

        var name = 'foo module'
        function hello () { }
        class Person { }
        
        export { name, hello, Person }
      
    • 3,别名导出,使用 as 进行重命名

      导出方式如下:

        var name = 'foo module'
        function hello () { }
        class Person { }
        
        export { name as fooName, hello as fooHello, Person as fooPerson }
      
    • 4,默认导出,设置某一个成员的别名是 default

      导出方式如下:

        var name = 'foo module'
        
        export { name as default }
        // <==> 推荐下方书写方式
        export default name
      

    导入 (import)

    import 是在模块内导入其他模块所提供的接口。

    导入语法

    对应上面的导出语法。

    • 1,对应 直接成员导出 和 成员集中导出

      导入方式如下:

        // .js 不可以省略,完整路径
        import { name, hello, Person } from 'module_path' 
      
    • 2,对应 别名导出

      导入方式如下(app.js):

        import { fooName, fooHello, fooPerson } from 'module_path'
      
    • 3,对应 默认导出

      导入方式如下(app.js):

        import { default as name }  from 'module_path' // default 是关键字
        // 简写为
        import name from 'module_path'
      
    • 4,导入模块时,模块路径的三种写法

      模块路径如下(app.js):

        // ./ 不可以省略,相对路径
        import { name } from './module.js'
        
        // / 绝对路径
        import { name } from '/04-import/module.js'
        
        // 完整 url 路径
        import { name } from 'htto://localhost:3000//04-import/module.js'
      
    • 5,加载模块,但不提取模块内的成员,一般用于导入一些不需要外部控制的子功能模块

      导入示例如下(app.js):

        import {} from './module.js'
        // 简写为
        import './module.js'
      
    • 6,提取模块导出的所有成员, 使用 as 将所有成员作为一个对象的属性

      导入示例如下(app.js):

        import * as mod from './module.js'
        console.log(mod.name, mod.age);
      
    • 7,动态导入模块, 返回一个 Promise对象

      导入示例如下(app.js):

        import('./module.js').then(function (module) {
            console.log(module);
        })
      
    • 8,导出时,同时导出命名成员和默认成员,如何导入

      导入示例如下(app.js):

        import { name, age, default as d } from './module.js'
        // 简写为, 默认成员的名字可以随意命名
        import d, { name, age } from './module.js'
      

    导出导入成员

    当前 module.js 模块的导出成员,将直接作为 app.js 模块的导出成员使用,一般用于集中导出分散的子模块成员

    • 1,index.js ,集中导出成员文件

        export { Button } from './button.js'
        
        // 默认成员的导出,必须重命名,以别名的形式导出
        export { default as Avatar} from './avatar.js'
      
    • 2,button.js ,分散子模块,导出 Button 成员

        export var Button = 'Button Component'
      
    • 3,avatar.js ,分散子模块,导出 Avatar 默认成员

        var  Avatar  = 'Avatar Component'
        export default Avatar
      

    注意事项

    • 1,export 单独使用时, {} 是固定语法,导出的不是对象字面量

      代码示例如下:

        var name = 'jack'
        var age = 18
        
        export { name, age } 
      

      导入模块,{} 固定语法,不是对象的解构

      代码示例如下:

        import { name, age } from './module.js'
      
    • 2,export default 组合使用时,{} 代表导出的是对象字面量

      代码示例如下:

        var name = 'jack'
        var age = 18
        
        export default { name, age }
      

      导入模块,不可以使用 {} 写法

      代码示例如下:

        // module_obj 自定义名字,最好和模块名保持一致
        import module_obj from './module.js' 
        
        // 访问导出的成员
        console.log(module_obj.name, module_obj.age)
      
    • 3,export 导出的是值的内存地址

      代码示例如下(module.js):

        var name = 'jack'
        var age = 18
        
        export { name, age } // 导出的是值的内存地址
        
        setTimeout(function () {
            name = 'ben'
        }, 1000)
      

      代码示例如下(app.js):

        import { name, age } from './module.js'
        
        console.log(name, age);  // jack 18
        
        setTimeout(function () {
            console.log(name, age); // ben 18
        }, 1500)
      
    • 4,导出的值是只读的,无法在模块外部修改成员

      代码示例如下(app.js):

        import { name, age } from './module.js'
        
        name = 'tom' // Uncaught TypeError: Assignment to constant variable.
      

    Polyfill

    解决浏览器的兼容性问题。

    • 在 HTML 页面,手动引入 browser-es-module-loader

      js 文件查找地址,如下:browser-es-module-loader

      代码示例如下(app.js):

        <!-- 有的IE版本不支持 Promise,因此需要引入 Promise Polyfill -->
        <script nomodule src="https://unpkg.com/promise-polyfill@8.2.0/dist/polyfill.min.js"></script>
        <!-- babel 即时运行在浏览器上的版本 -->
        <script nomodule src="https://unpkg.com/browser-es-module-loader@0.4.1/dist/babel-browser-build.js"></script>
        <!-- ES Modules Loader, 读取代码,将不识别的特性交给 babel 进行转换 -->
        <script nomodule src="https://unpkg.com/browser-es-module-loader@0.4.1/dist/browser-es-module-loader.js"></script>
      

    nomodule 属性,表示只在不支持 ES Modules 的浏览器中运行,避免支持的浏览器多次运行 。

    不建议在生产版本中使用,影响效率。

    in Node.js

    • 测试 ES Modules 在 node.js 环境的运行情况

      文件后缀名,设置为 xxx.mjs

      添加参数 – experimental-modules , 启动 ES Modules 的实验特性

        $ node --experimental-modules xxx.mjs # node 8.5+
      

      1)内置模块兼容了 ESM 的提取成员方式

      引入方式如下(index.mjs):

        // 方式一
        import fs from 'fs'
        fs.writeFileSync('./foo.txt', 'es module working') // 代码执行成功
        
        // 方式二
        import { writeFileSync } from 'fs'
        writeFileSync('./bar.txt', 'es module working~') // 代码执行成功
      

      2)第三方模块都是导出默认成员,不支持使用 {} 语法导入成员

      引入方式如下(index.mjs):

        import _ from 'lodash'
        console.log(_.camelCase('ES Module')); // 代码执行成功
        
        // import { camelCase } from 'lodash'
        // console.log(camelCase('ES Module')); // SyntaxError:...
      
    • ES Modules 与 CommonJS 交互

      1)ES Modules 中可以导入 CommonJS 模块

      代码示例如下(commonJs.js):

        module.exports = {
            foo: 'commonjs'
        }
        // exports 是 module.exports 的别名,二者是等价的
        exports.foo = 'commonjs'
      

      代码示例如下(es-modules.mjs):

        import mod from './common.js'
        console.log(mod);
      

      2)CommonJS 中不能导入 ES Modules 模块

      代码示例如下(commonJs.js):

        const mod = require('./es-module.mjs')
        console.log(mod); // Error [ERR_REQUIRE_ESM]: Must use import to load ES Module
      

      代码示例如下(es-modules.mjs):

        export const foo = 'es module export value'
      

      3)CommonJS 始终只会导出一个默认成员,不能直接提取成员

      代码示例如下(commonJs.js):

        exports.foo = 'commonjs'
      

      代码示例如下(es-modules.mjs):

        import { foo } from './common.js' // SyntaxError:...
        console.log(foo);
      

      4)注意 import 不是解构导出对象

    • ES Modules 与 CommonJs 的差异

      ES Modules 中没有 CommonJs 中的那些模块全局成员了,如:

      require(加载模块函数);
      module(模块对象);
      exports(导出对象别名);
      __filename(当前文件的绝对路径);
      __dirname(当前文件所在目录)

    • node.js 新版本进一步支持

      为了使项目中所有的js文件,都可以使用 ES Modules ,在 package.json 中添加属性 type 进行设置。

      代码示例如下(package.json):

        {
            type: 'module'
        }
      

      此时,无需再将 .js 改为 .mjs。但是要将 CommonJS 的 .js 改为 .cjs,保证兼容 CommonJS。

    • 低版本 Node.js,使用 Babel 进行兼容

      1)安装 babel 相关依赖模块

        $ yarn add @babel/node @babel/core @babel/preset-env --dev
      

      2)运行 ES Modules 的 JS 文件,需要添加特性转换的预设参数

        $ yarn babel-node index.js --presets=@babel/preset-env
      

      3)@babel/preset-env 只是一个插件集合,真正起作用的是 @babel/plugin-transform-modules-commonjs 插件

        $ yarn add @babel/plugin-transform-modules-commonjs --dev
      

      4)若不想在执行命令时添加参数,可以配置 .babelrc 文件,这是 babel 的配置文件

      代码示例如下(.babelrc):

        {
            "presets": ["@babel/preset-env"],
            "plugins": ["@babel/plugin-transform-modules-commonjs"]
        }
      

      5)运行命令,进行测试

        $ yarn babel-node index.js
      

    总结

    模块化的最佳实践:NodeJs 环境遵循 CommonJs,浏览器环境遵循 ES Modules 规范。

    展开全文
  • Tensorflow教程笔记 TensorFlow 基础 TensorFlow 模型建立与训练...常用模块 TensorBoard:训练过程可视 目录Tensorflow教程笔记实时查看参数变化情况查看 Graph 和 Profile 信息实例:查看多层感知机模型的训练情况
    1. 基础
      TensorFlow 基础
      TensorFlow 模型建立与训练
      基础示例:多层感知机(MLP)
      卷积神经网络(CNN)
      循环神经网络(RNN)
      深度强化学习(DRL)
      Keras Pipeline
      自定义层、损失函数和评估指标
      常用模块 tf.train.Checkpoint :变量的保存与恢复
      常用模块 TensorBoard:训练过程可视化
      常用模块 tf.data :数据集的构建与预处理
      常用模块 TFRecord :TensorFlow 数据集存储格式
      常用模块 tf.function :图执行模式
      常用模块 tf.TensorArray :TensorFlow 动态数组
      常用模块 tf.config:GPU 的使用与分配

    2. 部署
      TensorFlow 模型导出
      TensorFlow Serving
      TensorFlow Lite

    3. 大规模训练与加速
      TensorFlow 分布式训练
      使用 TPU 训练 TensorFlow 模型

    4. 扩展
      TensorFlow Hub 模型复用
      TensorFlow Datasets 数据集载入

    5. 附录
      强化学习基础简介


    有时,你希望查看模型训练过程中各个参数的变化情况(例如损失函数 loss 的值)。虽然可以通过命令行输出来查看,但有时显得不够直观。而 TensorBoard 就是一个能够帮助我们将训练过程可视化的工具。

    实时查看参数变化情况

    首先在代码目录下建立一个文件夹(如 ./tensorboard )存放 TensorBoard 的记录文件,并在代码中实例化一个记录器:

    summary_writer = tf.summary.create_file_writer('./tensorboard')     # 参数为记录文件所保存的目录
    

    接下来,当需要记录训练过程中的参数时,通过 with 语句指定希望使用的记录器,并对需要记录的参数(一般是 scalar)运行 tf.summary.scalar(name, tensor, step=batch_index) ,即可将训练过程中参数在 step 时候的值记录下来。这里的 step 参数可根据自己的需要自行制定,一般可设置为当前训练过程中的 batch 序号。整体框架如下:

    summary_writer = tf.summary.create_file_writer('./tensorboard')
    # 开始模型训练
    for batch_index in range(num_batches):
        # ...(训练代码,当前batch的损失值放入变量loss中)
        with summary_writer.as_default():                               # 希望使用的记录器
            tf.summary.scalar("loss", loss, step=batch_index)
            tf.summary.scalar("MyScalar", my_scalar, step=batch_index)  # 还可以添加其他自定义的变量
    

    每运行一次 tf.summary.scalar() ,记录器就会向记录文件中写入一条记录。除了最简单的标量(scalar)以外,TensorBoard 还可以对其他类型的数据(如图像,音频等)进行可视化。

    当我们要对训练过程可视化时,在代码目录打开终端(如需要的话进入 TensorFlow 的 conda 环境),运行:

    tensorboard --logdir=./tensorboard
    

    然后使用浏览器访问命令行程序所输出的网址(一般是 http://name-of-your-computer:6006),即可访问 TensorBoard 的可视界面,如下图所示:
    在这里插入图片描述
    默认情况下,TensorBoard 每 30 秒更新一次数据。不过也可以点击右上角的刷新按钮手动刷新。

    TensorBoard 的使用有以下注意事项:

    • 如果需要重新训练,需要删除掉记录文件夹内的信息并重启 TensorBoard(或者建立一个新的记录文件夹并开启 TensorBoard, --logdir 参数设置为新建立的文件夹);
    • 记录文件夹目录保持全英文。

    查看 Graph 和 Profile 信息

    除此以外,我们可以在训练时使用 tf.summary.trace_on 开启 Trace,此时 TensorFlow 会将训练时的大量信息(如计算图的结构,每个操作所耗费的时间等)记录下来。在训练完成后,使用 tf.summary.trace_export 将记录结果输出到文件。

    tf.summary.trace_on(graph=True, profiler=True)  # 开启Trace,可以记录图结构和profile信息
    # 进行训练
    with summary_writer.as_default():
        tf.summary.trace_export(name="model_trace", step=0, profiler_outdir=log_dir)    # 保存Trace信息到文件
    

    之后,我们就可以在 TensorBoard 中选择 “Profile”,以时间轴的方式查看各操作的耗时情况。如果使用了 tf.function 建立了计算图,也可以点击 “Graphs” 查看图结构。

    在 TensorFlow 2.3 及后续版本中,需要使用:

    pip install -U tensorboard-plugin-profile
    

    安装独立的 TensorBoard Profile 插件以使用 Profile 功能。

    实例:查看多层感知机模型的训练情况

    最后提供一个实例,以前章的 多层感知机模型 为例展示 TensorBoard 的使用:

    import tensorflow as tf
    from zh.model.mnist.mlp import MLP
    from zh.model.utils import MNISTLoader
    
    num_batches = 1000
    batch_size = 50
    learning_rate = 0.001
    log_dir = 'tensorboard'
    model = MLP()
    data_loader = MNISTLoader()
    optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)
    summary_writer = tf.summary.create_file_writer(log_dir)     # 实例化记录器
    tf.summary.trace_on(profiler=True)  # 开启Trace(可选)
    
    for batch_index in range(num_batches):
        X, y = data_loader.get_batch(batch_size)
        with tf.GradientTape() as tape:
            y_pred = model(X)
            loss = tf.keras.losses.sparse_categorical_crossentropy(y_true=y, y_pred=y_pred)
            loss = tf.reduce_mean(loss)
            print("batch %d: loss %f" % (batch_index, loss.numpy()))
            
            with summary_writer.as_default():                           # 指定记录器
                tf.summary.scalar("loss", loss, step=batch_index)       # 将当前损失函数的值写入记录器
                
        grads = tape.gradient(loss, model.variables)
        optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))
        
    with summary_writer.as_default():
        tf.summary.trace_export(name="model_trace", step=0, profiler_outdir=log_dir)    # 保存Trace信息到文件(可选)
    
    展开全文
  • 是的matlab代码Git培训材料 培训材料是为期两天的培训课程而设计的; 默认情况下,在一个电话make四个文件session_1.pdf到session_4.pdf产生; 每个铝箔甲板计划使用半天。 此外,还有下一个较短的车间的示例workshop...
  • 在开始学习之前推荐大家可以多在FlyAI竞赛服务平台多参加训练和竞赛,以此来提升自己的能力。FlyAI是为AI开发者提供数据竞赛并支持GPU离线训练的一站式服务平台。每周免费提供项目开源算法样例,支持算法能力变现...

    在开始学习之前推荐大家可以多在  FlyAI竞赛服务平台 多参加训练和竞赛,以此来提升自己的能力。FlyAI是为AI开发者提供数据竞赛并支持GPU离线训练的一站式服务平台。每周免费提供项目开源算法样例,支持算法能力变现以及快速的迭代算法模型。

    目录

      实时查看参数变化情况

      查看 Graph 和 Profile 信息

      实例:查看多层感知机模型的训练情况

      有时,你希望查看模型训练过程中各个参数的变化情况(例如损失函数 loss 的值)。虽然可以通过命令行输出来查看,但有时显得不够直观。而 TensorBoard 就是一个能够帮助我们将训练过程可视化的工具。

      实时查看参数变化情况

      首先在代码目录下建立一个文件夹(如 ./tensorboard )存放 TensorBoard 的记录文件,并在代码中实例化一个记录器:

      summary_writer = tf.summary.create_file_writer('./tensorboard') # 参数为记录文件所保存的目录

      接下来,当需要记录训练过程中的参数时,通过 with 语句指定希望使用的记录器,并对需要记录的参数(一般是 scalar)运行 tf.summary.scalar(name, tensor, step=batch_index) ,即可将训练过程中参数在 step 时候的值记录下来。这里的 step 参数可根据自己的需要自行制定,一般可设置为当前训练过程中的 batch 序号。整体框架如下:

      summary_writer = tf.summary.create_file_writer('./tensorboard')
    
      # 开始模型训练
    
      for batch_index in range(num_batches):
    
      # ...(训练代码,当前batch的损失值放入变量loss中)
    
      with summary_writer.as_default(): # 希望使用的记录器
    
      tf.summary.scalar("loss", loss, step=batch_index)
    
      tf.summary.scalar("MyScalar", my_scalar, step=batch_index) # 还可以添加其他自定义的变量

      每运行一次 tf.summary.scalar() ,记录器就会向记录文件中写入一条记录。除了最简单的标量(scalar)以外,TensorBoard 还可以对其他类型的数据(如图像,音频等)进行可视化。

      当我们要对训练过程可视化时,在代码目录打开终端(如需要的话进入 TensorFlow 的 conda 环境),运行:

     tensorboard --logdir=./tensorboard

      然后使用浏览器访问命令行程序所输出的网址(一般是 http://name-of-your-computer:6006),即可访问 TensorBoard 的可视界面,

      默认情况下,TensorBoard 每 30 秒更新一次数据。不过也可以点击右上角的刷新按钮手动刷新。

      TensorBoard 的使用有以下注意事项:

      如果需要重新训练,需要删除掉记录文件夹内的信息并重启 TensorBoard(或者建立一个新的记录文件夹并开启 TensorBoard, --logdir 参数设置为新建立的文件夹);

      记录文件夹目录保持全英文。

      查看 Graph 和 Profile 信息

      除此以外,我们可以在训练时使用 tf.summary.trace_on 开启 Trace,此时 TensorFlow 会将训练时的大量信息(如计算图的结构,每个操作所耗费的时间等)记录下来。在训练完成后,使用 tf.summary.trace_export 将记录结果输出到文件。

      tf.summary.trace_on(graph=True, profiler=True) # 开启Trace,可以记录图结构和profile信息
    
      # 进行训练
    
      with summary_writer.as_default():
    
      tf.summary.trace_export(name="model_trace", step=0, profiler_outdir=log_dir) # 保存Trace信息到文件

      之后,我们就可以在 TensorBoard 中选择 “Profile”,以时间轴的方式查看各操作的耗时情况。如果使用了 tf.function 建立了计算图,也可以点击 “Graphs” 查看图结构。

      在 TensorFlow 2.3 及后续版本中,需要使用:

      pip install -U tensorboard-plugin-profile

      安装独立的 TensorBoard Profile 插件以使用 Profile 功能。

      实例:查看多层感知机模型的训练情况

      最后提供一个实例,以前章的 多层感知机模型 为例展示 TensorBoard 的使用:

      import tensorflow as tf大连做人流哪家好 http://mobile.dlrlyy.com/
    
      from zh.model.mnist.mlp import MLP
    
      from zh.model.utils import MNISTLoader
    
      num_batches = 1000
    
      batch_size = 50
    
      learning_rate = 0.001
    
      log_dir = 'tensorboard'
    
      model = MLP()
    
      data_loader = MNISTLoader()
    
      optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)
    
      summary_writer = tf.summary.create_file_writer(log_dir) # 实例化记录器
    
      tf.summary.trace_on(profiler=True) # 开启Trace(可选)
    
      for batch_index in range(num_batches):
    
      X, y = data_loader.get_batch(batch_size)
    
      with tf.GradientTape() as tape:
    
      y_pred = model(X)
    
      loss = tf.keras.losses.sparse_categorical_crossentropy(y_true=y, y_pred=y_pred)
    
      loss = tf.reduce_mean(loss)
    
      print("batch %d: loss %f" % (batch_index, loss.numpy()))
    
      with summary_writer.as_default(): # 指定记录器
    
      tf.summary.scalar("loss", loss, step=batch_index) # 将当前损失函数的值写入记录器
    
      grads = tape.gradient(loss, model.variables)
    
      optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))
    
      with summary_writer.as_default():
    
      tf.summary.trace_export(name="model_trace", step=0, profiler_outdir=log_dir) # 保存Trace信息到文件(可选)

    在这里插入图片描述


    更多关于人工智能的文章,敬请访问:FlyAI-AI竞赛服务平台学习圈学习;同时FlyAI欢迎广大算法工程师在平台发文,获得更多原创奖励。此外,FlyAI竞赛平台提供大量数据型赛题供学习党和竞赛党参与,免费GPU试用,更多大赛经验分享。

    展开全文
  • 模块化开发与规范化标准 文章说明:本专栏内容为本人参加【拉钩大前端高新训练营】的学习笔记以及思考总结,学徒之心,仅为分享。如若有误,请在评论区支出,如果您觉得专栏内容还不错,请点赞、关注、评论。共同...

    Part2 · 前端工程化实战

    模块化开发与规范化标准

    文章说明:本专栏内容为本人参加【拉钩大前端高新训练营】的学习笔记以及思考总结,学徒之心,仅为分享。如若有误,请在评论区支出,如果您觉得专栏内容还不错,请点赞、关注、评论。共同进步!

    上一篇:【脚手架工具及自动化构建】

    本篇主要内容是前端模块化开发与规范化标准

    一、模块化演变过程

    模块化概述:

    模块化开发为当前最重要的前端开发范式之一。随着前端代码的日益复杂,的前端项目代码出现了不得不花费大量时间去整理。而模块化就是最主流的代码组织方式。他通过把复杂的代码通过功能不同划分为不同的模块,以单独维护的方式,提高开发效率,降低维护成本。【模块化】仅仅为一个思想,并没有提供具体的实现。

    1.stage1 基于文件划分

    将每一个模块独立为一个文件,在页面中引入这些文件(web中最原始的模块化系统)。

    具体做法就是将每个功能及其相关状态数据各自单独放到不同的文件中,约定每个文件就是一个独立的模块,使用某个模块就是将这个模块引入页面,然后直接调用模块的中的成员(成员/函数)

    特点:

    • 所有的模块都直接在全局工作,并没有私有空间,所有的成员都可以在模块外部被访问或者修改;
    • 文件模块过多时,容易产生命名冲突;
    • 无法管理模块与模块之间的依赖关系

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Modular evolution stage 1</title>
    </head>
    <body>
      <h1>模块化演变(第一阶段)</h1>
      <h2>基于文件的划分模块的方式</h2>
      <script src="module-a.js"></script>
      <script src="module-b.js"></script>
      <script>
        // 命名冲突,此处命名冲突问题由于引入模块顺序问题而不同,name值最后指向module-b.js中的name值
        method1()
        // 模块成员可以被修改,外部可以任意修改模块内部成员
        name = 'foo'
      </script>
    </body>
    </html>
    

    module-a.js

    // module a 相关状态数据和功能函数
    
    var name = 'module-a'
    
    function method1 () {
      console.log(name + '#method1')
    }
    
    function method2 () {
      console.log(name + '#method2')
    }
    
    

    module-b.js

    // module b 相关状态数据和功能函数
    
    var name = 'module-b'
    
    function method1 () {
      console.log(name + '#method1')
    }
    
    function method2 () {
      console.log(name + '#method2')
    }
    
    

    2.stage2 命名空间方式

    命名空间方式每个模块只暴露一个全局对象,所有模块成员都挂载到这个对象中。具体做法就是在第一阶段的额基础上,通过将每个模块【包裹】为一个全局对象的形式实现,有点类似于为模块内的成员添加了【命名空间】的感觉。

    特点:

    • 通过【命名空间】的方式减少了命名冲的可能
    • 同样没有私有空间,所有模块成员也可以在模块外部被访问或者修改
    • 同样无法管理模块之间的依赖关系

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Modular evolution stage 2</title>
    </head>
    <body>
      <h1>模块化演变(第二阶段)</h1>
      <h2>每个模块只暴露一个全局对象,所有模块成员都挂载到这个对象中</h2>
      <script src="module-a.js"></script>
      <script src="module-b.js"></script>
      <script>
        moduleA.method1()
        moduleB.method1()
        // 模块成员可以被修改
        moduleA.name = 'foo'
      </script>
    </body>
    </html>
    
    

    module-a.js

    // module a 相关状态数据和功能函数
    
    var moduleA = {
      name: 'module-a',
    
      method1: function () {
        console.log(this.name + '#method1')
      },
    
      method2: function () {
        console.log(this.name + '#method2')
      }
    }
    
    

    module-b.js

    // module b 相关状态数据和功能函数
    
    var moduleB = {
      name: 'module-b',
    
      method1: function () {
        console.log(this.name + '#method1')
      },
    
      method2: function () {
        console.log(this.name + '#method2')
      }
    }
    
    

    3.stage3 IIFE

    使用立即执行函数表达式IIFE(Immediately-Invoked Function Expression)为模块提供私有空间。具体做法就是将每个模块成员都放在一个函数提供的私有作用域中,对于需要宝库给外部的成员,通过挂载全局对象的方式实现。

    特点:
    有了私有成员的概念,私有成员只能在模块成员内通过必报的形式访问。

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Modular evolution stage 3</title>
    </head>
    <body>
      <h1>模块化演变(第三阶段)</h1>
      <h2>使用立即执行函数表达式(IIFE:Immediately-Invoked Function Expression)为模块提供私有空间</h2>
      <script src="module-a.js"></script>
      <script src="module-b.js"></script>
      <script>
        moduleA.method1()
        moduleB.method1()
        // 模块私有成员无法访问
        console.log(moduleA.name) // => undefined
      </script>
    </body>
    </html>
    

    module-a.js

    // module a 相关状态数据和功能函数
    
    ;(function () {
      var name = 'module-a'
      
      function method1 () {
        console.log(name + '#method1')
      }
      
      function method2 () {
        console.log(name + '#method2')
      }
    
      window.moduleA = {
        method1: method1,
        method2: method2
      }
    })()
    

    module-b.js

    // module b 相关状态数据和功能函数
    
    ;(function () {
      var name = 'module-b'
      
      function method1 () {
        console.log(name + '#method1')
      }
      
      function method2 () {
        console.log(name + '#method2')
      }
    
      window.moduleB = {
        method1: method1,
        method2: method2
      }
    })()
    

    4.stage4 IIFE 参数

    利用IIFE参数作为依赖声明使用,具体做法是在第三阶段的基础上,利用立即执行函数的参数传递模块依赖项

    特点:

    每个模块之间的关系变得更加明显

    index.html

    <!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>Modular evolution stage 4</title>
    </head>
    <body>
      <h1>模块化演变(第四阶段)</h1>
      <h2>利用 IIFE 参数作为依赖声明使用</h2>
      <p>
        具体做法就是在第三阶段的基础上,利用立即执行函数的参数传递模块依赖项。
      </p>
      <p>
        这使得每一个模块之间的关系变得更加明显。
      </p>
      <script src="https://unpkg.com/jquery"></script>
      <script src="module-a.js"></script>
      <script src="module-b.js"></script>
      <script>
        moduleA.method1()
        moduleB.method1()
      </script>
    </body>
    </html>
    
    

    module-a.js

    // module a 相关状态数据和功能函数
    
    ;(function ($) {
      var name = 'module-a'
      
      function method1 () {
        console.log(name + '#method1')
        $('body').animate({ margin: '200px' })
      }
      
      function method2 () {
        console.log(name + '#method2')
      }
    
      window.moduleA = {
        method1: method1,
        method2: method2
      }
    })(jQuery)
    
    

    module-b.js

    // module b 相关状态数据和功能函数
    
    ;(function () {
      var name = 'module-b'
      
      function method1 () {
        console.log(name + '#method1')
      }
      
      function method2 () {
        console.log(name + '#method2')
      }
    
      window.moduleB = {
        method1: method1,
        method2: method2
      }
    })()
    
    

    5.stage5 模块化规范的出现

    require.js提供AMD模块化规范以及一个自动模块化加载器

    目录结构:
    在这里插入图片描述

    index.html

    <!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>Modular evolution stage 5</title>
    </head>
    <body>
      <h1>模块化规范的出现</h1>
      <h2>Require.js 提供了 AMD 模块化规范,以及一个自动化模块加载器</h2>
      <script src="lib/require.js" data-main="main"></script>
    </body>
    </html>
    
    

    module1.js

    // 因为 jQuery 中定义的是一个名为 jquery 的 AMD 模块
    // 所以使用时必须通过 'jquery' 这个名称获取这个模块
    // 但是 jQuery.js 并不在同级目录下,所以需要指定路径
    define('module1', ['jquery', './module2'], function ($, module2) {
      return {
        start: function () {
          $('body').animate({ margin: '200px' })
          module2()
        }
      }
    })
    
    

    module2.js

    // 兼容 CMD 规范(类似 CommonJS 规范)
    define(function (require, exports, module) {
    	// 通过 require 引入依赖
      var $ = require('jquery')
      // 通过 exports 或者 module.exports 对外暴露成员
      module.exports = function () {
        console.log('module 2~')
        $('body').append('<p>module2</p>')
      }
    })
    
    

    main.js

    require.config({
      paths: {
        // 因为 jQuery 中定义的是一个名为 jquery 的 AMD 模块
        // 所以使用时必须通过 'jquery' 这个名称获取这个模块
        // 但是 jQuery.js 并不一定在同级目录下,所以需要指定路径
        jquery: './lib/jquery'
      }
    })
    
    require(['./modules/module1'], function (module1) {
      module1.start()
    })
    
    

    二、模块化规范

    1.CommonJS

    在之前的每个阶段中,模块加载的方式都是通过script标签手动引入。也就是说,之前的方法中,模块的加载并不受代码的控制。一旦模块过多,会出现各种问题,比如HTML忘记引入模块等。

    基于node.js的commonJS规范

    • 一个文件就是一个模块
    • 每个模块都有单独的作用域
    • 通过module.exports导出成员
    • 通过require函数载入模块

    commonJS是以同步模式加载模块,node执行机制是在启动时加载模块,在执行过程中不需要加载,只会使用。在浏览器端使用commonJS规范的话,必然导致效率低下。每次页面加载都会导致大量的同步模式请求出现。

    2.AMD

    所以在早期并没有选择commonJS规范,而是专门为浏览器端且结合浏览器特点,重新设计了一个模块加载规范:AMD(Asynchronous Module Definition)异步模块定义规范。同时也除了一个require.js库,其实现了AMD规范,同时本身又是一个强大的模块加载器。

    AMD规范中,require.js库规定每个模块使用define关键字去定义。可以传递2-3个参数,传递三个参数的话,第一个参数为该模块的名字;第二个参数为数组,声明该模块的依赖项,数组中每个数组的元素为具体依赖的其他模块;第三个模块为一个函数,该函数的参数与第二个参数中的依赖项一一对应,每一项分别为依赖项导出的成员,函数的作用是为当前的模块提供一个私有的空间。如果需要在本模块中向外部模块导出一些成员,通过return的方式去实现。

    define('module1', ['jquery', './module2'], function () {
        return {
            start: function () {
                $('body').animate({margin: '200px'})
                module2()
            }
        }
    })
    

    除此之外,require.js还提供了一个require()函数,该函数用来自动加载模块。用法与define类似,区别是require只是用来加载模块,而define是用来定义模块。require函数去加载一个模块时,其内部会自动创建一个script标签,发送对应脚本文件的请求,并且执行相应的模块代码

    require(['module1'], function(module1) {
        module1.start()
    })
    

    目前绝大多数第三方库都支持AMD规范,其生态相对较好,但是AMD使用起来比较复杂,除了业务代码,需要使用define定义模块以及require()函数去加载模块,导致代码复杂程度较高。如果项目中模块的划分较为细致时,模块JS文件请求频繁,从而呆滞页面效率比较低下。所以AMD也只能为前端模块化规范前进的一步,只是一种妥协的手段,并不是最终的解决方案。

    同期淘宝出现了Sea.js + CMD标准,类似commonJS且用法上与require.js大致相同,这种方式在后来也被Require.js兼容。

    // CMD规范(类似CommonJS)
    define(function (require, exports, module) {
        // 通过require引入依赖
        var $ = require('jquery');
        // 通过exports或者module.exports对外暴露成员
        module.exports = function () {
            console.log('module-2');
            $('body').append('<p>module2</p>')
        }
    })
    

    3.模块化标准规范

    随着技术的发展,模块化 技术实现方式相对以往有了很大的变化。大家在前端模块化的方式也基本统一。在node.js中遵循CommonJS,在Browser中采用ES Module。

    在node.js中,CommonJS为其内置的模块,正常使用require去导入模块,module.exports去导出模块。但是在ES Module在browser中就比较复杂一些。ES Module时ECMAScript2015(ES6)中定义的一个最新的模块系统,他是最近几年才定义的标准。定义初期,几乎所有主流浏览器都不支持这个特性,随着webpack等一系列打包工具的流行,这一规范才逐渐开始普及。

    在这里插入图片描述

    4.ES Module

    1.基本特性

    • 自动采用严格模式,忽略’use strict’
    • 每个ESM模块都是单独的私有作用域
    • ESM是通过CORS去请求外部JS模块的
    • ESM的script标签会延迟执行脚本
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>ES Module - 模块的特性</title>
    </head>
    <body>
      <!-- 通过给 script 添加 type = module 的属性,就可以以 ES Module 的标准执行其中的 JS 代码了 -->
      <script type="module">
        console.log('this is es module')
      </script>
    
      <!-- 1. ESM 自动采用严格模式,忽略 'use strict' -->
      <script type="module">
        console.log(this)  // undifined
      </script>
    
      <!-- 2. 每个 ES Module 都是运行在单独的私有作用域中 -->
      <script type="module">
        var foo = 100
        console.log(foo)
      </script>
      <script type="module">
        console.log(foo)  // foo is not defined
      </script>
    
      <!-- 3. ESM 是通过 CORS 的方式请求外部 JS 模块的 -->
      <!-- 所以应用外部js问价需要其CDn支持CORS -->
      <!-- <script type="module" src="https://unpkg.com/jquery@3.4.1/dist/jquery.min.js"></script> -->
      <!-- CORS不支持文件的方式去访问,只能通过http的方式去访问 -->
        
      <!-- 4. ESM 的 script 标签会延迟执行脚本 defer延迟执行 type="module"与defer属性功能相同 -->
      <!-- <script defer src="demo.js"></script> -->
      <script type="module" src="demo.js"></script>
      <p>需要显示的内容</p>
    </body>
    </html>
    

    2.导入和导出

    • export用法

      1.单独导出每个成员export var name

      module.js

      export var name = 'foo module'
      
      export function hello () {
        console.log('hello')
      }
      
      export class Person {}
      

      app.js

      import { name, hello, Person } from './module.js'
      console.log(name)  // foo module
      hello()  // hello
      

      2.模块尾部统一导出

      module.js

      var name = 'foo module'
      
      

    function hello () {
    console.log(‘hello’)
    }

    class Person {}

    export { name, hello, Person }

    app.js
    
    ```js
    import { name, hello, Person } from './module.js'
    console.log(name)  // foo module
    hello()  // hello
    

    3.导出别名

    module.js

    var name = 'foo module'
    
    function hello () {
      console.log('hello')
    }
    
    export {
      name as fooName,
      hello as fooHello
    }
    

    app.js

      import { fooName, fooHello } from './module.js'
      console.log(fooName)  // foo module
      fooHello()  // hello
    

    4.导出default

    module.js

    var name = 'foo module'
    
    export {
      name as default
    }
    

    app.js

    // 由于default为关键字,所以引入该变量时需要重命名
    import { default as fooName } from './module.js'
    console.log(fooName)  // foo module
    

    5.模块默认导出,引入时可取任意变量名

    module.js

    var name = 'foo module'
    export default name
    

    app.js

    import abc from './module.js'
    console.log(abc)  // foo module
    
    • 注意事项

      • export固定写法 { }
      • import导入成员并不是复制一个副本,而是直接导入模块成员的引用地址。也就是说import得到的变量与export导出的变量在内存中是同一块空间。一旦模块中的成员被修改,引入的变量也会同时修改。
      • import导入的变量是只读变量,但对象的读写属性不受影响

      module.js

      var name = 'jack'
      var age = 18
      
      // var obj = { name, age }
      
      // export default { name, age }
      
      // 这里的 `{ name, hello }` 不是一个对象字面量,
      // 它只是语法上的规则而已
      export { name, age }
      
      // export name // 错误的用法
      
      

    // export ‘foo’ // 同样错误的用法

    setTimeout(function () {
    name = ‘ben’
    }, 1000)

    
    app.js
    
    ```js
    // CommonJS 中是先将模块整体导入为一个对象,然后从对象中结构出需要的成员
    // const { name, age } = require('./module.js')
    
    // ES Module 中 { } 是固定语法,就是直接提取模块导出成员
    import { name, age } from './module.js'
    
    console.log(name, age)
    
    // 导入成员并不是复制一个副本,
    // 而是直接导入模块成员的引用地址,
    // 也就是说 import 得到的变量与 export 导入的变量在内存中是同一块空间。
    // 一旦模块中成员修改了,这里也会同时修改,
    setTimeout(function () {
    console.log(name, age)
    }, 1500)
    
    // 导入模块成员变量是只读的
    // name = 'tom' // 报错
    
    // 但是需要注意如果导入的是一个对象,对象的属性读写不受影响
    // name.xxx = 'xxx' // 正常
    
    • import用法

      app.js

      // 1.导入规则
      // import { name } from './module'  // 不可以省略.js扩展名以及./,在commonJS中可以省略扩展名及./
      import { name } from './module.js'
      console.log(name)  // 'jack'
      
      // commonJS中可以直接导入模块,例如:import { lowercase } from './utils',但是在原生ESM中需要填写完整路径
      // 后期使用打包工具后,可以省略扩展名以及省略index.js默认文件
      import { lowercase } from './utils/index.js'
      console.log(lowercase("HHH"))
      
      // 导入模块时必须使用/开头,否则ESM认为是需要加载一个第三方模块
      // import { name } from './module.js'  // 或者从网站根目录开始
      // import { name } from '/04-import/module.js'  // 或者使用完整的url加载模块
      import { name } from 'http://localhost:3000/04-import/module.js'  // 意味着可以直接饮用CDN的模块文件
      console.log(name)
      
      // 2.只是需要执行某个模块,并不需要提取模块中的成员
      import {} from './module.js'  // 或者import './module.js' ,在并不需要外界控制的子功能模块式使用此种导入方式
      
      // 3.导入多个模块
      import * as mod from './module.js'  // 将所有的导出的成员全部导入并使用as重命名,全部放入一个对象中,每个成员都会作为对象的属性
      console.log(mod)
      
      // 4.动态导入模块
      // var modulePath = './module.js'
      // import { name } from modulePath
      // console.log(name)  // 报错
      
      // if (true) {
      //     import { name } from './module.js'
      // }  // 报错
      
      // ESM提供全局函数import(),专门用于动态导入模块,该函数返回一个promise对象,当模块的异步加载完成后,会自动执行then中的回调函数,模块的对象可以通过参数获取
      import('./module.js').then(function (module) {
          console.log(module)
      })
      
      // 5.导入命名成员以及默认成员
      import { name, age, default as title } from './module.js'  // 或者
      console.log(name, age, title)
      // 导入命名成员以及默认成员简写
      import abc, {name, age} from './module.js'  // abc可以使用任意变量名
      console.log(abc, name, age)
      

      module.js

      var name = 'jack'
      var age = 18
      
      export { name, age }
      
      console.log('module action')
      
      export default 'default export'
      

      utils/index.js

      export function lowercase (input) {
        return input.toLowerCase()
      }
      
    • 直接导出所导入的成员

      除了导入模块,import还可以配合export使用,效果是将导入的结果直接作为当前模块的导出成员。导出后,当前作用域不再可以访问导入的成员了。一般在index.js中使用,在index.js中把某些目录中散落的一些模块通过export组织到一起再进行导出

      app.js

      // export {name, age} from './module.js'
      // console.log(name)  // name is not defined
      
      // 繁琐的方法
      import {Button} from './components/button.js'
      import {Avatar} from './components/avatar.js'
      console.log(Button, Avatar)
      
      // 简单的方法,compotents中新增index.js,导入再导出组件
      import { Button, Avatar } from './components/index.js'
      console.log(Button)
      console.log(Avatar)
      

      components/button.js

      var Button = 'Button Components'
      export default Button
      

      components/avatar.js

      export var Avatar = 'Avatar Components'
      

      components/index.js

      // import {Button} from './components/button.js'
      // import {Avatar} from './components/avatar.js'
      
      // export {Button, Avatar}
      export { default as Button } from './button.js'
      export { Avatar } from './avatar.js'
      
    • polyfill兼容方案

      ESM2014年提出,早期的浏览器它不可能支持这个特性,另外呢,在IE还有一些国产的浏览器上,截止到目前为止都还没有支持,所以说在使用的时候还是需要去考虑将信所带来的一个问题。

      可以借助一些编译工具在开发阶段将这些ES6的代码,编译成ES5的方式,然后呢,再到浏览器当中去执行。这里介绍一个模块browser-es-module-loader,将文件引入到网页中,网页就可以运行ESM了。

      <!DOCTYPE html>
      <html lang="en">
      <head>
        <meta charset="UTF-8">
        <title>ES Module 浏览器环境 Polyfill</title>
      </head>
      <body>
        <script nomodule src="https://unpkg.com/promise-polyfill@8.1.3/dist/polyfill.min.js"></script>
        <script nomodule src="https://unpkg.com/browser-es-module-loader@0.4.1/dist/babel-browser-build.js"></script>
        <script nomodule src="https://unpkg.com/browser-es-module-loader@0.4.1/dist/browser-es-module-loader.js"></script>
      
        <script type="module">
          import { foo } from './module.js'
          console.log(foo)
        </script>
         <!-- 以上代码在支持ESm中的浏览器会运行两次,所以使用nomoudle确保在不支持ESM的浏览器工作 -->
        <script nomodule>
          alert('hello')
        </script>    
      </body>
      </html>
      
      

      这种兼容ESm的方式,它只适合于本地区测试,也就是开发阶段去玩一玩,但是,在生产阶段千万不要去用它,因为它的原理是在运行阶段动态的去解析脚本,效率非常的差。在生产阶段,还是应该预先去把这些代码编译出来,让它可以直接在浏览器当中去工作。

    4.ESM in Node.js

    • 与CommonJS交互

      ESM作为JavaScript的语言层面的一个模块化标准,逐渐的会去统一所有JS应用领域的模块化需求,Node.js作为JavaScript的一个非常重要的一个应用领域,目前,已经开始逐步支持这样一个特性,从Node.js的8.5版本过后,内部就已经以实验特性的方式去支持ESM了,也就是说在Node.js当中可以直接原生的去使用ESM去编代码了。但是,考虑到原来的这个comment规范与现在的ESM他们之间的差距还是比较大的,所以说目前,这样一个特性一直还是处于一个过渡的状态,那接下来,就一起来尝试一下,直接在Node环境当中使用ESM编写代码。

      需要在Node.js中使用ESM:

      • 首先将文件扩展名改为.mjs
      • 然后在命令行使用–experimental-modules参数,这个参数代表去启用ESM的实验特性。

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jEsgLoEd-1608214600072)(./image-20201216231354541.png)]

      提取第三方模块

      import _ from 'lodash'
      
      console.log(_.camelCase('ES Module'))  // esModule
      

      提取node内置模块成员

      // 也可以直接提取模块内的成员,内置模块兼容了 ESM 的提取成员方式
      import {writeFileSync} from 'fs'
      writeFileSync('./bar.txt', 'es module working~')
      
      // 不支持,因为第三方模块都是导出默认成员
      // import { camelCase } from 'lodash'
      // console.log(camelCase('ES Module'))
      
    • 与CommonJS的差异

      1.在ESM中使用CommonJS模块

      es-module.mjs

      // ES Module 中可以导入 CommonJS 模块
      // 只能使用import载入默认成员的方式去使用commonJS模块
      
      import mod from './commonjs.js'
      console.log(mod)
      

      common.js

      // CommonJS 模块始终只会导出一个默认成员
      
      // module.exports = {
      //   foo: 'commonjs exports value'
      // }
      
      // 使用commonJS的导出的别名exports
      exports.foo = 'commonjs exports value'
      

      在命令行运行

      D:\DeskTop\02-interoperability>node --experimental-modules es-module.mjs
      { foo: 'commonjs exports value' }
      

      2.通过commonJS载入ESM(Node原生的环境中不能在 CommonJS 模块中通过 require 载入 ES Module)

      es-module.js

      export const foo = 'es module export value'
      

      common.js

      const mod = require('./es-module.js')
      console.log(mod)  // !!!报错
      

      总结:

      • ESM中可以导入CommonJS模块
      • CommonJS中不能导入ESM模块
      • CommonJS始终只会导出一个默认成员
      • 注意import不是解构导出对象
    • ES Modules in Node.js - 与 CommonJS 的差异

      esm.mjs

      // ESM 中没有模块全局成员了
      
      // // 加载模块函数
      // console.log(require)
      
      // // 模块对象
      // console.log(module)
      
      // // 导出对象别名
      // console.log(exports)
      
      // // 当前文件的绝对路径
      // console.log(__filename)
      
      // // 当前文件所在目录
      // console.log(__dirname)
      
      // -------------以上成员无法打印
      
      // require, module, exports 自然是通过 import 和 export 代替
      
      // __filename 和 __dirname 通过 import 对象的 meta 属性获取
      // const currentUrl = import.meta.url
      // console.log(currentUrl)
      
      // 通过 url 模块的 fileURLToPath 方法转换为路径
      import { fileURLToPath } from 'url'
      import { dirname } from 'path'
      const __filename = fileURLToPath(import.meta.url)
      const __dirname = dirname(__filename)
      console.log(__filename)
      console.log(__dirname)
      
      

      cjs.js

      // 加载模块函数
      console.log(require)
      
      // 模块对象
      console.log(module)
      
      // 导出对象别名
      console.log(exports)
      
      // 当前文件的绝对路径
      console.log(__filename)
      
      // 当前文件所在目录
      console.log(__dirname)
      
      
    • 新版本进一步支持ESM

      在Node.js的最新版本当中,它进一步的支持了ESM,这里可以来尝试一下,可以通过Node刚刚experimental去执行一这个js文件,那此时执行的效果呢,跟之前所看到的也是一样的,不过呢,在这个新版本当中,可以通过给项目的package点当中去添加一个type字段断,将这个type字段的设置为module,这个时候这个项目向所有的js文件默认就会以ESM去工作了,也就是说不用再将扩展名改成mjs了,直接让他们改回来为js,再回到文件当中,将文件当中的路径也给它修改回来。

      此时,就可以回到命令行当中,再次重新运行一下index.js,这个js文件就会按照ESM的形式去工作了,如果这个时候你还想去使用commonJS的话,例如再去新建一个common.js这样一个文件,这个时候需要单独对于commonJS这种方式,做一个偶尔的处理,那就是将这个common的文件修改为点cjs的这样一个扩展名,那此时再次去执行的话,就可以正常的去使用common js规范了。

      index.js

      // Node v12 之后的版本,可以通过 package.json 中添加 type 字段为 module,
      // 将默认模块系统修改为 ES Module
      // 此时就不需要修改文件扩展名为 .mjs 了
      
      import { foo, bar } from './module.js'
      
      console.log(foo, bar)
      

      module.js

      export const foo = 'hello'
      
      export const bar = 'world'
      

      common.cjs

      // 如果需要在 type=module 的情况下继续使用 CommonJS,
      // 需要将文件扩展名修改为 .cjs
      
      const path = require('path')
      
      console.log(path.join(__dirname, 'foo'))
      

      package.json

      {
        "type": "module"
      }
      
    • Babel兼容方案

      如果你使用的是早期的Node,可以使用babel去实现ESM的兼容问题。babel是目前最主流的一块JavaScript的编译器,他可以用来帮助我们将一些使用了新特性的代码,编译成当前环境的代码。之后我们可以放心的去使用新特性。下面使用babel去实现低版本Node(这里使用8.0.0)。

      index.js

      // 对于早期的 Node.js 版本,可以使用 Babel 实现 ES Module 的兼容
      
      import { foo, bar } from './module.js'
      
      console.log(foo, bar)
      

      module.js

      export const foo = 'hello'
      
      export const bar = 'world'
      
      • 安装babel及其他插件

        yarn add @babel/node @babel/core @babel/preset-env --dev
        
      • 直接运行yarn babel-node index.js时会报错,不支持import。原因非常简单,因为babel,它是基于插件机制去实现的,它的核心模块,并不会去转换我们的代码,那具体要去转换代码当中的每一个特性,它是通过插件来去实现的,也就是说需要一个插件去转换代码当中的一个特性,那之前所安装的这个preset-env,它实际上是一个插件的集合,在这个插件集合当中去包含了最新的JS标准当中的所有的新特性,可以借助于这个preset直接去把我们当前这个代码当中所使用到的ESM就给它转换过来。

      • 使用新命令

        yarn babel-node index.js --presets=@babel/preset-env
        # hello world
        
      • 如果说觉得每次手动的去传输这样一个参数会比较麻烦的话,那你也可以选择把它放到配置文件当中。项目中新建.babelrc文件,该文件为json格式的文件

        {
          "presets": ["@babel/preset-env"]
        }
        

        此时可以直接使用yarn babel-node index.js命令直接运行,不需要额外加参数。

      • preset是一个插件集合,我们移除preset,直接使用插件

        yarn remove @babel/preset-env
        yarn add @babel/plugin-transform-modules-commonjs --dev
        

        这时修改配置文件

        {
          "plugins": [
            "@babel/plugin-transform-modules-commonjs"
          ]
        }
        

        继续运行命令yarn babel-node index.js,这样也是可以的。

    展开全文
  • 模块化开发与规范化标准 文章说明:本专栏内容为本人参加【拉钩大前端高新训练营】的学习笔记以及思考总结,学徒之心,仅为分享。如若有误,请在评论区支出,如果您觉得专栏内容还不错,请点赞、关注、评论。共同...
  • 栖息地实验室是一个模块化的高级库,用于在嵌入式AI中进行端到端开发-定义嵌入式AI任务(例如,导航,指令跟踪,问题解答),配置嵌入式代理(物理形式,传感器,功能),对其进行培训代理(通过模仿或强化学习,...
  • 代码有问题,orl 人脸被命名为 1.pgm 到 400.pgm.5 张图像从每个类中随机抽取用于测试和训练集。图像分为 4 部分。请帮助
  • 随着引用模块化,我们的应用会产生新的问题: 1.ES Modules 存在环境兼容问题 2.模块文件过多,网络请求频繁(每一个我们需要请求的文件都要从网络请求当中请求回来,影响工作效率) 3.所有的前端资源都需要模块化 毋...
  • 基于深度学习理论,提出了一种基于栈式稀疏自动编码器(SSAE)的模块化五电平逆变器(MFLI)子模块开路故障诊断方法。该方法将MFLI子模块开路故障检测与定位问题转化成分类问题,首先将子模块电容电压信号组合成24通道序列...
  • 具体对于可视的阅读和模块的更多使用见下面的链接。 参考链接: ...
  • 模块8 课表查询 参照本模块的课表查询项目完成课表查询手机客户端的程序设计 项目训练课表查询设计 Android模块 项目式教程 综合实训-校园生活小助手 模块9 模块9 综合实训-校园生活小助手 学习目标 了解校园生活...
  • 【文章内容来自拉勾教育大前端高薪训练营课程】
  • 模块化球面项目 该项目旨在创建一个模块化的软机器人,能够在群体中适应和协作。 安装 使用setup.py安装库: sudo python setup.py install 例子 使用键盘箭头键对模块化领域进行遥控操作: python examples/...
  • 针对模块化神经网络结构设计过程中子网络输出不能最优集成的问题,提出一种基于粒子群算法的动态模块化神经网络.首先,该网络采用数据密度辨识样本分布空间,并更新数据中心;然后,根据输入数据激活相应的子网络,利用PSO...
  • 前言 细心的同学会发现上一篇文章中最后完整...关于训练结果可视,我在之前文章中写到过。通过记录终端输出,然后matlab实现。地址:http://blog.csdn.net/renhanchi/article/details/72457630 看第六部分可视内容
  • 利用粗糙集理论对边界角影响因素进行筛选,结合模块化神经网络建立边界角的预计模型。收集了116个地表移动观测站的数据,并将15个影响因素约简到9个,利用其中的100组数据对网络进行训练,其余16组数据作为检验样本。...
  • 2.可视化训练过程 2.1.导入必要模块 import tensorflow as tf import numpy as np import matplotlib.pyplot as plt 2.2.定义添加层函数 def add_layer(inputs,in_size,out_size,activation...
  • 下面我们来探讨如何模块化搭建神经网络,完成数据训练和预测。 首先我们将整体架构分为两个模块: forward.py 和 backward.py forward.py 主要完成神经网络模型的搭建,即构建计算图 backward.py 训练出网络...
  • 某型轰炸机武器模拟训练系统软件的开发采用模块化设计方法,各功能模块负责部分训练功能,为实现模拟训练系统的整体功能,必须使各功能模块协调工作,而功能模块间的数据交换是实现整个系统协调工作的重要途径,结合模拟...
  • JStap是一个模块化的静态恶意JavaScript检测系统。 我们的检测器由十个模块组成,包括五种不同的抽象代码方式(即令牌,抽象语法树(AST),控制流图(CFG),仅考虑数据流的程序依赖图(PDG-DFG)和PDG),以及两种...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,538
精华内容 615
关键字:

模块化训练