require OR import

以前在CommonJS中,我们用module.exports和require来导出和导入模块,而到了ES6却变成了export和import了,这两者到底有什么区别呢?
  一句话总结:CommonJS模块是运行输出(加载)一个值(或对象)的拷贝,而ES6模块则是编译时输出(加载)一个值的引用(或者叫做连接).
  这样的差异在平常使用是不易被察觉的,可是一旦出现循环引用,两者的差异就很明显了。直接的循环引用(a引用b,b又引用a)一般不会有,但在依赖关系复杂的大项目中,很容易出现a引用b,b引用其它模块,在若干次引用后,模块n又引用回a这样的情况。为了讲解的方便我们直接构造出一个a,b相互引用的项目。
  首先,我们来看看CommonJS模块中的现象:

// APage.js 关键代码
let BPage = require('./BPage');
class APage extends Component {
  render() {
    return (
      <View style={styles.containerAll} >
        <TouchableOpacity style={styles.btn} onPress={this.onPress.bind(this)}>
            <Text>PushToB</Text>
        </TouchableOpacity>
      </View>
    );
  } 
  onPress() {
    this.props.navigator.push(BPage);
  }
}
var route = {
  key: 'APage',
  component: APage,
};
module.exports = route;

// BPage.js 关键代码
let APage = require('./APage');
class BPage extends Component {
  constructor(props) {
    super(props);
    console.log('BPage alloc');
  }
  render() {
    return (
      <View style={styles.containerAll} >
        <TouchableOpacity style={styles.btn} onPress={this.onPress.bind(this)}>
            <Text>resetToA</Text>
        </TouchableOpacity>
      </View>
    );
  }
  onPress() {
    this.props.navigator.resetTo(APage);
  }
}
var route = {
  key: 'BPage',
  component: BPage,
};
module.exports = route;

commonJS.png

  可以看到,APage正常显示,并且点击PushToB可以正常显示出BPage,可从BPage再Reset到APage就成了空白了。这是为什么呢?
  我们来仔细分析一下整个过程:CommonJS的一个模块,就是一个脚本文件,require命令第一次加载该脚本,就会执行整个脚本,然后在内存生成一个对象。本例在index.js中先require了APage.js,那就开始执行该脚本,可是在执行过程中先遇到了let BPage = require('./BPage');这时候就会先去执行BPage.js。在BPage.js中又会遇到let APage = require('./APage');但这时候APage.js已经开始执行了,不会重复执行,所以系统会去模块对应的exports属性取值,可是因为APage.js还没执行完,从exports属性中只能取回已经执行的部分,所以APage还是空的,也就是说resetTo(APage)其实是reset到一个空。接着BPage.js会继续往下执行,等到全部执行完毕,再把执行权还给APage.js
  从上面的例子可以看出,在复杂项目中加载CommonJS模块需要非常小心处理各模块之间的引用关系。接下来我们来看看同样的场景在ES6中会是怎样:

// APage.js 关键代码
import BPage from './BPage';
...//中间部分与上文相同,故不重复贴代码
export default route;

// BPage.js 关键代码
import APage from './APage';
...//中间部分与上文相同,故不重复贴代码
export default route;

ES6.png

  只是把导入和导出改为import和export,这一次就可以顺利走完整个流程,得到我们想要的。这是因为import只是指向被加载模块,我们只需要保证真正取值的时候能够取到值即可。与require时相同,在APage.js中遇到import BPage from './BPage';也是会先去执行BPage.js,也就是说BPage.js在遇到import APage from './APage';时,APage.js同样是没执行完,这时候APage是undefined。不同的是使用import从一个模块加载变量,那些变量不会被缓存,而是成为一个指向被加载模块的引用。所以等到BPage.js执行完,把控制权交回给APage.js,这时就一切正常了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容