码迷,mamicode.com
首页 > 编程语言 > 详细

知识点【JavaScript模块化】

时间:2017-10-16 19:45:21      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:style   定义   img   sts   first   两种   核心   查找   参考   

JavaScript模块化历程

JavaScript发展变迁大概是一下几个步骤:

  • 工具(浏览器兼容)

  • 组件(功能模块)

  • 框架(功能模块组织)

  • 应用(业务模块组织)

但是经过了长长的后天努力过程JavaScript不断被类聚抽象,以更好的组织业务逻辑。从另一个角度而言,他也道出了JavaScript先天就缺乏的一项功能:模块

虽然W3C组织对HTML5规范推进以及各大厂对规范的大力支持,但是对于JavaScript本身而言,它的规范依然是薄弱的,它还有以下缺陷:

  • 没有标准模块系统

  • 标准库少(ECMAScript仅定义了部分核心库)

  • 没有标准接口(JavaScript几乎没有定义过如WEB服务器数据库操作之类的标准统一接口)

  • 缺乏包管理系统

CommonJS规范

CommonJS规范的提出,主要为了弥补JavaScript没有标准的缺陷,以达到想Python、Ruby和Java具备开发大型应用的基础能力,而不是停留在小脚本程序的阶段。

它的使用和定义也非常简单

CommonJS的模块规范

1 模块定义

// example.js
var x =5;
var addx = function (value){
    return value + x;
}
module.exports.x = x;
module.exports.addx = addx;

 定义关键字是exports这个module是什么意思呢:在CommonJS定义了每个文件都一个模块,也就是说module代表文件本身

2 模块引用

var example = require(‘./example.js‘);

console.log(example.x);  // 5
console.log(example.addx(1)); // 6

CommonJS模块特点如下:

  • 所有代码都运行在模块作用域,不会污染全局作用域。

  • 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。

  • 模块加载的顺序,按照其在代码中出现的顺序。

3 看图

用一个图很明显的看出它们之间的引用关系

技术分享

 

模块的实现

在Node中引入模块,需要经历3个步骤

1、路径分析

2、文件定位

3、编译执行

 

在Node中模块分为两类:一类是Node提供的模块,称为核心模块;另一类是用户编写的模块称为文件模块

ES6 Module

ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。

// CommonJS模块
let { stat, exists, readFile } = require(‘fs‘);

// 等同于
let _fs = require(‘fs‘);
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;

上面代码的实质是整体加载fs模块(即加载fs的所有方法),生成一个对象(_fs),然后再从这个对象上面读取3个方法。这种加载称为“运行时加载”,因为只有运行时才能得到这个对象,导致完全没办法在编译时做“静态优化”。

ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。

 

与CommonJS思想类似

1 模块定义

// profile.js
export var firstName = ‘Michael‘;
export var lastName = ‘Jackson‘;
export var year = 1958;

上面代码是profile.js文件,保存了用户信息。ES6 将其视为一个模块,里面用export命令对外部输出了三个变量。

export的写法,除了像上面这样,还有另外一种。

// profile.js
var firstName = ‘Michael‘;
var lastName = ‘Jackson‘;
var year = 1958;

export {firstName, lastName, year};

通常情况下,export输出的变量就是本来的名字,但是可以使用as关键字重命名。

function v1() { ... }
function v2() { ... }

export {
  v1 as streamV1,
  v2 as streamV2,
  v2 as streamLatestVersion
};

注意规范:

export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。

// 报错
export 1;

// 报错
var m = 1;
export m;

上面两种写法都会报错,因为没有提供对外的接口。第一种写法直接输出1,第二种写法通过变量m,还是直接输出1。1只是一个值,不是接口。正确的写法是下面这样。

// 写法一
export var m = 1;

// 写法二
var m = 1;
export {m};

// 写法三
var n = 1;
export {n as m};

functionclass的输出,也必须遵守这样的写法。

// 报错
function f() {}
export f;

// 正确
export function f() {};

// 正确
function f() {}
export {f};

另外,export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。

2 模块引用

// a.js
let a = 18;
let funcA = function () {
    console.log(‘module A‘)
};

// 提供一个对外的借口并输出a变量和funcA方法
export {a, funcA}

引用

import {a, funcA} from "./a";

// 通过import 引入里面的变量和方法
console.log(a);
console.log(funcA());

引用的时候可以设置别名

import {a as aValue, funcA} from "./a";

// 通过import 引入里面的变量和方法
console.log(aValue);
console.log(funcA());

3 export default命令

从前面的例子可以看出,使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。

为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出

本质上,export default就是输出一个叫做default的变量或方法,然后系统允许你为它取任意名字

// export-default.js
export default function () {
  console.log(‘foo‘);
}

然后你可以随便命名

// import-default.js
import customName from ‘./export-default‘;
customName(); // ‘foo‘

但是正常引入模块的情况下你必须指定你要引入的变量或者方法,像下面一样:

import {funcA} from "./a.js";  // 这里你在引用的时候你必须知道a.js中定义的方法的名字

比较下正常和export default不同

// 第一组
export default function crc32() { // 输出
  // ...
}

import crc32 from ‘crc32‘; // 输入

// 第二组
export function crc32() { // 输出
  // ...
};

import {crc32} from ‘crc32‘; // 输入

 

参考资料:http://es6.ruanyifeng.com/#docs/module

 

知识点【JavaScript模块化】

标签:style   定义   img   sts   first   两种   核心   查找   参考   

原文地址:http://www.cnblogs.com/luotianshuai/p/7677691.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!