最近总碰到类似于

var a = require('./expample.js).default

这样的代码,感觉很奇葩,总结一波。

为什么会出现这个问题?

import 是静态编译的,而 require 可以动态加载,也就是说你可以通过判断条件来决定什么时候去 require ,而 import 则不行,所以有时候我们会面临需要通过require 去导入一个es6模块(比如react-hot-loader官方demo :P)

当然,这只是场景之一。

前置知识

  1. ES6 Module常用语法。譬如export导出模块接口 | import 倒入模块| export default语法糖
  2. Node.js模块常用。譬如module.exports | require
  3. ES6模块与commonjs模块的区别(静态编译与动态加载 | 值得引用与值的拷贝)

如果上述前置知识您有所不了解的话,建议拜读一下阮一峰老师的《ECMAScript 6 入门》一书中的两个章节:

  1. Module 的语法
  2. Module 的加载实现

如果您已经具备了上述知识,我们来讨论一下

  1. export default为什么是语法糖
  2. require一个ES6 Module

export default为什么是语法糖

default关键字 说白了,就是别名(as)的语法糖

以下代码应当是非常常见的:

导出接口

// a.js
function a(){}
export {a}

导入模块

// b.js
import {a} from './a'

花括号就是解构赋值的语法,我们可以理解为export导出了一个对象,对象里存在a这个函数,就像下面这样

{
a:function(){}
}

于是就有了后面的通过结构赋值取出a,所以变量名必须一致。

ECMAScript 6 入门:从前面的例子可以看出,使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。
为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。

default可以理解为这一语法的语法糖

导出接口

// d.js
export default function() {} // 等效于:
function a() {};
export {a as default};

导入模块

import a from './d';

// 等效于,或者说就是下面这种写法的简写,是同一个意思
import {default as a} from './d';

这个语法糖的好处就是import的时候,可以省去花括号{}。

简单的说,如果import的时候,你发现某个变量没有花括号括起来(没有*号),那么你在脑海中应该把它还原成有花括号的as语法。

本质上依旧是结构赋值呀,只不过我们写的更为简便,假装花括号消失了罢了。

如何require一个ES6 Module

stackoverflow上有一个针对本文题目比较好的回答,原文如下:

Finally, the require and require.default... when dealing with ES6 imports (export default MyComponent), the exported module is of the format {"default" : MyComponent}. The import statement correctly handles this assignment for you, however, you have to do the require("./mycomponent").default conversion yourself. The HMR interface code cannot use import as it doesn't work inline. If you want to avoid that, use module.exports instead of export default.

我来翻译下原文

最后,require和require.default...当在node中处理ES6 模块(export default mycomponent)导入的时候,导出的模块格式为

{
"default": mycomponent
}

import
语句正确地为你处理了这个问题,然而你必须自己执行 require("./mycomponent").default. HMR(热更新模块)不在 inline 模式工作的情况下,接口代码不能使用 import ,如果你想避免,使用module.exports而不是export default;

上文提到过,export 关键字是导出一个对象,对象内存在一个属性(我们要暴露的),export default 则是 export 语法糖,import 一个export default 暴露出来的模块包含了解构赋值的步骤,所以在node中使用require去请求一个export default的模块需要我们通过.语法去取出对象中的属性(因为require木有解构赋值),清晰明了。

换个说法,如果 require 的 commonjs规范的模块,即:
导出:

// a.js
module.exports = {
a:'helloworld'
}

导入:

// b.js
var m = require('./a.js');
console.log(m.a); // helloworld

这样就显得非常清晰,我们 module.exports 的是啥,require 的就是啥。

但export default包装了一层语法糖,让我们看得不甚清晰:

const a = 'helloworld';
export default a;

其实导出的是

{
"default": a
}

而并非 a 这个变量,这就是我为什么之前要强调语法糖了,如果你将 export default 还原为:

const a = 'helloworld';
export {a as default}

是不是就能清楚一点了呢。

我们的疑问也就迎刃而解了。

注:以上所有代码都是在webpack开发环境(babel)中运行(保证ES6模块语法可以被识别)。

参考:Node中没搞明白require和import,你会被坑的很惨

require('./expample.js).default详解的更多相关文章

  1. js对象详解(JavaScript对象深度剖析,深度理解js对象)

    js对象详解(JavaScript对象深度剖析,深度理解js对象) 这算是酝酿很久的一篇文章了. JavaScript作为一个基于对象(没有类的概念)的语言,从入门到精通到放弃一直会被对象这个问题围绕 ...

  2. OpenWrt之feeds.conf.default详解

    目录 OpenWrt之feeds.conf.default详解 文件内容 命令解释 src-svn与src-gitsvn src-git与src-git-full src-cpy与src-link 其 ...

  3. Node.js npm 详解

    一.npm简介 安装npm请阅读我之前的文章Hello Node中npm安装那一部分,不过只介绍了linux平台,如果是其它平台,有前辈写了更加详细的介绍. npm的全称:Node Package M ...

  4. dva.js 用法详解:列表展示

    本教程案例github:https://github.com/axel10/dva_demo-Counter-and-list/tree/master 这次主要通过在线获取用户数据并且渲染成列表这个案 ...

  5. Vue.js项目详解

    还是以Blog项目来讲解,最近我本人利用闲暇时间,以博客作为参考学习一些新的技术并尝试之前没有尝试过的思路来玩玩. 技术看似枯燥,但是带有一个目的来学,你会发现还是蛮有趣的. 主要实践的就是前后端分离 ...

  6. JS 面向对象详解

    面向对象详解1 OO1.html <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...

  7. 开胃小菜——impress.js代码详解

    README 友情提醒,下面有大量代码,由于网页上代码显示都是同一个颜色,所以推荐大家复制到自己的代码编辑器中看. 今天闲来无事,研究了一番impress.js的源码.由于之前研究过jQuery,看i ...

  8. jquery图片切换插件jquery.cycle.js参数详解

    转自:国人的力量 blog.163.com/xz551@126/blog/static/821257972012101541835491/ 自从使用了jquery.cycle.js,我觉得再也不用自己 ...

  9. 值得收藏的js原型详解

    从虚无到Object 起初,地是空虚混沌,渊面黑暗:这时候一切还是null 神说,要有原型,于是就有了prototype 原型从凭空产生,于是需要一个指向于null的特征,人们把这种特征叫做隐式原型, ...

随机推荐

  1. 洗礼灵魂,修炼python(76)--全栈项目实战篇(4)—— 购物车系统

    要求: 1.基本符合日常购物车的要求(根据你的想法开放性提升功能) 2.展示商品信息,并且可随时上新商品 3.用户购买每一样商品时都对所剩的钱做一次对比,如果够则提示“已购买”,如果不够提示“余额不足 ...

  2. Linux学习历程——Centos 7 cat命令

    一.命令介绍 我们使用man cat命令,可以看到cat命令的用途是连接文件或标准输入并打印,简单来说cat命令是用来查看纯文本文件(通常为内容较少的文件),与重定向符号配合使用,可以实现创建文件与合 ...

  3. 好系统重装助手教你如何让win10系统快速开机

    电脑开机的时候,有一些自动开启的软件或工具会占用一定的开机时间,把它们禁止开机启动项就会提高电脑开机速度.很多人会借助360或者电脑管家等软件来设置,下面小编就来教大家一招不借助第三方工具来禁止win ...

  4. php学习----面向对象

    面向对象 项目代码都应该由单个能起子程序作用的对象组成 重用性.灵活性.扩展性 变量 $this 代表自身的对象. PHP_EOL 为换行符. PHP 中创建对象 类创建后,我们可以使用 new 运算 ...

  5. GitHub-标签管理

    参考博文:廖雪峰Git教程 1. 创建标签 切换到需要打标签的分支上,之后打标签 [root@mini05 zhangtest]# git branch dev * master [root@mini ...

  6. 枚举应用demo

    package com.xx; public enum PositionEM{ ONE(1,"领导"), TWO(2,"员工"); private Long v ...

  7. ELK+Kafka 企业日志收集平台(一)

    背景: 最近线上上了ELK,但是只用了一台Redis在中间作为消息队列,以减轻前端es集群的压力,Redis的集群解决方案暂时没有接触过,并且Redis作为消息队列并不是它的强项:所以最近将Redis ...

  8. 使用Docker在本地搭建Hadoop分布式集群

    学习Hadoop集群环境搭建是Hadoop入门必经之路.搭建分布式集群通常有两个办法: 要么找多台机器来部署(常常找不到机器) 或者在本地开多个虚拟机(开销很大,对宿主机器性能要求高,光是安装多个虚拟 ...

  9. vue源码分析—数据绑定

    放进沙里附件拉萨就发牢骚:剑飞:啊撒

  10. 11175-From D to E and Back(思维)

    Problem UVA11175-From D to E and Back Accept: 164  Submit: 607Time Limit: 3000 mSec Problem Descript ...