基於CommonJS中的導入和導出

# CommonJS中的導出ide

// cal.js中導出一個對象
module.exports = {
  name: 'cal',
  add: function(a, b) {
    return a + b;
  }
}
// 爲了書寫方便,能夠像下面簡寫
exports.name = 'cal';
exports.add = function(a, b) {
  return a + b;
}

上面兩段代碼,在實現效果上沒有任何的不一樣.ui

其內在機制是將exports指向了module.exports,而moudle.exports在初始化時是一個空對象.咱們能夠簡單的理解爲,CommonJS在每一個模塊的首部默認添加了如下代碼:spa

var module = {
  exports: {}
}

var exports = module.exports

所以,爲exports.add賦值,至關於在module.exports對象上添加了一個屬性對象

# 注意:blog

在使用exports時要注意一個問題,即不要直接給exports賦值,不然致使其失效,如:接口

exports = {
  add: function(a, b) {
    return a + b;
  }
}

上面代碼中,因爲對exports進行了賦值操做,使其指向了一個新的對象,module.exports卻仍然是原來的空對象,所以add屬性並不會被導出,例以下面這個代碼:it

var module = {
  exports: {}
}

var exports = module.exports

console.log(exports === module.exports) // true
exports = {
  add: function(a, b) {
    return a + b
  }
}
console.log(exports === module.exports) // false  注意這個地方是false

# 注意:io

另外一個須要注意的問題,module.exports和exports不要混用console

exports.add = function(a, b) {
  return a + b
}

module.exports = {
  name: 'cal'
}

上面代碼中的module.exports指向了另外一個對象,致使以前的add屬性被丟失,因此最後導出只有name屬性function

# 注意:

在module.exports和exports後面的代碼依舊會執行,但不建議這樣寫

# CommonJS中的導入

使用require導入模塊時,有下面兩種狀況:

1.require的模塊是第一次被加載.這時會首先執行該模塊,而後導出內容

2.require的模塊曾被加載過.這時該模塊的代碼不會再次執行,而是直接導出上次執行後的結果

例如:

// cal.js
console.log('cal.js')
module.exports = {
  name: '我是喬峯',
  add: function(a, b) {
    return a + b
  }
}
// index.js
// 第一次require
const add = require('./cal').add
console.log(add(1, 2))


// 第二次require
const name = require('./cal').name
console.log(name)

此時的結果以下:

49.jpg

從結果上能夠看出,儘管咱們require兩次,但其內部代碼只會執行一遍.

其原理大體以下:

在模塊中,有一個module對象用來存儲信息,這個對象中有一個屬性loaded用於記錄該模塊是否被加載過.它的默認值是false,當模塊第一次被加載和執行事後會變成true

若是後面再次加載時,檢測到loaded爲true,則不會次再執行模塊代碼

# 注意:

有時咱們加載一個模塊,不須要獲取其導出的內容,只是想要經過執行它而產生某種做用,好比把它的接口掛載到全局對象上,此時直接使用require便可

require('./task.js')

# 注意:

另外,require能夠接收表達式,能夠動態加載指定的模塊

const moduleNames = ['foo.js', 'bar.js']
moduleNames.forEach(name => {
  require('./' + name)
})
相關文章
相關標籤/搜索