js匯入匯出總結與實踐

陌上寒發表於2019-03-31

在上一篇文章中JavaScript中AMD和ES6模組的匯入匯出對比,偏向於理論層面,還有一些同學在微信群裡或是私下裡針對一些問題進行了溝通,所以有了這一篇文章,對js的匯入匯出進行總結和實踐

當直接給 module.exports時,exports會失效

這個問題其實已經和匯入匯出沒什麼關係了, 我們看一個知乎上的問題(詳細地址閱讀原文可以檢視) 我們以此為突破點 js 陣列賦值問題 :值傳遞還是引用?

var a = [1,2,3];
var b = a;
a = [4,5,6];
console.log(b);  //=>[1,2,3]
複製程式碼

繼續看

var a = [1,2,3];
var b = a;
a.pop();
console.log(b);  //=>[1,2]
複製程式碼

為什麼會出現這種情況?

陣列和物件的賦值操作都是引用傳遞

看下這個(留意註釋部分)

var a = [1,2,3];// a指向了陣列 [1,2,3];
var b = a;//b 指向 a 所指向的陣列[1,2,3];
a = [4,5,6];//a 指向了新的陣列 [4,5,6],(a的指向發生了變化,改變的是a引用本身,沒有改變陣列物件,所以b沒有變)
console.log(b);  //b沒有改變,還是指向陣列 [1,2,3];
複製程式碼

再看下這個(留意註釋部分)

var a = [1,2,3];// a指向了陣列 [1,2,3];
var b = a;//b 指向 a 所指向的陣列[1,2,3];
a.pop();// a 指向的陣列例項發生了 pop 操作
console.log(b);  //=>a和b都是指向同一個陣列,a變數,所以b也變數,最後輸出=>[1,2]
複製程式碼

看一張圖片,很形象的描述

js匯入匯出總結與實踐
陣列如此,物件也是大同小異 看一個群友@ZSing提供的demo

var test = {
  "name": "zhangshuo"
}
var demo = test;

demo.name = "want you"
//你認為test是什麼?
console.log(test)//=>{ name: 'want you' }
複製程式碼

下面通過註釋解釋一下(如出一轍)

var test = {  "name": "zhangshuo"}//test指向了一個物件 {  "name": "zhangshuo"}
var demo = test;//demo 指向 test 所指向的物件 {  "name": "zhangshuo"}
demo.name = "want you"//物件的屬性發生了改變 {  "name": "want you"}
//你認為test是什麼?
console.log(test)//=>{ name: 'want you' }
複製程式碼

test和demo指向了同一個物件,一個變了,就都變了 同樣的,我們對上面的demo做一下改造

var test = {
  "name": "zhangshuo"
}
var demo = test;
  test={
    "name": "更改了這個name"
  }
demo.name = "want you"
//你認為test是什麼?
console.log(test)//=>{ name: '更改了這個name' }
複製程式碼

還需要對此進行贅述嗎? 還是通過註釋對此進行解釋說明

var test = {  "name": "zhangshuo"}//test指向了一個物件 {  "name": "zhangshuo"}
var demo = test;//demo 指向 test 所指向的物件 {  "name": "zhangshuo"}
  test={ "name": "更改了這個name" }//test的指向發生了變化,指向了一個新物件{ "name": "更改了這個name" }
demo.name = "want you"//demo的指向沒有變,改變了原物件的屬性 {  "name": "want you"}
//你認為test是什麼?
console.log(test)//=>{ name: '更改了這個name' }
複製程式碼

我相信,上面的兩個栗子你已經看懂了,即將進入正題 先來一個過渡 再看一個栗子,用來模擬exports和 module.exports的關聯關係

  let md = {exps:{}}//md指向一個物件 {exps:{}}
  let exps = md.exps//exps指向了md.exps所指向的物件 ,這個空物件{}
  md.exps = {a: 1,  b: 2}//md.exps指向了一個新物件 {a: 1,  b: 2}
  exps.c=3//exps,屬性賦值 {c: 3}
  console.log(md.exps); //新物件{ a: 1, b: 2 }
複製程式碼

上面栗子中的md就是module,md.exps就是module.exports,exps就是exports 在每一個模組的頭部都有一行這樣的命令

var exports = module.exports;
複製程式碼

當直接給module.exports賦值時(module.exports={.....}),module.exports就指向了一個新物件,exports會失效

直接給exports賦值會切斷exports和 module.exports的關聯關係

還是這樣的一個前提

var exports = module.exports;
複製程式碼

exports是來自於module,exports指向 module.exports所指向的物件 當直接給exports賦值,即

 exports = {a:1}
複製程式碼

exports指向了一個新物件,不再是 module.exports所指向的物件,所以不要給 exports 直接賦值( exports =。。。)

實踐=>匯出

exports

exports的output.js

exports.str='string字串'//匯出字串
exports.bool=true//匯出布林
exports.num=123//匯出number
exports.foo=(r)=>{//匯出函式
  console.log(`匯出函式為:${r}`);
}
exports.arr=[1,2,3]//匯出陣列
exports.obj={ a:1, b:2}//匯出物件
複製程式碼

input.js

  const iptObj= require('./output.js')
  console.log(iptObj.str);//=>string字串
  console.log(iptObj.bool);//=>true
  console.log(iptObj.num);//=>123
  console.log(iptObj.arr);//=>[ 1, 2, 3 ]
  console.log(iptObj.obj);//=>{ a: 1, b: 2 }
  iptObj.foo('引數')//=>匯出函式為:引數
複製程式碼

module.exports

module.exports的output.js

module.exports={
  str:'string字串',
  bool:true,
  num:123,
  foo:(r)=>{
    console.log(`匯出函式為:${r}`);
  },
  arr:[1,2,3],
  obj:{ a:1, b:2}
}
複製程式碼

input.js

  const iptObj= require('./output.js')
  console.log(iptObj.str);//=>string字串
  console.log(iptObj.bool);//=>true
  console.log(iptObj.num);//=>123
  console.log(iptObj.arr);//=>[ 1, 2, 3 ]
  console.log(iptObj.obj);//=>{ a: 1, b: 2 }
  iptObj.foo('引數')//=>匯出函式為:引數
複製程式碼

module.exports的output.js同時支援如下寫法

module.exports.str='string字串'
module.exports.bool=true
module.exports.num=123
module.exports.foo=(r)=>{
  console.log(`匯出函式為:${r}`);
}
module.exports.arr=[1,2,3]
module.exports.obj={ a:1, b:2}
複製程式碼

input.js不變

export

export的output.js

export const srt = 'string字串'
export const bool = true
export const num = 123
export const arr = [1, 2, 3]
export const obj = { a: 1, b: 2}
export function foo(r) {
  console.log(`匯出函式為:${r}`);
}
複製程式碼

input.js

import {str,arr,obj,bool,num,foo} from './output'
console.log(str)
console.log(arr)
console.log(obj)
console.log(bool)
console.log(num)
foo('引數')
複製程式碼

export的output.js同時支援如下寫法

const str = 'string字串' 
const bool = true
const num = 123
const arr = [1, 2, 3]
const obj = { a: 1, b: 2}
function foo(r) {
  console.log(`匯出函式為:${r}`);
}
export {
  str,bool,num,arr,obj,foo
}
複製程式碼

input.js 匯入支援重新命名

import {str as STR,arr,obj,bool,num,foo as FOO} from './output'
console.log(STR)
console.log(arr)
console.log(obj)
console.log(bool)
console.log(num)
FOO('引數')
複製程式碼

繼續重新命名

import * as newName from './output'
console.log(newName.str)
console.log(newName.arr)
console.log(newName.obj)
console.log(newName.bool)
console.log(newName.num)
newName.foo('引數')
複製程式碼

export default

export default的output.js

export default {
  str: 'string字串',
  bool: true,
  num: 123,
  foo: (r) => {
    console.log(`匯出函式為:${r}`);
  },
  arr: [1, 2, 3],
  obj: { a: 1, b: 2 }
}
複製程式碼

input.js

import defaultObj from './output'
console.log(defaultObj.str)
console.log(defaultObj.arr)
console.log(defaultObj.bool)
console.log(defaultObj.num)
console.log(defaultObj.obj)
defaultObj.foo('ef')//=>匯出函式為:ef
複製程式碼

export default的output.js同時支援如下寫法

const str = 'string字串'
const bool = true
const num = 123
const arr = [1, 2, 3]
const obj = {a: 1, b: 2}
function foo(r) {
  console.log(`匯出函式為:${r}`);
}
export default {
  str,
  bool,
  num,
  arr,
  obj,
  foo
}
複製程式碼

input.js不變

總結

這篇文章是對上一篇文章的總結和實踐

  • 當直接給 module.exports時,exports會失效
  • 直接給exports賦值會切斷exports和 module.exports的關聯關係
  • export,export default,exports,module.exports具體的使用方法例項

更多前端資源請關注微信公眾號“前端陌上寒”

原文連結

參考連結

js 陣列賦值問題 :值傳遞還是引用?

相關文章