import与export在node.js中的使用

作者: 炙热地瓜 | 来源:发表于2017-09-11 15:19 被阅读303次

    简述

    import与export是es6中模块化的导入与导出,node.js现阶段不支持,需要通过babel进行编译,使其变成node.js的模块化代码。(关于node.js模块,可参考其他node.js模块化的文章�)

    export 曝露

    使用export可以曝露出方法、对象、字符串等等,如下代码

    //写法1
    export var foo=function(){
        console.log(1);
    }
    //写法2
    var bar ={a:"1",b:2};
    export {bar};
    //写法3
    var baz='hello world';
    export {baz as qux};
    

    那么,上面的代码经过babel的编译后,变成可以执行的node.js代码,如下

    "use strict";
    //标记这个模块是es的模块
    Object.defineProperty(exports, "__esModule", {
        value: true
    });
    //写法1
    var foo = exports.foo = function foo() {
        console.log(1);
    };
    //写法2
    var bar = { a: "1", b: 2 };
    exports.bar = bar;
    //写法3
    
    var baz = 'hello world';
    exports.qux = baz;
    

    看到上面的代码我们知道了,es6的export会被转成node.js中的exports的曝露方式。

    import 导入

    再来看下import的写法,我们引入上面写export的文件xx.js

    第一种写法

    import {foo,qux} from './xx';
    console.log(qux);
    

    foo,qux是在xx.js中我们曝露出来的属性,在xx.js中曝露出来的属性有foo、bar、qux3个,由此可知这种写法需要知道引入文件中曝露出来的属性的名称,并且可以按需要写,不需要枚举全部属性。
    下面我们来看下babel编译后的代码:

    'use strict';
    var _ = require('./xx');
    console.log(_.qux);
    

    就是一个简单的require方法,引入xx.js,所以用这种方式我们是可以引入es6的模块也可以引入node.js模块的。

    第二种写法

    import * as xx from './xx';
    console.log(xx.bar);
    

    这里还是引入xx.js,这种写法会把xx.js中曝露出来的属性都赋值给xx这个变量(其实就是给module.exports起个别名),被babel编译后如下下:

    'use strict';
    var _ = require('./xx');
    var xx = _interopRequireWildcard(_);
    function _interopRequireWildcard(obj) {
        //判断是node模块还是es模块
        if (obj && obj.__esModule) {
            return obj;
        }
        else {
            var newObj = {};
            if (obj != null) {
                for (var key in obj) { 
                    if (Object.prototype.hasOwnProperty.call(obj, key)) 
                     newObj[key] = obj[key];
                }
            }
       //兼容旧的babel编译
            newObj.default = obj;
            console.log(newObj);
            return newObj;
        }
    }
    console.log(xx.bar);
    

    看到上面的代码,有一个判断是node模块还是es模块,这种写法也是兼容es模块和node的模块的。

    第三种写法

    import oo from './xx'
    console.log(oo.bar);
    

    在这种写法中oo是随意的变量,乍一看可能会觉的和第二种写法一样,其实不然,来看一下编译后的代码:

    'use strict';
    var _ = require('./xx');
    var _2 = _interopRequireDefault(_);
    function _interopRequireDefault(obj) { 
      return obj && obj.__esModule ? obj : 
      { default: obj }; 
    }
    console.log(_2.default.bar);
    

    在最后一行,oo.bar被编译成了_2.default.bar,多了一个default,这里的bar当然就找不到了,所以这种用法不是用来引入export的属性的,而是下面要说的export default。

    export default 曝露且一次性曝露

    export与export default我会在别的文章总结,这里我们只说export default的用法,下面来看代码。

    var foo=123;
    export default foo;
    

    被babel编译后

    "use strict";
    Object.defineProperty(exports, "__esModule", {
      value: true
    });
    var foo = 123;
    exports.default = foo;
    

    看到最后一行foo会被赋给exports.default,这样正好对应上了import oo from './xx'这种写法里面会调用default里面的属性,所以这两种用法对应使用。既然属性的值是会赋给exports.default,那么就可以有下面的用法

    export default 123;
    
    export default {foo:123};
    
    export default function f(){}
    
    export default function (){}
    

    上面的代码是分开写的,因为一个js里面只能使用一次export default,理由和使用module.exports一样,除了不能写多个,下面也是错误的写法:

    export default var foo=123; //错误
    

    export default还可以用来曝露class这里不多说了,都是曝露。

    其他的一些用法

    继承

    这里说是模块继承,其实就是一个父模块引入子模块,然后又将子模块曝露出来的属性曝露出去:

    export * from './xx';
    

    被编译后

    'use strict';
    Object.defineProperty(exports, "__esModule", {
      value: true
    });
    var _ = require('./xx');
    Object.keys(_).forEach(function (key) {
      if (key === "default" || key === "__esModule") return;
      Object.defineProperty(exports, key, {
        enumerable: true,
        get: function get() {
          return _[key];
        }
      });
    });
    

    注意下面这句

    if (key === "default" || key === "__esModule") return;
    

    default属性不向外曝露...这说明,我们的引入的xx.js这个文件里面用exports default是无效的,替代写法是

    export {default} from './xx';
    

    继承的写法常用于组织多个模块,经常与下面要说的引包一起用

    引文件夹(引包)

    很多人不理解下面这行代码

    import * as o from './oo';  //oo是个文件
    

    为什么import可以引入文件夹,注意不是什么文件夹都可以,里面至少有一个文件就是index.js或者有package.json和另外名字的js,因为文件夹里面有index.js那么这就不是一个文件夹而是node.js的包了(更多参见node.js包的文章),import会被babel编译成require,require可以去引用指定路径的包,因此,import可以去导入一个文件夹,我们可以依赖index.js将文件夹中的其他文件代码导出,例如:

    8AEC47A4-CC79-4F6F-A1EC-32AA6E95BEDC.png
    //index.js
    export * from './1';
    export * from './2';
    

    我们可以通过import oo这个文件夹得到1.js、2.js里面曝露出的属性。

    总结

    从看babel编译后的代码,可以看出export与exports,module.exports与export default的用法的相似,至于用什么怎么用还是看个人喜好吧。

    相关文章

      网友评论

        本文标题:import与export在node.js中的使用

        本文链接:https://www.haomeiwen.com/subject/xaxejxtx.html