iT邦幫忙

2022 iThome 鐵人賽

DAY 9
0
Modern Web

前端蛇行撞牆記系列 第 9

Day9 前端蛇行撞牆記 - 淺入了解array-like

  • 分享至 

  • xImage
  •  

前言

array-like看起來像是個自由自在的男子,想幹嘛就幹嘛,遊戲人間,笑看眾生,從來不必擔心被認出,還可以使用一些方法。可是僅此於此,他做不到其他array的method,因為他終究不是array..

以上是我對array-like的第一個印象,但是他還有很多需要被發掘的!

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"!

  • 所以array-like 是可以使用部分array的methods,但看起來完全不是array!

再來看看我第一次遇到的 arguments,其實我覺得他滿酷的,但也從來沒有用過,有人建議不要使用他,因為他有一些太怪的地方了。

arguments

  • 使用 arguments可以讓function參數變得更自由:
    根本不用寫參數,一旦有值傳進去就會自動變成 arguments
function add() {
  return arguments[0] + arguments[1];
}

console.log(add(1, 2));
// 3

來看看他到底是什麼?

console.log(typeof arguments);
// object

是object!

  • 但我們可以用解構的方式把他變成真正的array,就可以使用forEach了~
function add() {
  const a = [...arguments];
  console.log(a)
    
  a.forEach((item) => console.log(item));
}

console.log(add(1, 5));
// [ 1, 5 ]
// 1
// 5
  • 試試看去更改arguments的長度。
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長度。

  • 來看看正牌array,只要去動到他的length,整個array就會被改變。
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真的很壞!

String

回到最一開始的字串,字串所能使用的 methods比 arguments多更多。

  • 先從最基本的,字串同樣可以使用 length、index
const str = "Hello";

console.log(str.length); // 5
console.log(str[0]); // H
  • 一樣也不會因為length變短而改變內容,別忘記他是prmitvie,是immutable。
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
  • 非常故意的我用不是數字的話,將會返回第0個值

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翻轉,再換回字串。

  • 字串換成陣列1: 使用Array.from()
const str = "foo";
const array = Array.from(str);
array.reverse(); // 直接改變原始陣列

const str2 = array.join(""); // 要用變數去接
console.log(str2);
// oof

記得reverse()是會改變原陣列

  • 字串換成陣列2: 使用split("")
const str = "foo";
const str1 = str.split("").reverse().join("");

console.log(str1);
// oof
  • 字串換成陣列3: 使用展開運算子
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


上一篇
Day8 前端蛇行撞牆記 - 不用宣告一個空陣列也可以創建陣列的方法
下一篇
Day10 前端蛇行撞牆記 - array-like 可以用陣列方法嗎?
系列文
前端蛇行撞牆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言