以前在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   可以看到,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   只是把导入和导出改为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,这时就一切正常了。