导出原始类型
通过兼容性处理的几个例子,我们可以观察到 es6 module 和 commonjs 的导出值其实是不同的。
esmodule 和 commonjs 导出值的区别
- esmodule 引用导出
- commonjs 值导出
我们拿个具体的例子来说事,代码我拷贝过来了。
/** ./src/index.js **/
let title = require('./title');
console.log(title.default);
console.log(title.age);
/** ./src/title.js **/
export default 'title_name';
export const age = 'title_age';
;(()=>{
var modules = {
'./src/title.js':(module, exports, require)=>{
require.r(exports);
require.d(exports, {
default: () => DEFAULT_EXPORT,
age: () => age
});
const DEFAULT_EXPORT = 'title_name';
const age = 'title_age';
}
}
var cache = {};
function require(moduleId){
if(cache[moduleId]){
return cache[moduleId].exports
}
var module = cache[moduleId] = {
exports: {}
};
modules[moduleId](module, module.exports, require);
return module.exports;
}
require.r = (exports) => {
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
Object.defineProperty(exports, '__esModule', { value: true })
}
require.d = (exports, definition) => {
for(var key in definition){
Object.defineProperty(exports, key, { get: definition[key] })
}
}
let title = require('./src/title.js');
console.log(title.default);
console.log(title.age);
})()
ES6 Module 引用导出
在这个例子中 title.js 是一个 ES6 Module,所以他是一个引用导出。
我们修改一下代码,把 DEFAULT_EXPORT 和 age 的标识改成 var 方便后面修改值。用 setTimeout 延迟 1s 设置 age 的值为 new_title_age, 然后再 3s 后再打印结果
;(()=>{
var modules = {
'./src/title.js':(module, exports, require)=>{
require.r(exports);
require.d(exports, {
default: () => DEFAULT_EXPORT,
age: () => age
});
// 将标识改成 var 方便后面修改
var DEFAULT_EXPORT = 'title_name';
var age = 'title_age';
// 在 1s 之后改变 age 的值
setTimeout(()=>{
age = "new_title_age";
}, 1000)
}
}
var cache = {};
function require(moduleId){
if(cache[moduleId]){
return cache[moduleId].exports
}
var module = cache[moduleId] = {
exports: {}
};
modules[moduleId](module, module.exports, require);
return module.exports;
}
require.r = (exports) => {
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
Object.defineProperty(exports, '__esModule', { value: true })
}
require.d = (exports, definition) => {
for(var key in definition){
Object.defineProperty(exports, key, { get: definition[key] })
}
}
let title = require('./src/title.js');
console.log(title.default);
// 在 3s 后打印 age
setTimeout(()=>{
console.log(title.age);
}, 3000)
})()
结果如下:
发现打印的变成了 new_title_age。说明 ES6 Module 中导出值之后,只要引用的那个变量变了,仍然会导致在引用这个模块的模块中值发生变化。
commonjs 值导出
我们再来看一下值导出是怎么样的。
我们为了方便,直接在 模块定义中加一个模块
;(()=>{
var modules = {
'./src/title.js':(module, exports, require)=>{
require.r(exports);
require.d(exports, {
default: () => DEFAULT_EXPORT,
age: () => age
});
var DEFAULT_EXPORT = 'title_name';
var age = 'title_age';
setTimeout(()=>{
age = "new_title_age";
}, 1000)
},
// 新增一个 commonjs 模块
'./src/common.js':(module, exports, require) => {
var age = 'title_age';
exports.age = age;
// 在 1s 之后改变 age 的值
setTimeout(()=>{
age = "new_title_age";
}, 1000);
}
}
var cache = {};
function require(moduleId){
if(cache[moduleId]){
return cache[moduleId].exports
}
var module = cache[moduleId] = {
exports: {}
};
modules[moduleId](module, module.exports, require);
return module.exports;
}
require.r = (exports) => {
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
Object.defineProperty(exports, '__esModule', { value: true })
}
require.d = (exports, definition) => {
for(var key in definition){
Object.defineProperty(exports, key, { get: definition[key] })
}
}
let title = require('./src/common.js');
// 在 3s 后打印 age
setTimeout(()=>{
console.log(title.age);
}, 3000)
})()
结果如下:
我们发现即使在 1s 后改变了导出的值,但是在引入模块中返回的值并没有改变,还是 title_age。这就是值引用。
导出引用类型
commonjs 导出引用地址:
- 地址变了,无影响。
- 如果地址对应的属性变了,有影响。
//.... var modules = { './src/common.js':(module, exports, require) => { var age = { x: 1 }; exports.age = age; // 在 1s 之后改变 age 的值 setTimeout(()=>{ //age = { x: 2 }; 无影响 最终打印的还是 { x: 1 } age.x = 2; // 有影响 最终打印的就变成了 { x: 2 } }, 1000); } } //...