Eloquent JavaScript #04# Objects and Arrays

 要點索引:javascript

一、補:js字符串的表達方式有三種: "" 和 '' 沒什麼區別,惟一區別在於 "" 中寫 "要轉義字符,在 '' 中寫 ' 要轉義字符。最後一種是 `` ,容許 'xx = ${算式}' 的簡寫方式。html

 

二、兩種主要的訪問對象屬性的方式 —— 點號與 [ ]java

[ ] 會獲取 [ ] 中的計算後字符串,點號則不會。node

必須用 [ ] 的場景是訪問數組屬性 x[1], 由於點號後不能跟數字。python

 

三、js數組自帶push和pop方法。c++

隊列也能夠很容易實現:數組

let todoList = [];
function remember(task) {
  todoList.push(task);
}
function getTask() {
  return todoList.shift();
}
// 緊急事件插入到隊列前面
function rememberUrgently(task) {
  todoList.unshift(task);
}

 

四、對象的屬性中,非有效引用名(例如包含空格↓)必須用字符串形式表達:網絡

let descriptions = {
  work: "Went to work",
  "touched tree": "Touched a tree"
};

且必需要用 [ ] 訪問該屬性:ide

descriptions["touched tree"]

 

五、js對象容許動態添加屬性:post

descriptions["another property"] = "new one";

若是已經存在就替換。點號也是能夠的,但 [ ] 比較通用。

 

六、動態刪除屬性:

/*
 * 能夠把對象想象成一隻章魚,對象的屬性想象成帶着便籤
 * 的章魚觸手,數組也是一種對象,typeof [];的結果是object
 * 因此數組是一種觸手上的便籤全爲順序數字的章魚。
 */
let octopuse = {
    tentacleA: 1,
    tentacleB: 2,
    tentacleC: 3
};

console.log(octopuse.tentacleA);
// → 1
delete octopuse.tentacleA;
console.log(octopuse.tentacleA);
// → undefined
console.log('tentacleA' in octopuse);
// → false

用in來判斷屬性是否存在纔是準確的,由於值自己可能爲undefined

注意,delete刪除是有後遺症的!並不會刪除乾淨(會留引用)。因此能用filter儘可能不用delete

【PS. in和includes貌似能夠互相替換?】

 

七、列出對象的全部屬性名:

console.log(Object.keys(octopuse));
// → ["tentacleB", "tentacleC"]

 

八、Object.assign:

let objectA = {a: 1, b: 2};
Object.assign(objectA, {b: 3, c: 4});
console.log(objectA);
// → {a: 1, b: 3, c: 4}

 

九、多個引用能夠指向同一個對象,obj1==obj2比較的是引用的值(只有指向同一個對象才返回true),而不是對象的內容。

const obj只是引用的值不變,不能保證所指向對象的內容不變。

(上述兩點均可以類比Java)

 

 

十、直接傳入綁定(鍵值對):

let journal = [];

function addEntry(events, squirrel) {
  journal.push({events, squirrel});
}

 

十一、重寫書上的示例(探究xxx變成松鼠的緣由):

/**
 * getPhi返回變成松鼠和事件的
 * 相關性,返回的值爲-1~1,-1表示
 * 負相關,1表示正相關,0表示毫無關係。
 * table表示一個二維表,用於統
 * 計下面四種事件發生的次數:
 * 一、不變鬆鼠,事件沒發生00=0,
 * 二、不變鬆鼠,事件發生01=1,
 * 三、變成松鼠,事件沒發生10=2,
 * 四、變成松鼠,事件發生11=3
 * 測試:
 * console.log(getPhi([76, 9, 4, 1]));
 * → 0.06859943405700354
 */
const getPhi = (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(getTable(JOURNAL, "pizza"));
 * → [76, 9, 4, 1]
 */
const getTable = (JOURNAL, specificEvent) => {
    let result = [0, 0, 0, 0];
    for (let someday of JOURNAL) {
        let tableIndex = 0;
        if (someday.squirrel) tableIndex += 2;
        if (someday.events.includes(specificEvent)) tableIndex += 1;
        result[tableIndex]++;
    }
    return result;
};

/**
 * 返回包括日誌所記錄的全部事件的字符串數組
 */
const getAllEvents = (JOURNAL) => {
    let result = [];
    for (let x of JOURNAL) {
        for (let theEvent of x.events) {
            if (!result.includes(theEvent)) {
                result.push(theEvent);
            }
        }
    }
    return result;
};


const main = () => {
    let allEvents = getAllEvents(JOURNAL);
    for (let specificEvent of allEvents) {
        let table = getTable(JOURNAL, specificEvent);
        console.log(specificEvent + ":", getPhi(table));
    }
};

數據:

let JOURNAL = [{
        "events": ["carrot", "exercise", "weekend"],
        "squirrel": false
    },
    {
        "events": ["bread", "pudding", "brushed teeth", "weekend", "touched tree"],
        "squirrel": false
    },
    {
        "events": ["carrot", "nachos", "brushed teeth", "cycling", "weekend"],
        "squirrel": false
    },
    {
        "events": ["brussel sprouts", "ice cream", "brushed teeth", "computer", "weekend"],
        "squirrel": false
    },
    {
        "events": ["potatoes", "candy", "brushed teeth", "exercise", "weekend", "dentist"],
        "squirrel": false
    },
    {
        "events": ["brussel sprouts", "pudding", "brushed teeth", "running", "weekend"],
        "squirrel": false
    },
    {
        "events": ["pizza", "brushed teeth", "computer", "work", "touched tree"],
        "squirrel": false
    },
    {
        "events": ["bread", "beer", "brushed teeth", "cycling", "work"],
        "squirrel": false
    },
    {
        "events": ["cauliflower", "brushed teeth", "work"],
        "squirrel": false
    },
    {
        "events": ["pizza", "brushed teeth", "cycling", "work"],
        "squirrel": false
    },
    {
        "events": ["lasagna", "nachos", "brushed teeth", "work"],
        "squirrel": false
    },
    {
        "events": ["brushed teeth", "weekend", "touched tree"],
        "squirrel": false
    },
    {
        "events": ["lettuce", "brushed teeth", "television", "weekend"],
        "squirrel": false
    },
    {
        "events": ["spaghetti", "brushed teeth", "work"],
        "squirrel": false
    },
    {
        "events": ["brushed teeth", "computer", "work"],
        "squirrel": false
    },
    {
        "events": ["lettuce", "nachos", "brushed teeth", "work"],
        "squirrel": false
    },
    {
        "events": ["carrot", "brushed teeth", "running", "work"],
        "squirrel": false
    },
    {
        "events": ["brushed teeth", "work"],
        "squirrel": false
    },
    {
        "events": ["cauliflower", "reading", "weekend"],
        "squirrel": false
    },
    {
        "events": ["bread", "brushed teeth", "weekend"],
        "squirrel": false
    },
    {
        "events": ["lasagna", "brushed teeth", "exercise", "work"],
        "squirrel": false
    },
    {
        "events": ["spaghetti", "brushed teeth", "reading", "work"],
        "squirrel": false
    },
    {
        "events": ["carrot", "ice cream", "brushed teeth", "television", "work"],
        "squirrel": false
    },
    {
        "events": ["spaghetti", "nachos", "work"],
        "squirrel": false
    },
    {
        "events": ["cauliflower", "ice cream", "brushed teeth", "cycling", "work"],
        "squirrel": false
    },
    {
        "events": ["spaghetti", "peanuts", "computer", "weekend"],
        "squirrel": true
    },
    {
        "events": ["potatoes", "ice cream", "brushed teeth", "computer", "weekend"],
        "squirrel": false
    },
    {
        "events": ["potatoes", "ice cream", "brushed teeth", "work"],
        "squirrel": false
    },
    {
        "events": ["peanuts", "brushed teeth", "running", "work"],
        "squirrel": false
    },
    {
        "events": ["potatoes", "exercise", "work"],
        "squirrel": false
    },
    {
        "events": ["pizza", "ice cream", "computer", "work"],
        "squirrel": false
    },
    {
        "events": ["lasagna", "ice cream", "work"],
        "squirrel": false
    },
    {
        "events": ["cauliflower", "candy", "reading", "weekend"],
        "squirrel": false
    },
    {
        "events": ["lasagna", "nachos", "brushed teeth", "running", "weekend"],
        "squirrel": false
    },
    {
        "events": ["potatoes", "brushed teeth", "work"],
        "squirrel": false
    },
    {
        "events": ["carrot", "work"],
        "squirrel": false
    },
    {
        "events": ["pizza", "beer", "work", "dentist"],
        "squirrel": false
    },
    {
        "events": ["lasagna", "pudding", "cycling", "work"],
        "squirrel": false
    },
    {
        "events": ["spaghetti", "brushed teeth", "reading", "work"],
        "squirrel": false
    },
    {
        "events": ["spaghetti", "pudding", "television", "weekend"],
        "squirrel": false
    },
    {
        "events": ["bread", "brushed teeth", "exercise", "weekend"],
        "squirrel": false
    },
    {
        "events": ["lasagna", "peanuts", "work"],
        "squirrel": true
    },
    {
        "events": ["pizza", "work"],
        "squirrel": false
    },
    {
        "events": ["potatoes", "exercise", "work"],
        "squirrel": false
    },
    {
        "events": ["brushed teeth", "exercise", "work"],
        "squirrel": false
    },
    {
        "events": ["spaghetti", "brushed teeth", "television", "work"],
        "squirrel": false
    },
    {
        "events": ["pizza", "cycling", "weekend"],
        "squirrel": false
    },
    {
        "events": ["carrot", "brushed teeth", "weekend"],
        "squirrel": false
    },
    {
        "events": ["carrot", "beer", "brushed teeth", "work"],
        "squirrel": false
    },
    {
        "events": ["pizza", "peanuts", "candy", "work"],
        "squirrel": true
    },
    {
        "events": ["carrot", "peanuts", "brushed teeth", "reading", "work"],
        "squirrel": false
    },
    {
        "events": ["potatoes", "peanuts", "brushed teeth", "work"],
        "squirrel": false
    },
    {
        "events": ["carrot", "nachos", "brushed teeth", "exercise", "work"],
        "squirrel": false
    },
    {
        "events": ["pizza", "peanuts", "brushed teeth", "television", "weekend"],
        "squirrel": false
    },
    {
        "events": ["lasagna", "brushed teeth", "cycling", "weekend"],
        "squirrel": false
    },
    {
        "events": ["cauliflower", "peanuts", "brushed teeth", "computer", "work", "touched tree"],
        "squirrel": false
    },
    {
        "events": ["lettuce", "brushed teeth", "television", "work"],
        "squirrel": false
    },
    {
        "events": ["potatoes", "brushed teeth", "computer", "work"],
        "squirrel": false
    },
    {
        "events": ["bread", "candy", "work"],
        "squirrel": false
    },
    {
        "events": ["potatoes", "nachos", "work"],
        "squirrel": false
    },
    {
        "events": ["carrot", "pudding", "brushed teeth", "weekend"],
        "squirrel": false
    },
    {
        "events": ["carrot", "brushed teeth", "exercise", "weekend", "touched tree"],
        "squirrel": false
    },
    {
        "events": ["brussel sprouts", "running", "work"],
        "squirrel": false
    },
    {
        "events": ["brushed teeth", "work"],
        "squirrel": false
    },
    {
        "events": ["lettuce", "brushed teeth", "running", "work"],
        "squirrel": false
    },
    {
        "events": ["candy", "brushed teeth", "work"],
        "squirrel": false
    },
    {
        "events": ["brussel sprouts", "brushed teeth", "computer", "work"],
        "squirrel": false
    },
    {
        "events": ["bread", "brushed teeth", "weekend"],
        "squirrel": false
    },
    {
        "events": ["cauliflower", "brushed teeth", "weekend"],
        "squirrel": false
    },
    {
        "events": ["spaghetti", "candy", "television", "work", "touched tree"],
        "squirrel": false
    },
    {
        "events": ["carrot", "pudding", "brushed teeth", "work"],
        "squirrel": false
    },
    {
        "events": ["lettuce", "brushed teeth", "work"],
        "squirrel": false
    },
    {
        "events": ["carrot", "ice cream", "brushed teeth", "cycling", "work"],
        "squirrel": false
    },
    {
        "events": ["pizza", "brushed teeth", "work"],
        "squirrel": false
    },
    {
        "events": ["spaghetti", "peanuts", "exercise", "weekend"],
        "squirrel": true
    },
    {
        "events": ["bread", "beer", "computer", "weekend", "touched tree"],
        "squirrel": false
    },
    {
        "events": ["brushed teeth", "running", "work"],
        "squirrel": false
    },
    {
        "events": ["lettuce", "peanuts", "brushed teeth", "work", "touched tree"],
        "squirrel": false
    },
    {
        "events": ["lasagna", "brushed teeth", "television", "work"],
        "squirrel": false
    },
    {
        "events": ["cauliflower", "brushed teeth", "running", "work"],
        "squirrel": false
    },
    {
        "events": ["carrot", "brushed teeth", "running", "work"],
        "squirrel": false
    },
    {
        "events": ["carrot", "reading", "weekend"],
        "squirrel": false
    },
    {
        "events": ["carrot", "peanuts", "reading", "weekend"],
        "squirrel": true
    },
    {
        "events": ["potatoes", "brushed teeth", "running", "work"],
        "squirrel": false
    },
    {
        "events": ["lasagna", "ice cream", "work", "touched tree"],
        "squirrel": false
    },
    {
        "events": ["cauliflower", "peanuts", "brushed teeth", "cycling", "work"],
        "squirrel": false
    },
    {
        "events": ["pizza", "brushed teeth", "running", "work"],
        "squirrel": false
    },
    {
        "events": ["lettuce", "brushed teeth", "work"],
        "squirrel": false
    },
    {
        "events": ["bread", "brushed teeth", "television", "weekend"],
        "squirrel": false
    },
    {
        "events": ["cauliflower", "peanuts", "brushed teeth", "weekend"],
        "squirrel": false
    }
];
View Code

 

十二、重寫getPhi

function phi([n00, n01, n10, n11]) {
  return (n11 * n00 - n10 * n01) /
    Math.sqrt((n10 + n11) * (n00 + n01) *
              (n01 + n11) * (n00 + n10));
}

 

1三、JSON是方便在網絡上傳輸的數據,詳情直接閱讀百度百科。它的格式規定是很是嚴格的:JSON的屬性必須由雙引號包圍,JSON中不能有註釋 ...

let obj = {
    a: 123,
    b: "456"
};

console.log(obj);
// → {a: 123, b: "456"}

let string = JSON.stringify(obj);

console.log(string);
// → {"a":123,"b":"456"}

let obj2 = JSON.parse(string);
console.log(obj2);
// → {a: 123, b: "456"}

console.log(obj == obj2);
// → false

PS. === 是精確比較,不會進行類型轉換,== 會進行類型轉換(例如 1 == '1' 是true),在類型肯定相同的狀況下能夠用。

 

1四、各類語言中的可變參數(java、python、c++、javascript)

 

 

1五、More ...

經常使用數組方法

經常使用string方法

經常使用Math方法

大約在全文 2 /3 處 

 

1六、練習

① 實現range(a, b),返回[a, ... , b]。

(省略sum)

onst range = (start, end, step=1) => {
    let result = [];
    if (start <= end && step > 0) {
        for (let i = start; i <= end; i+=step) {
            result.push(i);
        }
    } else if (step < 0) {
        for (let i = start; i >= end; i+=step) {
            result.push(i);
        }        
    }
    return result;
};

console.log(range(1, 10));
console.log(range(5, 2, -1));
console.log(range(5, 2, 1));
// → [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// → [5, 4, 3, 2]
// → []

- - -- - - - - - -        -- -  -- -  - -- - - -          -- -  -- - - -- - - - - -- - - -- -- 

② 字符串倒序

let x = ['A', 'b', 'C'];
console.log(x.reverse());
console.log(x);
// → ["C", "b", "A"]
// → ["C", "b", "A"]

const reverseArray = arr => {
    let result = [];
    for (let i = 0; i != arr.length; ++i) {
        result.unshift(arr[i]); // 進隊
    }
    return result;
};

console.log(reverseArray(x));
console.log(x);
// → ["A", "b", "C"]
// → ["C", "b", "A"]

const reverseArrayInPlace = arr => {
    let start = 0;
    let end = arr.length - 1;
    while (start < end) {
        let temp = arr[start];
        arr[start++] = arr[end];
        arr[end--] = temp;
    }
};

console.log(reverseArrayInPlace(x));
console.log(x);
// → undefined
// → ["A", "b", "C"]

- - -- - - - - - -        -- -  -- -  - -- - - -          -- -  -- - - -- - - - - -- - - -- --  

③ 單向鏈表

const arrayToList = arr => {
    // 空數組直接返回null
    if(arr.length == 0) return null;

    let index = 0;
    let result = {
        value: arr[index++],
        rest: null    
    };
    // 數組元素數量爲1在初始化後馬上返回結果
    if(arr.length == 1) return result;

    // 數組元素數量大於1繼續添加元素到list
    let next = result;
    while(index < arr.length) {
        next = next.rest = {
            value: arr[index],
            rest: null
        };
        index++;
    }
    return result;
};

console.log(arrayToList([10, 20, 30]));
// → {value: 10, rest: {…}}

const listToArray = list => {
    let result = [];
    
    while (list.rest != null) {
        result.push(list.value);
        list = list.rest;
    }
    result.push(list.value);
    
    return result;
};

console.log(listToArray(arrayToList([10, 20, 30])));
// → [10, 20, 30]

const prepend = (x, list) => {
    let result = {
        value: x,
        rest: list
    };
    return result;
};

console.log(prepend(10, prepend(20, null)));
// → {value: 10, rest: {…}}

const nth = (list, x) => {
    for (let i = 0; i < x; ++i) {
        list = list.rest;
    }
    return list.value;
};

console.log(nth(arrayToList([10, 20, 30]), 1));
// → 20

遞歸版本nth:

const nth = (list, x) => {
    if (x == 0) return list.value;
    return nth(list.rest, --x);
};

課本解法(簡潔了一倍。。):

function arrayToList(array) {
  let list = null;
  for (let i = array.length - 1; i >= 0; i--) {
    list = {value: array[i], rest: list};
  }
  return list;
}

function listToArray(list) {
  let array = [];
  for (let node = list; node; node = node.rest) {
    array.push(node.value);
  }
  return array;
}

function prepend(value, list) {
  return {value, rest: list};
}

function nth(list, n) {
  if (!list) return undefined;
  else if (n == 0) return list.value;
  else return nth(list.rest, n - 1);
}

- - -- - - - - - -        -- -  -- -  - -- - - -          -- -  -- - - -- - - - - -- - - -- --  

④ 深度比較

const deepEqual = (a, b) => {
    let typeA = typeof a;
    let typeB = typeof b;
    // 類型不一樣直接返回false
    if (typeA != typeB) return false;
    
    // 判斷是否是能夠直接比較的類型
    let comparedDirectly = ["boolean", "number", "string"];
    if (comparedDirectly.includes(typeA)) return a === b;
    
    // 先排除值爲null的狀況
    if (a == null && b == null) return true;
    if (a == null && b != null || a !=null && b == null) return false;
    // 遞歸判斷
    if (typeA == "object") {
        let keyA = Object.keys(a);
        let keyB = Object.keys(b);
        if (keyA.length != keyB.length) return false;
        for (let k of keyA) {
            if (keyB.includes(k)) {
                return deepEqual(a[k], b[k]);
            } else {
                return false;
            }
        }
    }
    
    // 其它狀況一概返回未定義
    return undefined;
};

let obj = {here: {is: "an"}, object: 2};
console.log(deepEqual(obj, obj));
// → true
console.log(deepEqual(obj, {here: 1, object: 2}));
// → false
console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));
// → true

 課本解法:

function deepEqual(a, b) {
  if (a === b) return true;
  
  // null == null 的狀況在 a === b 時已通過濾掉了。
  if (a == null || typeof a != "object" ||
      b == null || typeof b != "object") return false;

  let keysA = Object.keys(a), keysB = Object.keys(b);

  if (keysA.length != keysB.length) return false;

  for (let key of keysA) {
    if (!keysB.includes(key) || !deepEqual(a[key], b[key])) return false;
  }

  return true;
}
相關文章
相關標籤/搜索