iT邦幫忙

0

JavaScript物件與記憶體位置

  • 分享至 

  • xImage
  •  

物件傳參考特性

  • 陣列、函式、物件、日期都屬於物件型別
  • 物件型別屬於傳參考
const person = {
    name: "小明",
};
const person2 = person;
person2.name = "漂亮阿姨";
//漂亮阿姨
console.log(person.name);

const person = {
      name: "小明",
};
function fn(obj) {
  obj.name = "漂亮阿姨";
}
fn(person);
//漂亮阿姨
console.log(person.name);

當 key 名稱存在於變數中時,可使用中括號取用:

var variable = 'go';
obj[variable]();

進階觀念

  • 物件中的屬性名稱本質上都是字串
  • 可以加上?.可選串聯,防止存取不存在的屬性時拋錯
  • 特殊字元(如 emoji)可作為 key,但需用字串形式包起來
  • 可用變數作為 key,只要加上中括號 []
const propertyName = "name";
const obj = {
  [propertyName]: "小明",
  姓名: "小華",
  1: 1,
  '❤️': "這是一個 emoji",
  inner: {
    姓名: "內層的物件"
  }
};
console.log(obj);
console.log(obj.test?.name); // undefined,不拋錯

函式也是物件

函式屬於物件型別,因此可以使用物件的方式賦值屬性

const fn = function () {};
const fn2 = fn;
fn2.age = 18;
console.dir(fn);
console.log(fn.age);

parseInt相關補充

Number.parseInt 和全域的 parseInt 指向同一個記憶體位置

//100
console.log(Number.parseInt("100元"));
//true
console.log(window.parseInt === Number.parseInt);
//true
console.log(parseInt("100元"));

將內建函數parseInt賦值給一個常數變數"轉數值"。轉數值這個變數就指向parseInt函數

const 轉數值 = parseInt;
console.log(轉數值("100元"));

將 parseInt 指向 null,不影響 Number.parseInt

parseInt = null;
console.log(Number.parseInt("100元"));

物件參考範例說明

函式內直接修改傳入物件的屬性,會影響原物件

const family = {
  name: "小明家",
  Ming: {
    name: "小明",
  },
};
const Ming = family.Ming;

function fn(obj) {
  obj.name = "漂亮阿姨";
}
fn(Ming);
//{name : '漂亮阿姨'}
console.log(Ming);

若函式內重新賦值一個新物件,則不影響原本的物件:

  1. fn(Ming) 傳入的是 Ming 的參考(指向原本那個 { name: "小明" } 的記憶體位址)
  2. 但在函數內你寫了 obj = { name: "杰倫" },這行讓 obj 改指向了一個新的物件
  3. 此時 obj 跟原本的 Ming 就沒有任何關係了
  4. 所以你後面改的是 obj 指向的新物件,對 Ming 沒有影響
const family = {
  name: "小明家",
  Ming: {
    name: "小明",
  },
};
const Ming = family.Ming;

function fn(obj) {
  obj = {
    name: "杰倫",
  };
  obj.name = "漂亮阿姨";
}
fn(Ming);
console.log(Ming);

淺層拷貝

  • 只複製第一層屬性
  • 對於物件中的基本類型(primitive)值,會直接複製值
  • 對於物件中的參考類型(object、array、function)值,只複製參考(reference)

常見方法:

  • Object.assign({}, obj)
  • 展開運算子:{ ...obj }、[ ...arr ]
const family = {
  name: "小明家",
  Ming: { name: "小明" },
};

const newFamily = { ...family };
newFamily.name = "小華";
newFamily.Ming.name = "漂亮阿姨";
console.log(newFamily);
console.log(family);

深層拷貝

  • 完整複製所有層級的資料,不共用記憶體位置
  • 佔用較多記憶體,但避免資料意外互相影響
const family = {
  name: "小明家",
  member: {
    name: "小明",
  },
};

const newFamily = JSON.parse(JSON.stringify(family));
newFamily.name = "小華家";
newFamily.member.name = "漂亮阿姨";

console.log(family);
console.log(newFamily);

函式參數重新賦值

當函式內部 obj = {...},只會改變內部參數的參考,不影響原始物件:

  • 當你在函式內 obj = { name: 1 } 時,是在「重新賦值給參數變數 obj」,這個改變只發生在 fn 函式的內部作用域,不會影響外部的 person 變數所指的記憶體位址
  • obj會另外創建另一個記憶體空間
const person = {};
function fn(obj) {
  obj = {
    name: 1,
  };
}
fn(person);
console.log(person);

補充:物件搭配陣列方法

物件可透過 Object.keys 和 Object.values 使用陣列方法:

const family = {
  Ming: { name: '小明' },
  Jay: { name: '杰倫' },
  Auntie: { name: '漂亮阿姨' }
};

console.log(Object.keys(family)); // ['Ming', 'Jay', 'Auntie']
console.log(Object.values(family)); // [ {...}, {...}, {...} ]

Object.values(family).forEach(item => {
  console.log(item);
});

Object.keys(family).forEach(key => {
  console.log(key);
  console.log(family[key]);
});


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言