# JS 物件傳值?傳參考?|筆記 by Jiang ###### tags: `Jiang` `Vue新手夏令營` - [Vue 新手夏令營 課程頁面](https://hackmd.io/@dbFY0UD9SUeKmNXhWf01ew/BkJoW-hn_/%2FC05go-8iTSS-nrMwKU22kA) - [:sun_with_face:筆記入口](/2JiZbCPdR0G4p5fNycPmTg) ## JS 物件傳值?傳參考? 20210609 [影片連結 ](https://www.youtube.com/watch?v=y1odVMpi6dU)、[source code](https://codepen.io/viccjiang/pen/wvdgKRO) [重新認識 JavaScript: Day 05 JavaScript 是「傳值」或「傳址」?](https://ithelp.ithome.com.tw/articles/10191057) [五分鐘快速了解 [傳址,傳參考,傳址] ](https://dotblogs.com.tw/daniel/2018/02/26/150443) ## 內容大綱 - 物件與純值 - 物件傳參考的特性 - 陣列、函式也是傳參考嗎? - 傳參考的運用情境 - 如何避免傳參考 - 各種運用技巧 - 奇怪的題目 ```jsx console.log('真相只有一個'); var person = '小明'; var person2 = person; console.log(person, person2); // 一樣喔 var person = '小明'; var person2 = person; person2 = '杰倫'; console.log(person === person2) // 不一樣喔 console.log(person, person2); var person = { name: '小明' } var person1 = person; person1.name = '杰倫'; console.log(person === person1) console.log(person) // 杰倫 console.log(person.name); // 杰倫 var member = ['爸', '媽']; var member2 = member; member2.push('小三'); console.log(member); // 有小三 function fn(name) { return `${name}被抓到了` } var fn2 = fn; fn2.magicName = '奇怪的東西'; // 不會出錯,正確的 console.log(fn2) // 從fn拷貝過來 console.log(fn===fn2) // true console.log(fn2.magicName); //奇怪的東西 console.dir(fn2.magicName); function 函式(name) { return `${name}被抓到了` } console.log(函式('漂亮阿姨')); // 中文化可以動 var 名偵探 = console; 名偵探.柯南 = console.log; // 名偵探.柯南(函式('漂亮阿姨')) // ## let 5, const 6 // 沒有改變過指向,只有改變屬性值,建議用const const person = { name: '小明' } // person.name = '杰倫'; 名偵探.柯南(person) // 1 const, 2 let // 改變裡面的值而已,指向都沒變,可以用 const const family = ['爸', '媽', '小三']; family.forEach((item, key) => { if(item === '小三') { family.splice(key, 1) } }); console.log(family); function fn(item) { item.name = '杰倫'; } const person = { name: '小明', } fn(person); console.log(person); // 杰倫 function fn(item) { const newItem={ name : '杰倫', } // item = newItem; // item.name = newItem; Object.keys(item).forEach(key => { // 把屬性取出來 console.log(key) // key 對應到 name 屬性 item[key] = newItem [key]; // 直接覆蓋取代 }) console.log('item', item); } const person = { name: '小明', } fn(person); console.log(person); // 小明 #1 淺層複製 尚未用淺層複製 const person = { name: '小明' } const person2 =person; person2.name = '杰倫'; console.log(person2.name, person.name); console.log(person === person2); //這裡結果一樣喔 使用淺層複製 const person = { name: '小明' } const person2 = { ...person }; // 用...展開來淺層複製 person2.name = '杰倫'; console.log(person2.name, person.name); // 兩個分開了 console.log(person === person2); // 用淺層複製就不一樣了 #2 深層複製 只用淺層拷貝 var person = { name: '小明', family: { name: '小明家', members: ['爸', '媽'] } } const person2 = {...person}; person2.name = '杰倫'; person2.family.name = '杰倫家' console.log(person, person2); console.log(person.family === person2.family); // 第一層結果不一樣,但第二層就同時改變了 因為指向同一個參考位置 使用深層拷貝 var person = { name: '小明', family: { name: '小明家', members: ['爸', '媽'] } } const person2 = JSON.parse( JSON.stringify(person)); // JSON.stringify轉字串 JSON.parse再轉物件 person2.name = '杰倫'; person2.family.name = '杰倫家' console.log(person, person2); console.log(person.family === person2.family); // 兩者沒有關聯性了不相等 擴展:把原本的東西複製一份,再增加一些東西 const person = { name: '小明', fn: function() { console.log(`我叫作 ${this.name}`); } }; const person2 = { ...person, // 直接記住 person name: '杰倫', // name 直接替換掉 }; person.fn();//小明 person2.fn();//杰倫 const family = [{name: '爸'}, { name: '媽' }]; family.forEach((item, key) => { const newItem = { name: '杰倫' }; family[key] = newItem; console.log('family[key]', family[key]); console.log('item', item); }); console.log(family); // 有加上杰倫喔,蓋過去了 // 真地獄 var person = { name: '小明' } person.person = person; console.log(person.person === person.person.person); //true 無限迴圈哈哈哈 // 真真真真真地獄 面試題目 var a = { x: '小明' } var b = a; a.y = a = { x: '杰倫' }; console.log(b === a); // false console.log('a:', a ); console.log('b:', b ); // 1. a 結果 // 2. { x: '杰倫'} // 3. 其它 console.log(b.y === a); // 1一樣 ```