# Eloquent JavaScript 3rd edition (2018) 第四章~Data Structures: Objects and Arrays --- tags: Javascript relate --- ###### tags: `Javascript` > On two occasions I have been asked, ‘Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?’ [...] I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question. > > Charles Babbage, Passages from the Life of a Philosopher (1864) ## The weresquirrel 講述一個人有變成松鼠造成他困擾的故事,因此他做了很多個紀錄看看哪些因素導致她變成松鼠,由這個點開啟這個章節的連結。 ## Data sets ### array 用來儲存一系列的值,一個值的清單寫在[]這個之間並且使用(,)來區別每個值。 array要取得裡面的值的時候也必須使用[],然後要知道裡面的順序是從0開始,所以當使用 `console.log(listOfNumbers[2]);`的時候是在找array裡面的第三個數字。 ```javascript= let listOfNumbers = [2, 3, 5, 7, 11]; console.log(listOfNumbers[2]); // → 5 console.log(listOfNumbers[0]); // → 2 console.log(listOfNumbers[2 - 1]); // → 3 ``` ## Properties String.length 取的字串長度 Max.max 取最大值 這兩個都是expression 取得一些值的屬性。像是我們藉由length這個property來取的myString的value也就是它的長度。 幾乎所有的Js的value都有他的屬性。例外是null and undefined,如果你試著去取的的話會得到error。 ``` javascript= null.length; // → TypeError: null has no properties ``` 然而要訪問property有兩種方式: 第一種就是使用(.) `value.x` 第二種是使用`[]` `value[x]` 這兩種方式都可以訪問property但不一定會是一樣的property主要影響的關鍵是其中變數。 * 當使用(.)得時候後方的文字是propery的名子 * 當使用[]的時候在之中的expression被"評估"去取得property 然而當value.x 取得叫做x的value的property的時候 value[x]正在評估那個expression x以及運用它的結果並轉換成字串也就是那個property的名字。 以下以兩個例子可以說明: * 如果你對color 這個Property有興趣你可以使用 value.color * 如果你想要擷取property的名字從 binding i 裡面的話你可以使用 value[i] **在array裡面的元素都被儲存成array的property,並且使用numbers當作property name** ## Methods > Properties that contain functions are generally called methods 如果propety包含了functions通常你可以叫它們methods 以下程式碼包含了一些範例methods: push 加上一個值在array的最後面 pop 減去一個值在array的最後面 ```javascript= let sequence = [1, 2, 3]; sequence.push(4); sequence.push(5); console.log(sequence); // → [1, 2, 3, 4, 5] console.log(sequence.pop()); // → 5 console.log(sequence); // → [1, 2, 3, 4] ``` ## Objects > Values of the type object are arbitrary collections of properties. objects 是一種value任意的集合 ```javascript= let day1 = { squirrel: false, events: ["work", "touched tree", "pizza", "running"] }; console.log(day1.squirrel); // → false console.log(day1.wolf); // → undefined day1.wolf = false; console.log(day1.wolf); // → false ``` 在property裡面如果不是有效的字串或是數字的話都必須加上("") ```javascript= let descriptions = { work: "Went to work", "touched tree": "Touched a tree" }; ``` 如果內容的propety不存在的話會顯示undefine ### delete operator 可以做到刪除property的名字 ```javascript= let anObject = {left: 1, right: 2}; console.log(anObject.left); // → 1 delete anObject.left; console.log(anObject.left); // → undefined console.log("left" in anObject); // → false console.log("right" in anObject); // → true ``` ### in operator 當 `in` operator作用在字串或是objects時,可以告訴你是否這個object有名字 ### object.keys 為了得知object的property是什麼可以使用這個function 你給這個function一個object他會return一個array一串也就是property的名字給你 ```javascript= console.log(Object.keys({x: 0, y: 0, z: 2})); // → ["x", "y", "z"] ``` ### Object.assign 可以把別的object的property copy進去 ```javascript= let objectA = {a: 1, b: 2}; Object.assign(objectA, {b: 3, c: 4}); console.log(objectA); // → {a: 1, b: 3, c: 4} ``` 說道這邊可以說出來array就是個object被特化用來儲存一連串的東西。 ## Mutability * string value是沒有辦法改變其內容的 * object value可以被改變 property的內容在不同的時間點 從下方可以得知:O1跟O2的identity相等所以改變時兩個會一起動,然而O3則是雖然一開始的property是一樣的可是他們卻是不一樣的 ```javascript= let object1 = {value: 10}; let object2 = object1; let object3 = {value: 10}; console.log(object1 == object2); // → true console.log(object1 == object3); // → false object1.value = 15; console.log(object2.value); // → 15 console.log(object3.value); // → 10 ``` 就算是const被使用了,object的contents還是可以被改變 ```javascript= const score = {visitors: 0, home: 0}; // This is okay score.visitors = 1; // This isn't allowed score = {visitors: 1, home: 1}; ``` ## The lycanthrope’s log 解釋了一些關於 correlation,1跟-1代表的意思1代表完全相同,-1代表完全相反,0的話代表不相關 ## Computing correlation 這段看不懂但她解釋了 ![](https://i.imgur.com/rQvNELv.png) ![](https://i.imgur.com/p3VLRCT.png) ```javascript= function phi(table) { return (table[3] * table[0] - table[2] * table[1]) / Math.sqrt((table[2] + table[3]) * (table[0] + table[1]) * (table[1] + table[3]) * (table[0] + table[2])); } console.log(phi([76, 9, 4, 1])); // → 0.068599434 ``` ```javascript= function tableFor(event, journal) { let table = [0, 0, 0, 0]; for (let i = 0; i < journal.length; i++) { let entry = journal[i], index = 0; if (entry.events.includes(event)) index += 1; if (entry.squirrel) index += 2; table[index] += 1; } return table; } console.log(tableFor("pizza", JOURNAL)); // → [76, 9, 4, 1] ``` ## Array loops ```javascript= for (let i = 0; i < JOURNAL.length; i++) { let entry = JOURNAL[i]; // Do something with entry } ``` ## The final analysis 基本上接續上面也是看不懂 不過檢驗資料的結果是他吃堅果跟他不刷牙導致她變成松鼠。所以她只要不吃堅果就好瞜!~ ## Further arrayology `unshift` and `shift` 在array前方增加或是減少東西 ```javascript= let todoList = []; function remember(task) { todoList.push(task); } function getTask() { return todoList.shift(); } function rememberUrgently(task) { todoList.unshift(task); } ``` `remember` 在後方加入新的task `getTask` 當你準備好要做事情的時候 `rememberUrgently` 在前方加入新的task `indexOf` 從頭開始尋找特定的value `lastIndexOf` 從尾開始尋找特定的value 上面兩個methods都可以設定第二個argument當作從哪邊開始搜尋的點 ```javascript= console.log([1, 2, 3, 2, 1].indexOf(2)); // → 1 console.log([1, 2, 3, 2, 1].lastIndexOf(2)); // → 3 ``` `slice` 會取得argument中間的數字包含左邊的數字右邊不包含 並且當右邊的argument沒有給的時候會取得後方全部的值,也可以不填寫argument他就會全部array都copy下來 ```javascript= console.log([0, 1, 2, 3, 4].slice(2, 4)); // → [2, 3] console.log([0, 1, 2, 3, 4].slice(2)); // → [2, 3, 4] ``` `concat` 可以把兩個array黏在一起創造新的array就像 "+"這個operator一樣 `remove` 可以移除指定位置的value ```javascript= console.log(remove(["a", "b", "c", "d", "e"], 2)); // → ["a", "b", "d", "e"] ``` ## Strings and their properties string number boolean 的value型態都不是objects 所以他們不能這樣使用: ```javascript= let kim = "Kim"; kim.age = 88; console.log(kim.age); // → undefined ``` 但他們已經有數個好用的methods了: ```javascript= console.log("coconuts".slice(4, 7)); // → nut console.log("coconut".indexOf("u")); // → 5 ``` `trim` 可以消除(spaces, newlines, tabs, and similar characters) ```javascript= console.log(" okay \n ".trim()); // → okay ``` `padStart` 前方argument代表幾位數後面的代表要加入甚麼數字 ```javascript= console.log(String(6).padStart(3, "0")); // → 006 ``` `split` `join` 分開句子跟加入東西進去句子 ```javascript= let sentence = "Secretarybirds specialize in stomping"; let words = sentence.split(" "); console.log(words); // → ["Secretarybirds", "specialize", "in", "stomping"] console.log(words.join(". ")); // → Secretarybirds. specialize. in. stomping ``` `repeat` 重複文字內容 ```javascript= console.log("LA".repeat(3)); // → LALALA ``` `length` 探測內文文字長度以及尋找內文定位文字 ```javascript= let string = "abc"; console.log(string.length); // → 3 console.log(string[1]); // → b ``` ## Rest parameters (...)的用法,可以把一個array引用進去 ```javascript= let numbers = [5, 1, 7]; console.log(max(...numbers)); // → 7 ``` ## The Math object 介紹一些math的methods ## Destructuring 如果試著解構dull跟undefined會的到error ## JSON objects and array都是儲存在電腦的記憶體內,因此它們都有address,如果你想要把他們傳輸給其他電腦做使用,這個時候就需要把它們做序列化serialize 資料,也就是JSON。是一種廣泛運用在網頁資料儲存以及溝通的格式。(其他語言也有在使用) 有一些嚴格的規定存在: 所有property都必須被""包含,並且只能使用簡單的expression並且不能使用functions bindings 或是任何計算甚至註解也不行使用。 ```javascript= { "squirrel": false, "events": ["work", "touched tree", "pizza", "running"] } ``` `JSON.stringify` 回應使用JSON編碼過後的內容回來 `JSON.parse` 擷取出被編譯前的內容出來 ```javascript= let string = JSON.stringify({squirrel: false, events: ["weekend"]}); console.log(string); // → {"squirrel":false,"events":["weekend"]} console.log(JSON.parse(string).events); // → ["weekend"] ``` ## Summary object 跟 array就像是我們使用一個袋子把東西裝進去並且開始轉動拋,而不是我們直接雙手一開去抓那些東西。 大部分的value都有property,除了null and undefined array使用numbers當作他property的名字(從0開始) 也有一些像是length這樣property作用在array裡面,他們會作用在property的值上面 也可以使array重複,使用`for (let element of array)` ## Exercises ### The sum of a range ### Reversing an array ### A list ### Deep comparison