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
注意,delete删除是有后遗症的!并不会删除干净(会留引用)。所以能用filter尽量不用delete
【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 } ];
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)
大约在全文 2 /3 处
① 实现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; }