要解决的问题
如何引用动态链接库指定的符号
解决方案
动态链接库提供了很多个函数,类或者常量之类的东西,我们统称为symbol。引用了具体的符号才能开始使用。这个需要定义的地方对符号进行导出,使用的地方对符号进行导入。由 binder 进行符号的撮合绑定。
构成
- exported symbol: 动态链接库导出的符号
- imported symbol:导入的符号
- binder:把导入的符号和导出的符号绑定到一起
解决方案案例
传统浏览器
传统浏览器没有 binder。全局共享一个namespace(window对象),动态链接库导出和导入通过读写全局变量实现。
支持 ES6 Module 的浏览器或者 nodejs
- exported symbol
export function my_func() {}定义和export合一function my_func() {}; export {my_func as my_exported_func}定义和export分离export default function my_func() {}export成为特殊的符号default
- imported symbol
import './library.mjs'只加载动态链接库,但是并不导入符号import {my_func} from './library.mjs'导入动态链接库中的指定符号 my_funcimport my_func from './library.mjs'把导出的default符号,导入并重命名为 my_funcimport * as lib from './library.mjs'把动态链接库整体导入为 lib
- binder:浏览器或者nodejs
ES6 Module 的导入的是引用,如果源对象发生了变化,导入的符号也会跟着变化
// /opt/library.mjs
export let my_var = 3
export function increase_my_var() {
my_var++
}
// /opt/executable.mjs
import {my_var, increase_my_var} from './library.mjs'
console.log(my_var)
increase_my_var()
console.log(my_var)
node --experimental-modules executable.mjs
// Output:
// 3
// 4
nodejs
- exported symbol
exports.my_func = function() {}定义和export合一function my_func() {}; exports.my_exported_func = my_func定义和export分离module.exports = function() {}只导出一个符号,导入的时候也无需选择
- imported symbol
require('./library.js')只加载动态链接库,但是并不导入符号const my_func = require('./library.js').my_func导入链接库中的指定符号 my_funcconst lib = require('./library.js')把动态链接库整体导入为 lib binder:nodejs
nodejs 的 require 语法的导入是拷贝值的行为,和ES6 Module不同
// /opt/library.js
exports.my_var = 3
exports.increase_my_var = function() {
exports.my_var++
}
// /opt/executable.js
const {my_var, increase_my_var} = require('./library.js')
console.log(my_var)
increase_my_var()
console.log(my_var)
console.log(require('./library.js').my_var)
node executable.js
// Output:
// 3
// 3
// 4
我们可以看到导入这份 my_var 没有改变,而原始的那份 my_var 已经改变了。
定义唯一导出符号需要重新定义 module.exports
// /opt/library.js
module.exports = function() {
console.log('library called')
}
// /opt/executable.js
const my_func = require('./library.js')
my_func()
node executable.js
// Ouptut:
// library called