zoukankan      html  css  js  c++  java
  • 【读书笔记】《深入浅出nodejs》第二章 模块机制

    1.什么是模块?

      指在程序设计中,为完成某一功能所需的一段程序或子程序;或指能由编译程序、装配程序等处理的独立程序单位;或指大型软件系统的一部分。 ----《百度百科》

    2.JavaScript缺乏模块机制。

      -> 薄弱的JavaScript规范:

        (1)没有模块系统;

        (2)标准库较少(对于I/O流,文件系统等常见需求没有标准API);

        (3)没有标准接口(没有Web服务器或数据库之类的标准统一接口);

        (4)缺乏包管理系统(使JavaScript应用中基本没有自动加载和安装依赖的能力);

      -> CommonJS规范(大部分为草案):

        (1)内容:模块    二进制    Buffer    字符集编码    I/O流    进程环境    文件系统    套接字  单元测试  Web服务器网关接口  包管理  ...

        (2)目的:使用CommonJS API写出的应用可以具备跨宿主环境执行的能力。

      -> CommonJS模块规范:

        (1)【模块引用】:

    var math = require('math'); // require()方法 -> 接受模块标识,并引入一个模块的API到当前上下文。

        (2)【模块定义】:

          require() 方法 -> 导入模块 

          exports() 方法 -> 导出当前模块的方法或变量(唯一的导出口)  ----

                                           |---->  JS文件中

          module对象 -> 存在于模块中,代表模块自身,拥有exports属性 ----

        (3)【模块标识】:

          传递给require()方法的参数,

          必须符合小驼峰命名的字符串,

          或以.、..开头的相对路径或绝对路径,

          可以没有.js后缀。

       ->模块规范的意义

        “使用户可以在完全不必考虑变量污染的前提下,建立上下游的依赖关系。”

    3.Node的模块实现

      (1)模块引入的步骤:

        A.【路径分析】(通过模块标识符):

          -> 模块标识符的分类:

            -> 核心模块,如http、fs、path等;

            -> .或..开始的相对路径文件夹;

            -> 以/开始的绝对路径文件模块;

            -> 非路径形式的文件模块,如自定义的connect模块。

        B.【文件定位

          -> 文件扩展名分析

          -> 目录分析和包

        C.【编译执行

          在Node中,每个文件模块都是一个对象,其定义如下:

    function Module(id, parent) {
            
        this.id = id;
    
        this.exports = {};
    
        this.parent = parent;
    
        if (parent && parent.children) {
            
            parent.children.push(this);
        
        }
    
        this.filename = null;
    
        this.loaded = false;
    
        this.children = [];
    
    }

      (2)模块分类:

        A.核心模块 -- Node提供的模块 (仅需路径分析,加载速度快)

        B.文件模块 -- 用户编写的模块(三步执行,加载速度较慢)

      (3)模块的缓存加载:

        无论是核心模块还是文件模块,require()方法对相同模块的二次加载都一律采用缓存优先的方式,这是第一优先级的。

    4.Node核心模块

      (1)JavaScript编写的核心模块(存放在lib目录下) -> 需转存为C/C++代码

        *与文件模块的区别:

          A. 获取源码的方式(核心模块是从内存中加载的)

          B. 缓存执行结构的位置

      (2)C/C++编写的核心模块(存放在src目录下)-> 统称为“內建模块”(buffer、crypto、evals、fs、os等模块)

        优势:

          A. 性能优于脚本语言

          B. 被编译进二进制文件,一旦Node开始执行,他们被直接加载仅内存中,无需在做标识符定位、文件定位、编译等过程,直接就可以执行

        內建模块的导出:

          内建模块 -> 核心模块 -> 文件模块

    5.包与NPM

      包与NPM是将模块联系起来的一种机制。

      模块 -> 一定程度上解决了变量依赖、依赖关系等代码组织性问题

      包 -> 在模块的基础上进一步组织JavaScript代码

      (1)包规范 -- 帮助Node解决依赖包安装的问题。

        A. 包结构

          包实际上是一个存档文件,即一个目录直接打包为.zip或tar.gz格式的文件,安装后解压还原为目录。

          完全符合CommonJS规范的包目录应该包含如下这些文件。

            package.json :包描述文件 -> name(包名),description(简介),version(版本号),keywords(关键词数组),maintainers(包维护者列表)

            bin :用于存放可执行二进制文件目录

            lib :用于存放JavaScript代码的目录

            doc :用于存放文档目录

            test :用于存放单元测试用例的代码

        B. 包描述

          用于表达非代码相关的信息,它是一个JSON格式的文件 -- package.json 位于包的根目录下,是包的重要组成部分。

          NPM的所有行为斗鱼包描述文件的字段息息相关。

      (2)NPM -- 包规范的一种实践,帮助完成了第三方模块的发布、安装和依赖等。

        借助NPM,Node与第三方模块之间形成了很好的生态系统。

        借助NPM,可以帮助用户快速安装和管理依赖包。

      (3)安装包,引用包,发布包

        安装包:$npm install express -> node_modules > express

        引用包:require()

        发布包:保存js文件 -> $npm init -> $npm adduser -> npm pulish <folder>

      (4)NPM的潜在问题 -> 包质量与安全问题

    6.前后端功用模块

      前后端JavaScript分别搁置在HTTP的两端,他们扮演的角色并不同。

      浏览器端的JavaScript需要经历从同一个服务器端分发到多个客户端执行 -> 瓶颈在于带宽 -> 需要网络加载代码(慢)

      服务器端的JavaScript需要经历相同的代码需要多次执行 -> 瓶颈在于CPU和内存资源 -> 直接从磁盘中加载(块)

      解决的方式 -> AMD规范 && CMD规范

      AMD规范:

        AMD规范是CommonJS模块的一个延伸。

        define(id?, dependencies?, factory);

        id : 模块id(可选)

        dependencies : 依赖(可选)

        factory : 实际的代码内容

      CMD规范:

        更接近CommonJS规范的定义。

        define(factory)

        在依赖部分,支持动态引入:

        define(function(require, exports, module) {

          // The module code goes here

        });

        require、exports和module通过形参传递给模块,在需要依赖模块时,随时调用require()引入。

  • 相关阅读:
    JS运行机制之 Event Loop 的思考
    模块机制 之commonJs、node模块 、AMD、CMD
    git报错:'fatal:remote origin already exists'怎么处理?附上git常用操作以及说明。
    Uncaught RangeError: Maximum call stack size exceeded-栈溢出
    对循环内部反复声明变量的写法的一点想法?
    JS的forEach和map方法的区别
    函数的属性和方法之call、apply 及bind
    利用Apach ab对nodejs进行并发负载的压力测试
    怎么判断一个对象是不是数组类型?
    Python模块学习之fabric
  • 原文地址:https://www.cnblogs.com/libinfs/p/5915875.html
Copyright © 2011-2022 走看看