array-like看起來像是個自由自在的男子,想幹嘛就幹嘛,遊戲人間,笑看眾生,從來不必擔心被認出,還可以使用一些方法。可是僅此於此,他做不到其他array的method,因為他終究不是array..
以上是我對array-like的第一個印象,但是他還有很多需要被發掘的!
什麼是 array-like? 直接的感覺是「像陣列」所以就是「不是陣列」嘛!
第一次看到這個名詞的時候是讀到 arguments的時候,那個時候只知道他可以用length,可以用index,這樣而已。
後來在閱讀《你所不知道的JS》裡面有講到:
「很普遍的看法是『string基本上只是字元(characters)所組成的array』而已,但還是要知道『JavaScript的string實際上並不等同於字元所組成的陣列』這一點還是很重要的。他們的相似僅止於表面」
疑?所以字串也是array-like嗎?好像是耶!
於是就想來研究一下array-like到底怎樣like,怎麼區分?
先來看個經典的例子:
const obj = {
0: "It",
1: "is",
2: "nice",
length: 3
}
來看看這個 obj的 key偽裝成 index值,又自訂擁有了 length的 method,使他們可以被存取,這個就是 array-like "object"!
再來看看我第一次遇到的 arguments,其實我覺得他滿酷的,但也從來沒有用過,有人建議不要使用他,因為他有一些太怪的地方了。
function add() {
return arguments[0] + arguments[1];
}
console.log(add(1, 2));
// 3
來看看他到底是什麼?
console.log(typeof arguments);
// object
是object!
function add() {
const a = [...arguments];
console.log(a)
a.forEach((item) => console.log(item));
}
console.log(add(1, 5));
// [ 1, 5 ]
// 1
// 5
function foo(a, b) {
console.log(arguments);
// [Arguments] { '0': 1, '1': 2 }
// 原本長度
console.log(arguments.length); //2
// 更改程度
arguments.length = 3;
// 現在長度
console.log(arguments.length); //3
return arguments;
}
console.log(foo(1, 2));
// 完全沒被影響
// [Arguments] { '0': 1, '1': 2 }
原本的長度是 2,改變 arguments的長度變成3,再印出長度的確有改變,可是內容不會改變,沒有減少。
array-like 沒辦法用length去改變內容,只能呈現目前的length長度。
const array = [1, 2, 3];
array.length = 1;
console.log(array);
// [1]
還有要注意,arguments是可以被改變的!如果在 function裡面重新賦值整個 arguments的話,原本外面傳進去的值也沒有用了。
function foo(a, b) {
var arguments = 40;
return arguments;
}
console.log(foo(1, 2));
// 直接不管那個1,2
// 40
arguments真的很壞!
回到最一開始的字串,字串所能使用的 methods比 arguments多更多。
const str = "Hello";
console.log(str.length); // 5
console.log(str[0]); // H
const str = "Hello";
str.length = 1;
console.log(str); //"Hello"
這裡要提一下,其實字串本身有一個methods叫做String.prototype.charAt()
,也同樣像是index一樣,可以找到第0個值是什麼。
const str = "Hello";
const index = str.charAt(1);
console.log(index); // e
MDN: If the index cannot be converted to the integer or no index is provided, the default is 0, so the first character of str is returned.
const str = "Hello";
const index = str.charAt("嗨");
console.log(index); //H
const str = "Hello";
const index = str.charAt(10);
console.log(index);
//
好了好了好了!怎麼突然在介紹,完全試到欲罷不能,第一次用哪!
還有字串不只可以用 length還可以用Array.prototype.concat()
啊,真是太神奇了,看來是array轉型成字串,然後才可以相加。
const str = "Hello";
const array = [1, 2, 3];
const newStr1 = str.concat(array);
console.log(newStr1);
// Hello1,2,3
但是字串的型別不就是 string嗎? array-like明明就都是 object!
好拉我想你應該知道了,因為有 「包裹器(wrapper)」 啊。
為什麼 String有一堆 methods,是因為他在當下會變成一個 object,才能使用 object的 method,可是一但使用完畢他就會立刻解包裝,又變回基本型別 String了!
今天就這樣好像太虛了,加碼字串翻轉~~
也就是說先把字串換成陣列,然後再用array methods翻轉,再換回字串。
const str = "foo";
const array = Array.from(str);
array.reverse(); // 直接改變原始陣列
const str2 = array.join(""); // 要用變數去接
console.log(str2);
// oof
記得reverse()是會改變原陣列
const str = "foo";
const str1 = str.split("").reverse().join("");
console.log(str1);
// oof
const str = "foo";
const str2 = [...str]; // ["f","o","o"]
const str3 = str2.reverse().join("");
console.log(str3);
// oof
不管用什麼方法都要再轉回字串,好像也沒有哪一個特別快?
明天還會繼續介紹 array-like 是不是真的不能使用所有的 array methods 呢? 相信會一定會顛覆大家的印象的哈哈哈
明天見囉!
參考資料:In JavaScript are strings arrays-like objects?
Why do you need to know about Array-like Objects?
你所不知道的JS- 導讀,型別與文法
MDN