2016-06-27

JS: 如何刪除 object 中的第一個屬性?

如何刪除 javascript object 中的第一個屬性?

結論:

var obj = { "first": "object", "2th": "delete", "3th": "property", "4th": "like", "last": "array"};
delete obj[Object.keys(obj)[0]];
console.log(obj);
//  { '2th': 'delete',
//    '3th': 'property',
//    '4th': 'like',
//   'last': 'array' }

廢話:

沒遇到前, 也想不到居然有需要做這件事的一天.
因為 js 的 object 類似雜湊, 以 鍵-值 對的形式來儲存. 實作上是不保證順序的. 也就是說, object 與有一定的次序的 array 不同. 當使用 each之類的方法讀取內容時, 不保證會得到相同順序的結果. 理論上, 當 object 每次放入新的屬性, object 內的屬性的順序就有可能變動. 在這樣的原則下, 有甚麼必要去特定刪除所謂的"第一個"屬性?
不過理論就只是理論.
因為要利用 object 存儲一些執行結果作為 cache . 寫完才想到程式持續的執行下去, object 中存放的 key-value 越多, 那程式早晚會掛點. 所以得要清除舊的資料才行, 但我怎麼知道哪些是舊資料哪些是新資料? 要知道資料存放的先後順序, 必須要將資料存放的時間也記錄下來. 但要加上這個資訊, 程式必須改寫. 所以, 我想到不如就刪掉最早加入的一筆資料就好了. 反正是最早加入的, 只要 cache 中保留的筆數夠多, 被使用到的機會就小到可以忽略. 如此, 程式只要加入這個程序就能修正資料會不斷成長到用光資源的問題. 真好 :)
但, "誰"是第一個加入的?

正文:

首先, 研究一下 javascript object 放屬性的順序.
var obj_txt_1 = { 
    "first": "object", 
    "2th": "delete", 
    "3th": "property", 
    "4th": "like", 
    "last": "array"
};
var obj_txt_2 = { 
    "2th": "delete", 
    "first": "object", 
    "4th": "like", 
    "last": "array",
    "3th": "property" 
};
console.log(obj_txt_1);
//{ first: 'object',
//  '2th': 'delete',
//  '3th': 'property',
//  '4th': 'like',
//  last: 'array' }
console.log(obj_txt_2);
//{ '2th': 'delete',
//  first: 'object',
//  '4th': 'like',
//  last: 'array',
//  '3th': 'property' }
看來, 好像跟一開始放入的順序一致. 那逐一加入的話, 會一樣?
var obj_txt_1 = { };
    obj_txt_1["first"]= "object"; 
    obj_txt_1["2th"]  = "delete"; 
    obj_txt_1["3th"]  = "property"; 
    obj_txt_1["4th"]  = "like";
    obj_txt_1["last"] = "array";

var obj_txt_2 = { };
    obj_txt_2["2th"]  = "delete"; 
    obj_txt_2["first"]= "object"; 
    obj_txt_2["4th"]  = "like";
    obj_txt_2["last"] = "array";
    obj_txt_2["3th"]  = "property"; 

console.log(obj_txt_1);
//{ first: 'object',
//  '2th': 'delete',
//  '3th': 'property',
//  '4th': 'like',
//  last: 'array' }
console.log(obj_txt_2);
//{ '2th': 'delete',
//  first: 'object',
//  '4th': 'like',
//  last: 'array',
//  '3th': 'property' }
結果一樣. 看起來就是依放入的順序.
不能放心, 再試試其他例子.
var obj_num_1 = { 
    "1": "object", 
    "2": "delete", 
    "3": "property", 
    "4": "like", 
    "5": "array"};
console.log(obj_num_1);  
//{ '1': 'object',
//  '2': 'delete',
//  '3': 'property',
//  '4': 'like',
//  '5': 'array' }
var obj_num_2 = { 
    "2": "delete", 
    "1": "object", 
    "4": "like", 
    "5": "array",
    "3": "property"}; 
console.log(obj_num_2);      
//{ '1': 'object',
//  '2': 'delete',
//  '3': 'property',
//  '4': 'like',
//  '5': 'array' }
怎麼依數字排序了, 明明給的是文字.
再試試, 文數字混合的 key 會如何?
var obj_mix_1 = { 
    "first": "object", 
    "2": "delete", 
    "3": "property", 
    "4": "like", 
    "last": "array"
};
console.log(obj_mix_1); 
//{ '2': 'delete',
//  '3': 'property',
//  '4': 'like',
//  first: 'object',
//  last: 'array' }
var obj_mix_2 = { 
    "last": "array",
    "first": "object", 
    4: "like", 
    2: "delete",         
    3: "property",     
};  
console.log(obj_mix_2);   
//{ '2': 'delete',
//  '3': 'property',
//  '4': 'like',
//  last: 'array',
//  first: 'object' }
看來, 不管是"文字"還是"數字"型別, 只要是長得像數字的 key, 就會依數字排序, 其他就是依放入順序.
但除了正整數外, 也會排序?
var obj_num_3 = { 
    "2.3": "array",
    "2.1": "object", 
    1.4: "like", 
    1.2: "delete",         
    1.3: "property",     
};  
console.log(obj_num_3);
//{ '2.3': 'array',
//  '2.1': 'object',
//  '1.4': 'like',
//  '1.2': 'delete',
//  '1.3': 'property' }
// 浮點數不排序
var obj_num_4 = { 
    "-4": "array",
    "-0": "object", 
    "-2": "like", 
    "-3": "delete",         
    "-1": "property",     
};  
console.log(obj_num_4);
//{ '-4': 'array',
//  '-0': 'object',
//  '-2': 'like',
//  '-3': 'delete',
//  '-1': 'property' }
// 負數不排序
var obj_num_5 = { 
    "-4": "array",
    "0": "object", 
    "-2": "like", 
    "-3": "delete",         
    "-1": "property",     
}; 
//{ '0': 'object',
//  '-4': 'array',
//  '-2': 'like',
//  '-3': 'delete',
//  '-1': 'property' }
// 數字"零"會排序
也就是用在陣列索引的 0 與正整數, 會排序, 其他依放入順序.
雖然, 上面可能依不同的 JS engine 實作會得到不同的結果. 但目前就先假設是如此來處理. 且, 因為我的程式不會使用非負整數(含零的自然數)當索引. 所以, 只需要考慮哪個 key 是第一個被放入的即可.
// 首先, 先將借用 Object 的 `keys` 方法, 將 object 的所有 key取出.
// 這個方法傳回的會是一個 array. 
var obj = { "first": "object", "2th": "delete", "3th": "property", "4th": "like", "last": "array"};
var ary = Object.keys(obj);
console.log(ary);
// [ 'first', '2th', '3th', '4th', 'last' ]

//而 JS array 的第一個元素, 可以使用`[0]`來的取值.
var key = ary[0];
console.log(key);
// 'first'

// 而 JS object 可以使用 key 來取得屬性值, 並用 `delete` 來刪除 object 中的屬性.
console.log(obj[key]);

// 'object'

delete obj[key];
console.log(obj);
//{ '2th': 'delete',
//  '3th': 'property',
//  '4th': 'like',
//  last: 'array' }

//簡單合併一下, 上面的做法.
var obj = { "first": "object", "2th": "delete", "3th": "property", "4th": "like", "last": "array"};
console.log(obj);
//{ first: 'object',
//  '2th': 'delete',
//  '3th': 'property',
//  '4th': 'like',
//  last: 'array' }

// 刪掉第一個元素
delete obj[Object.keys(obj)[0]];
// true
console.log(obj);
//{ '2th': 'delete',
//  '3th': 'property',
//  '4th': 'like',
//  last: 'array' }

沒有留言:

張貼留言