js remind

閉包 - 回傳 function 要小心,以下 x 會累積

function aFunc(x){
  // 這裡的 x 被保留,值為 1
  function bFunc(){
    console.log( x++ )
  }
  return bFunc
}

const newFunc = aFunc(1)
newFunc() // 1
newFunc() // 2, 預期會得到 1,但因為閉包,x 保留了變成累加


所以 bFunc 在執行時,內部用到環境變數(x在aFunc內)被保留了,傳入的 x 會累加
執行時像這樣

var count = 0
function add(){
  return count = count + 1
}
add() // 1,count 環境變數指了同一個,所以就會累加
add() // 2

解法:
閉包是一種保護措施,不讓外部叫用內部變數,可以當成 private var 來看


傳值與傳參考

var user1 = { name: 'leo' }
var user2 = user1
user2.name = 'frank'
user1.name // frank

本來想要改 user2 的名字,但因為 user2 只是 user1 的參考(別名),所以 user1 被改成 frank,所以要改成

解法 A:
var user1 = { name: 'leo' }
var user2 = Object.assign({}, user1) // 複製 user1 物件給 user2
user2.name = 'frank'
user1.name // leo

解法 B:
var user1 = { name: 'leo' }
var user2 = JSON.parse(JSON.stringify(user1))
user2.name = 'frank'
user1.name // leo

解法 B 可以處理多層,以下是巢狀結構,Object.assign 會失敗,

var user1 = { name: 'leo', info: { height: 170, weight: 78 } }
var user2 = Object.assign({}, user1)

user2.name = 'frank'
user2.info.height = 168
user2.info.weight = 65

user1.name // leo ,正確
user1.info.height // 168,錯誤,被影響
user1.info.weight // 65,錯誤,被影響

所以最安全是使用 JSON 轉換,不然就是要避免巢狀



留言