Eloquent JavaScript #04# Objects and Arrays

 要点索引:

1、补:js字符串的表达方式有三种: "" 和 '' 没什么区别,唯一区别在于 "" 中写 "要转义字符,在 '' 中写 ' 要转义字符。最后一种是 `` ,允许 'xx = ${算式}' 的简写方式。

2、两种主要的访问对象属性的方式 —— 点号与 [ ]

[ ] 会获取 [ ] 中的计算后字符串,点号则不会。

必须用 [ ] 的场景是访问数组属性 x[1], 因为点号后不能跟数字。

3、js数组自带push和pop方法。

队列也可以很容易实现:

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

4、对象的属性中,非有效引用名(例如包含空格↓)必须用字符串形式表达:

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

且必须要用 [ ] 访问该属性:

descriptions["touched tree"]

5、js对象允许动态添加属性:

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

如果已经存在就替换。点号也是可以的,但 [ ] 比较通用。

6、动态删除属性:

/*
 * 可以把对象想象成一只章鱼,对象的属性想象成带着便签
 * 的章鱼触手,数组也是一种对象,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

【PS. in和includes貌似可以互相替换?】

7、列出对象的所有属性名:

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

8、Object.assign:

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

9、多个引用可以指向同一个对象,obj1==obj2比较的是引用的值(只有指向同一个对象才返回true),而不是对象的内容。

const obj只是引用的值不变,不能保证所指向对象的内容不变。

(上述两点都可以类比Java)

10、直接传入绑定(键值对):

let journal = [];

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

11、重写书上的示例(探究xxx变成松鼠的原因):

/**
 * getPhi返回变成松鼠和事件的
 * 相关性,返回的值为-1~1,-1表示
 * 负相关,1表示正相关,0表示毫无关系。
 * table表示一个二维表,用于统
 * 计下面四种事件发生的次数:
 * 1、不变松鼠,事件没发生00=0,
 * 2、不变松鼠,事件发生01=1,
 * 3、变成松鼠,事件没发生10=2,
 * 4、变成松鼠,事件发生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

12、重写getPhi

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

13、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),在类型确定相同的情况下可以用。

14、各种语言中的可变参数(java、python、c++、javascript)

15、More ...

常用数组方法

常用string方法

常用Math方法

16、练习

① 实现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;
}

猜你喜欢

转载自www.cnblogs.com/xkxf/p/9546554.html