├── .DS_Store ├── 示例代码 ├── JSONs │ ├── .vscode │ │ └── settings.json │ ├── index.html │ └── index.js ├── .DS_Store ├── PostMessage │ ├── index │ │ ├── .vscode │ │ │ └── settings.json │ │ └── index.html │ └── other │ │ └── index.html ├── ESNext │ ├── .DS_Store │ ├── modules │ │ ├── main.js │ │ └── index.html │ ├── 01.basic │ │ └── index.js │ ├── 03.异步操作 │ │ ├── generator.js │ │ └── async-await.js │ └── 02.Proxy │ │ └── index.js ├── requestAnimationFrame │ ├── index.css │ ├── index.html │ └── index.js ├── doms │ ├── js │ │ ├── lib.js │ │ └── index.js │ └── index.html ├── Object │ ├── index.js │ └── index.html ├── Event │ ├── index.js │ └── index.html ├── BrowserCaches │ ├── 02_localStorage │ │ ├── index.js │ │ └── index.html │ ├── 01_Cookie │ │ ├── index.js │ │ ├── index.html │ │ └── Cookies.js │ └── 03_indexDB │ │ ├── index.html │ │ ├── index.js │ │ └── utils.js ├── DesignPatterns │ ├── 01.工厂模式.js │ ├── 03.观察者模式.js │ ├── 04.发布订阅者模式.js │ └── 02.单例模式.js ├── Basic │ └── 01_基础语法.js ├── Eventloops │ └── index.js ├── DebounceAndThrottle │ └── index.html └── Promise │ └── 01.基础用法 │ └── index.js ├── IMGS ├── rAF.gif ├── 任务队列.png ├── .DS_Store ├── extends.png ├── rect.jpeg ├── ec_stack.png ├── location.jpeg ├── nodeTree.png ├── part_2_1.png ├── part_2_2.jpg ├── part_3_8.jpeg ├── part_3_9.jpeg ├── part_6_1.jpeg ├── part_6_2.jpeg ├── part_6_3.jpeg ├── part_6_4.jpeg ├── part_6_5.jpeg ├── part_6_6.jpeg ├── part_6_8.png ├── useragent.jpg ├── bom_location.png ├── bom_screen.png ├── part_10_14.jpeg ├── part_10_15.jpeg ├── part_10_16.jpeg ├── part_10_17.jpeg ├── part_3_10.jpeg ├── post_message.png ├── scope_word.png ├── flowOfEvents.jpeg ├── page_renders.jpeg ├── execution_stack.gif ├── indexDB_examples.jpg ├── js_life_circles.png └── prototype-chain.png ├── 思维导图 ├── .DS_Store ├── DOM树.xmind ├── 任务队列.xmind ├── 渲染进程.xmind └── 运行生命周期.xmind ├── 第08章 Symbol.md ├── 第12章 定时器与延迟函数.md ├── 第15章 异常处理.md ├── 第11章 BOM.md ├── 第17章 requestAnimationFrame.md ├── 第16章 事件循环.md ├── 第14章 正则表达式.md ├── 第13章 浏览器缓存.md ├── 第03章 数值.md ├── 第18章 设计模式.md ├── 第10章 事件.md ├── README.md ├── 第02章 程序结构.md ├── 第08章 内置对象.md ├── 第09章 DOM.md └── 第04章 字符串.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/.DS_Store -------------------------------------------------------------------------------- /示例代码/JSONs/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "liveServer.settings.port": 5501 3 | } -------------------------------------------------------------------------------- /IMGS/rAF.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/rAF.gif -------------------------------------------------------------------------------- /IMGS/任务队列.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/任务队列.png -------------------------------------------------------------------------------- /IMGS/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/.DS_Store -------------------------------------------------------------------------------- /IMGS/extends.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/extends.png -------------------------------------------------------------------------------- /IMGS/rect.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/rect.jpeg -------------------------------------------------------------------------------- /思维导图/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/思维导图/.DS_Store -------------------------------------------------------------------------------- /思维导图/DOM树.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/思维导图/DOM树.xmind -------------------------------------------------------------------------------- /思维导图/任务队列.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/思维导图/任务队列.xmind -------------------------------------------------------------------------------- /思维导图/渲染进程.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/思维导图/渲染进程.xmind -------------------------------------------------------------------------------- /示例代码/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/示例代码/.DS_Store -------------------------------------------------------------------------------- /IMGS/ec_stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/ec_stack.png -------------------------------------------------------------------------------- /IMGS/location.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/location.jpeg -------------------------------------------------------------------------------- /IMGS/nodeTree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/nodeTree.png -------------------------------------------------------------------------------- /IMGS/part_2_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/part_2_1.png -------------------------------------------------------------------------------- /IMGS/part_2_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/part_2_2.jpg -------------------------------------------------------------------------------- /IMGS/part_3_8.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/part_3_8.jpeg -------------------------------------------------------------------------------- /IMGS/part_3_9.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/part_3_9.jpeg -------------------------------------------------------------------------------- /IMGS/part_6_1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/part_6_1.jpeg -------------------------------------------------------------------------------- /IMGS/part_6_2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/part_6_2.jpeg -------------------------------------------------------------------------------- /IMGS/part_6_3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/part_6_3.jpeg -------------------------------------------------------------------------------- /IMGS/part_6_4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/part_6_4.jpeg -------------------------------------------------------------------------------- /IMGS/part_6_5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/part_6_5.jpeg -------------------------------------------------------------------------------- /IMGS/part_6_6.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/part_6_6.jpeg -------------------------------------------------------------------------------- /IMGS/part_6_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/part_6_8.png -------------------------------------------------------------------------------- /IMGS/useragent.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/useragent.jpg -------------------------------------------------------------------------------- /思维导图/运行生命周期.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/思维导图/运行生命周期.xmind -------------------------------------------------------------------------------- /示例代码/PostMessage/index/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "liveServer.settings.port": 5501 3 | } -------------------------------------------------------------------------------- /IMGS/bom_location.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/bom_location.png -------------------------------------------------------------------------------- /IMGS/bom_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/bom_screen.png -------------------------------------------------------------------------------- /IMGS/part_10_14.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/part_10_14.jpeg -------------------------------------------------------------------------------- /IMGS/part_10_15.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/part_10_15.jpeg -------------------------------------------------------------------------------- /IMGS/part_10_16.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/part_10_16.jpeg -------------------------------------------------------------------------------- /IMGS/part_10_17.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/part_10_17.jpeg -------------------------------------------------------------------------------- /IMGS/part_3_10.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/part_3_10.jpeg -------------------------------------------------------------------------------- /IMGS/post_message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/post_message.png -------------------------------------------------------------------------------- /IMGS/scope_word.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/scope_word.png -------------------------------------------------------------------------------- /示例代码/ESNext/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/示例代码/ESNext/.DS_Store -------------------------------------------------------------------------------- /IMGS/flowOfEvents.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/flowOfEvents.jpeg -------------------------------------------------------------------------------- /IMGS/page_renders.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/page_renders.jpeg -------------------------------------------------------------------------------- /IMGS/execution_stack.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/execution_stack.gif -------------------------------------------------------------------------------- /IMGS/indexDB_examples.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/indexDB_examples.jpg -------------------------------------------------------------------------------- /IMGS/js_life_circles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/js_life_circles.png -------------------------------------------------------------------------------- /IMGS/prototype-chain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihongyao/JavaScript/HEAD/IMGS/prototype-chain.png -------------------------------------------------------------------------------- /示例代码/ESNext/modules/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2023-05-08 18:21:03 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2023-05-08 18:21:59 6 | * @Description: 7 | */ 8 | console.log('模块化'); 9 | -------------------------------------------------------------------------------- /示例代码/requestAnimationFrame/index.css: -------------------------------------------------------------------------------- 1 | .progress { 2 | width: 300px; 3 | height: 10px; 4 | border-radius: 12px; 5 | background: #eee; 6 | margin-bottom: 16px; 7 | } 8 | .v { 9 | height: 100%; 10 | background: cornflowerblue; 11 | border-radius: 12px; 12 | } -------------------------------------------------------------------------------- /示例代码/ESNext/01.basic/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2023-05-30 10:54:59 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2023-05-30 11:32:40 6 | * @Description: 7 | */ 8 | 9 | // -- 解构 10 | // 1. 交换值 11 | let x = 10, y = 20; 12 | [x, y] = [y, x]; 13 | console.log(x, y); 14 | 15 | 16 | // -- Map 17 | 18 | -------------------------------------------------------------------------------- /示例代码/doms/js/lib.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2022-03-29 17:22:47 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2022-11-29 15:31:10 6 | */ 7 | 8 | function showDomInfos(sel) { 9 | const el = document.querySelector(sel); 10 | console.table({ 11 | nodeName: el.nodeName, 12 | nodeValue: el.nodeValue, 13 | nodeType: el.nodeType, 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /示例代码/Object/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2022-11-29 10:44:31 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2022-11-29 11:43:40 6 | * @Description: 7 | */ 8 | 9 | var o1 = { name: '张三' }; 10 | var o2 = { major: '软件技术', name: '李四' }; 11 | 12 | var result = Object.assign(o1, o2); 13 | 14 | console.log(result); // {name: '李四', major: '软件技术'} 15 | console.log(result === o1); 16 | -------------------------------------------------------------------------------- /示例代码/Event/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2022-12-01 16:05:40 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2022-12-01 17:04:32 6 | * @Description: 7 | */ 8 | var button = document.querySelector('.button'); 9 | 10 | // -- 添加事件监听 11 | button.addEventListener('click', handler, false); 12 | // -- 移除事件监听 13 | button.removeEventListener('click', handler, false); 14 | 15 | function handler() { 16 | console.log('Hello'); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /示例代码/ESNext/03.异步操作/generator.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2023-05-30 17:47:18 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2023-05-30 17:54:56 6 | * @Description: 7 | */ 8 | 9 | function* generator1() { 10 | yield 'Hello'; 11 | yield 'World'; 12 | } 13 | 14 | function* generator2() { 15 | yield* generator1(); 16 | yield '!'; 17 | } 18 | 19 | // 遍历组合的生成器 20 | const iterator = generator2(); 21 | for (const item of iterator) { 22 | console.log(item); // Hello, World, ! 23 | } 24 | -------------------------------------------------------------------------------- /示例代码/Object/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Objects 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /示例代码/JSONs/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | JSON - testing 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /示例代码/ESNext/modules/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 模块化 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /示例代码/BrowserCaches/02_localStorage/index.js: -------------------------------------------------------------------------------- 1 | var key = ''; 2 | var value = ''; 3 | 4 | function onKeyChange(event) { 5 | key = event.target.value; 6 | } 7 | function onValueChange(event) { 8 | value = event.target.value; 9 | } 10 | 11 | function onSetItem() { 12 | console.log(localStorage.setItem(key, value)); 13 | } 14 | 15 | function onGetItem() { 16 | console.log(localStorage.getItem(key)); 17 | } 18 | 19 | function onRemoveItem() { 20 | console.log(localStorage.removeItem(key)); 21 | } 22 | 23 | function onClear() { 24 | console.log(localStorage.clear()); 25 | } 26 | -------------------------------------------------------------------------------- /示例代码/Event/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Document 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /示例代码/DesignPatterns/01.工厂模式.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2023-05-06 16:59:30 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2023-05-06 16:59:35 6 | * @Description: 7 | */ 8 | function createPerson(name, age) { 9 | return { 10 | name: name, 11 | age: age, 12 | sayHello: function () { 13 | console.log( 14 | `Hello, my name is ${this.name} and I'm ${this.age} years old.` 15 | ); 16 | }, 17 | }; 18 | } 19 | 20 | const person1 = createPerson('John', 30); 21 | const person2 = createPerson('Jane', 25); 22 | 23 | person1.sayHello(); // 输出:Hello, my name is John and I'm 30 years old. 24 | person2.sayHello(); // 输出:Hello, my name is Jane and I'm 25 years old. 25 | -------------------------------------------------------------------------------- /示例代码/Basic/01_基础语法.js: -------------------------------------------------------------------------------- 1 | var value = 2; 2 | var foo = { 3 | value: 1, 4 | }; 5 | function bar(name, job) { 6 | return { 7 | value: this.value, 8 | name, 9 | job, 10 | }; 11 | } 12 | 13 | // var r = bar.call(foo, "Alice", "Web Front-end Engineer"); 14 | // console.log(r); // → { value: 1, name: 'Alice', job: 'Web Front-end Engineer' } 15 | 16 | var r = bar.apply(this, ["Alice", "Web Front-end Engineer"]); /** this 指向window, 所以this.value = 2 */ 17 | console.log(r); // → {value: 2, name: 'Alice', job: 'Web Front-end Engineer'} 18 | 19 | // var func = bar.bind(foo, "Alice", "Web Front-end Engineer"); /** 返回新函数 */ 20 | // console.log(func()); // → { value: 1, name: 'Alice', job: 'Web Front-end Engineer' } 21 | -------------------------------------------------------------------------------- /示例代码/BrowserCaches/01_Cookie/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2022-12-05 09:25:40 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2022-12-05 10:56:03 6 | * @Description: 7 | */ 8 | 9 | var key = ''; 10 | var value = ''; 11 | 12 | function onKeyChange(event) { 13 | key = event.target.value; 14 | } 15 | function onValueChange(event) { 16 | value = event.target.value; 17 | } 18 | function onGetCookies() { 19 | console.log(docCookies.getItem(key)); 20 | } 21 | function onSetCookies() { 22 | if (!key || !value) return; 23 | console.log(docCookies.setItem(key, value)); 24 | } 25 | function onRemoveCookies() { 26 | console.log(docCookies.removeItem(key)); 27 | } 28 | 29 | function onGetKeys() { 30 | console.log(docCookies.keys()); 31 | } 32 | -------------------------------------------------------------------------------- /示例代码/requestAnimationFrame/index.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | requestAnimationFrame 14 | 15 | 16 | 17 |
18 |
19 |
20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /示例代码/PostMessage/other/index.html: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | OTHER PAGE 17 | 18 | 19 | 20 |
Sub window recived message is:
21 |
22 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /示例代码/doms/index.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | DOMs 14 | 15 | 16 |
成都哈戳戳科技有限公司
17 | 25 |
成都市高新区新川科技园A区
26 |
DOMs
27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /示例代码/ESNext/03.异步操作/async-await.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2023-03-07 20:31:44 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2023-03-07 20:39:25 6 | * @Description: 7 | */ 8 | 9 | // -- 线程休眠 10 | /*function sleep(seconds) { 11 | return new Promise((resolve) => setTimeout(() => resolve(seconds), seconds)); 12 | } 13 | 14 | async function test() { 15 | console.log(1); 16 | await sleep(2000); 17 | console.log(2); 18 | } 19 | test();*/ 20 | 21 | // -- async & await 是否可以取代Promise --- 不可以 22 | function sleep(seconds) { 23 | return new Promise((resolve) => { 24 | setTimeout(() => { 25 | console.log(Math.random()); 26 | resolve(); 27 | }, seconds); 28 | }); 29 | } 30 | 31 | // -- 串行执行 32 | // -- 省市区 33 | async function test() { 34 | await sleep(1000); 35 | await sleep(1000); 36 | await sleep(1000); 37 | } 38 | 39 | // -- 并发执行 -- 还是得用Promise.all 40 | async function test() { 41 | const tasks = []; 42 | for (let i = 0; i < 3; i++) { 43 | tasks.push(sleep(1000)); 44 | } 45 | await Promise.all(tasks); 46 | } 47 | 48 | test(); 49 | -------------------------------------------------------------------------------- /示例代码/BrowserCaches/02_localStorage/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Web Storage 17 | 18 | 19 | 20 |

21 | 键: 22 | 23 |

24 |

25 | 值: 26 | 27 |

28 | 31 | 34 | 37 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /示例代码/BrowserCaches/01_Cookie/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Cookie 16 | 17 | 18 | 19 |

20 | 键: 21 | 22 |

23 |

24 | 值: 25 | 26 |

27 | 30 | 33 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /示例代码/PostMessage/index/index.html: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | INDEX PAGE 18 | 19 | 20 | 21 |
22 | 23 |
24 |
25 | 26 |
27 | 28 | 29 | 30 | 45 | 46 | -------------------------------------------------------------------------------- /示例代码/DesignPatterns/03.观察者模式.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2023-05-06 17:17:18 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2023-05-06 17:24:29 6 | * @Description: 7 | */ 8 | 9 | // 1.创建一个被观察者(Subject)对象,它包含一个观察者(Observer)列表和一些方法来添加、删除和通知观察者。 10 | class Subject { 11 | constructor() { 12 | this.observers = []; 13 | } 14 | 15 | addObserver(observer) { 16 | this.observers.push(observer); 17 | } 18 | removeObserver(observer) { 19 | const index = this.observers.indexOf(observer); 20 | if (index !== -1) { 21 | this.observers.splice(index, 1); 22 | } 23 | } 24 | notifyObservers(data) { 25 | for (const observer of this.observers) { 26 | observer.update(data); 27 | } 28 | } 29 | } 30 | 31 | // 2.创建一个观察者对象,它包含一个 update 方法,用于接收来自被观察者的通知。 32 | class Observer { 33 | constructor() {} 34 | update(data) { 35 | console.log(`Received data:${data}`); 36 | } 37 | } 38 | 39 | // 3.创建一个被观察者实例和多个观察者实例,并将观察者添加到被观察者的观察者列表中。 40 | const subject = new Subject(); 41 | const observer1 = new Observer(); 42 | const observer2 = new Observer(); 43 | 44 | subject.addObserver(observer1); 45 | subject.addObserver(observer2); 46 | 47 | // 4.调用被观察者的 notifyObservers 方法,通知所有观察者更新。 48 | subject.notifyObservers(JSON.stringify({ message: 'Hello' })); 49 | -------------------------------------------------------------------------------- /示例代码/BrowserCaches/03_indexDB/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | IndexDB 8 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /示例代码/Eventloops/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2023-05-06 16:14:03 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2023-05-06 16:33:09 6 | * @Description: 7 | */ 8 | 9 | 10 | 11 | // → 示例1 12 | // console.log('start'); 13 | // setTimeout(function cb() { 14 | // console.log('setTimeout1'); 15 | // }); 16 | 17 | // console.log('message'); 18 | 19 | // setTimeout(function cb1() { 20 | // console.log('setTimeout2'); 21 | // }, 0); 22 | 23 | // console.log('end'); 24 | 25 | 26 | 27 | 28 | // → 示例2 29 | // console.log('start'); 30 | 31 | // setTimeout(() => { 32 | // console.log('setTimeout'); 33 | // }, 0); 34 | 35 | // Promise.resolve() 36 | // .then(() => { 37 | // console.log('promise1'); 38 | // }) 39 | // .then(() => { 40 | // console.log('promise2'); 41 | // }); 42 | 43 | // console.log('end'); 44 | 45 | // → 示例3 46 | // console.log('start'); // 同步代码,立即执行 47 | 48 | // setTimeout(function () { 49 | // console.log('timeout1'); // 宏任务 50 | // }, 5); 51 | 52 | // new Promise((resolve) => { 53 | // console.log('promise1'); // 同步代码,立即执行 54 | // resolve(); 55 | // setTimeout(() => console.log('timeout2'), 5); // 宏任务 56 | // }).then(function () { 57 | // console.log('then1'); // 微任务 58 | // }); 59 | 60 | // console.log('end'); // 同步代码,立即执行 61 | 62 | // start → promise1 → end → then1 → timeout1 → timeout2 63 | 64 | 65 | -------------------------------------------------------------------------------- /示例代码/DesignPatterns/04.发布订阅者模式.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2023-05-06 17:40:30 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2023-05-06 18:04:25 6 | * @Description: 7 | */ 8 | class EventBus { 9 | constructor() { 10 | this.listeners = {}; 11 | } 12 | 13 | on(event, listener) { 14 | if (!this.listeners[event]) { 15 | this.listeners[event] = []; 16 | } 17 | this.listeners[event].push(listener); 18 | } 19 | 20 | emit(event, ...args) { 21 | const listeners = this.listeners[event]; 22 | if (listeners) { 23 | listeners.forEach((listener) => { 24 | listener(...args); 25 | }); 26 | } 27 | } 28 | 29 | removeListener(event, listenerToRemove) { 30 | const listeners = this.listeners[event]; 31 | if (listeners) { 32 | this.listeners[event] = listeners.filter( 33 | (listener) => listener !== listenerToRemove 34 | ); 35 | } 36 | } 37 | 38 | removeAllListeners(event) { 39 | delete this.listeners[event]; 40 | } 41 | } 42 | 43 | const bus = new EventBus(); 44 | 45 | const listenerFunction = (args) => { 46 | console.log(args); 47 | }; 48 | 49 | // 1. 添加一个监听器 50 | bus.on('click', listenerFunction); 51 | // 2. 触发事件 52 | bus.emit('click', 'Hello'); 53 | // 3. 删除监听器 54 | bus.removeListener('click', listenerFunction); 55 | // 4. 删除所有监听器 56 | bus.removeAllListeners('click'); 57 | -------------------------------------------------------------------------------- /示例代码/DesignPatterns/02.单例模式.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2023-05-06 17:02:57 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2023-05-06 17:09:31 6 | * @Description: 7 | */ 8 | 9 | // const Singleton = (function () { 10 | // let instance; 11 | 12 | // function createInstance() { 13 | // const object = new Object({ name: 'John' }); 14 | // return object; 15 | // } 16 | 17 | // return { 18 | // getInstance: function () { 19 | // if (!instance) { 20 | // instance = createInstance(); 21 | // } 22 | // return instance; 23 | // }, 24 | // }; 25 | // })(); 26 | 27 | // const instance1 = Singleton.getInstance(); 28 | // const instance2 = Singleton.getInstance(); 29 | 30 | // console.log(instance1 === instance2); // true 31 | 32 | class Singleton { 33 | constructor() { 34 | if (Singleton.instance) { 35 | return Singleton.instance; 36 | } 37 | Singleton.instance = this; 38 | } 39 | 40 | static getInstance() { 41 | if (Singleton.instance) { 42 | return Singleton.instance; 43 | } 44 | return new Singleton(); 45 | } 46 | } 47 | 48 | const instance1 = new Singleton(); 49 | const instance2 = new Singleton(); 50 | const instance3 = Singleton.getInstance(); 51 | const instance4 = Singleton.getInstance(); 52 | console.log(instance1 === instance2); // true 53 | console.log(instance3 === instance4); // true 54 | -------------------------------------------------------------------------------- /示例代码/doms/js/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2022-03-29 17:12:53 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2022-11-30 10:44:25 6 | */ 7 | 8 | // -- 查找DOM 9 | // 1. 根据ID查找 10 | console.log(document.getElementById('company')); 11 | // 2. 根据name属性查找 12 | console.log(document.getElementsByName('address')); 13 | // 3. 根据类名查找 14 | console.log(document.getElementsByClassName('departments')); 15 | // 4. 根据标签名查找 16 | console.log(document.getElementsByTagName('li')); 17 | // 5. 根据CSS选择器查找 18 | console.log(document.querySelector('#company')); 19 | console.log(document.querySelectorAll('.departments li')); 20 | 21 | var list = document.querySelector('.departments'); 22 | console.log(list.previousElementSibling); 23 | console.log(list.previousSibling); 24 | console.log(list.nextElementSibling); 25 | console.log(list.nextSibling); 26 | console.log(list.parentElement); 27 | console.log(list.parentNode); 28 | console.log(list.children); 29 | console.log(list.childElementCount); 30 | console.log(list.childNodes); 31 | console.log(list.firstElementChild); 32 | console.log(list.lastElementChild); 33 | 34 | // -- 节点操作 35 | // 1. 创建节点 36 | const el = document.createElement('div'); 37 | const attr = document.createAttribute('class'); 38 | const fragment = document.createDocumentFragment(); 39 | 40 | const li = document.createElement('li'); 41 | li.textContent = '纪检部'; 42 | // list.appendChild(li); 43 | // list.append(li); 44 | list.prepend(li); 45 | 46 | 47 | -------------------------------------------------------------------------------- /第08章 Symbol.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | [Symbol](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Symbol) 是 ES6 引入的一种原始数据类型,其主要作用是生成 **唯一且不可变** 的标识符。 4 | 5 | `Symbol()` 函数会返回 **symbol** 类型的值,该类型具有静态属性和静态方法。它的静态属性会暴露几个内建的成员对象;它的静态方法会暴露全局的 symbol 注册,且类似于内建对象类,但作为构造函数来说它并不完整,因为它不支持语法:"`new Symbol()`"。 6 | 7 | # 应用场景 8 | 9 | Symbol 的常见应用场景包括: 10 | 11 | 1. **作为对象的唯一属性名**:Symbol 能确保对象属性的唯一性,避免因属性名重复导致的意外覆盖。 12 | 13 | ```js 14 | const id = Symbol('id'); 15 | const obj = { 16 | [id]: '12345' 17 | }; 18 | ``` 19 | 20 | 2. **实现私有属性或方法**:通过 Symbol 定义的属性在常规遍历(如 `for...in` 或 `Object.keys()`)中不可见,可用于模拟私有成员。 21 | 22 | ```js 23 | const _privateMethod = Symbol('privateMethod'); 24 | class MyClass { 25 | [_privateMethod]() { 26 | // 私有方法逻辑 27 | } 28 | } 29 | ``` 30 | 31 | 3. **定义唯一常量值**:Symbol 的不可重复特性使其适合表示需要严格区分的常量。 32 | 33 | ```js 34 | const LOG_LEVEL = { 35 | DEBUG: Symbol('debug'), 36 | INFO: Symbol('info'), 37 | ERROR: Symbol('error') 38 | }; 39 | ``` 40 | 41 | 4. **利用内置 Symbol 值扩展对象行为**:ES6 提供了如 `Symbol.iterator`、`Symbol.toStringTag` 等内置 Symbol,用于自定义对象的语言原生行为(如迭代、类型标签等)。 42 | 43 | ```js 44 | const obj = { 45 | [Symbol.toStringTag]: 'MyObject' 46 | }; 47 | console.log(obj.toString()); // 输出:[object MyObject] 48 | ``` 49 | 50 | # 注意事项 51 | 52 | 1. Symbol 属性无法通过 `Object.keys()` 或 `for...in` 遍历,需使用 `Object.getOwnPropertySymbols()` 获取。 53 | 2. Symbol 的核心价值在于 **属性唯一性**、**代码封装性** 和 **对象行为扩展性**,合理使用可提升代码健壮性并减少命名冲突风险。 -------------------------------------------------------------------------------- /示例代码/requestAnimationFrame/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2022-12-07 17:03:47 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2022-12-12 11:42:35 6 | * @Description: 7 | */ 8 | 9 | /**************** 10 | * 1.页面可见性:visibilitychange 11 | */ 12 | window.addEventListener( 13 | 'visibilitychange', 14 | () => { 15 | console.log('document.hidden = ' + document.hidden); 16 | }, 17 | false 18 | ); 19 | 20 | /**************** 21 | * 2.使用·动画 22 | */ 23 | // -- 获取DOM元素 24 | let progress = document.querySelector('.v'); 25 | // -- 记录步长 26 | let step; 27 | // -- 记录回调函数 28 | let handlerId; 29 | // -- 动画帧回调函数 30 | function render() { 31 | step++; 32 | progress.style.width = `${step}%`; 33 | if (step < 100) { 34 | handlerId = window.requestAnimationFrame(render); 35 | } 36 | } 37 | // -- 点击Loading按钮时触发,调用动画效果 38 | function onLoading() { 39 | step = 0; 40 | progress.style.width = '0%'; 41 | render(); 42 | } 43 | // -- 点击Stop按钮时触发,停止动画 44 | function onStop() { 45 | cancelAnimationFrame(handlerId); 46 | } 47 | 48 | /**************** 49 | * 3.使用·函数节流 50 | */ 51 | /*window.onmousemove = ({ clientX, clientY }) => { 52 | requestAnimationFrame(() => { 53 | console.log(clientX, clientY); 54 | }); 55 | };*/ 56 | 57 | /**************** 58 | * 4.使用·分帧初始化 59 | */ 60 | /*class A {} 61 | class B {} 62 | class C {} 63 | class D {} 64 | var lazyLoadList = [A, B, C, D]; 65 | lazyLoadList.forEach((module) => { 66 | window.requestAnimationFrame(() => { 67 | new module(); 68 | }); 69 | });*/ 70 | 71 | -------------------------------------------------------------------------------- /示例代码/DebounceAndThrottle/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 函数防抖与节流 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /示例代码/JSONs/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2022-11-29 13:46:56 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2022-11-29 14:11:15 6 | * @Description: 7 | */ 8 | 9 | /// 语法形式:JSON.stringify(value[, replacer[, space]]) 10 | 11 | /// -- 转换 12 | 13 | var person = { 14 | name: '张三', 15 | age: 30, 16 | sex: '男', 17 | job: '前端工程师', 18 | }; 19 | 20 | // 1. 转换对象 21 | console.log(JSON.stringify(person)); 22 | // → {"name":"张三","age":30,"sex":"男","job":"前端工程师"} 23 | 24 | // 2. 转换普通值 25 | console.log(JSON.stringify('成都')); // → "成都" 26 | console.log(JSON.stringify(1)); // → "1" 27 | console.log(JSON.stringify(true)); // → "true" 28 | console.log(JSON.stringify(null)); // → "null" 29 | 30 | // 3. 指定replacer参数为:函数 31 | console.log( 32 | JSON.stringify(person, (key, value) => { 33 | // -- 过滤属性值为 number 类型的 key-value 对 34 | return typeof value === 'number' ? undefined : value; 35 | }) 36 | ); 37 | // → {"name":"张三","sex":"男","job":"前端工程师"} 38 | 39 | // 4. 指定replacer参数为:数组 40 | console.log(JSON.stringify(person, ['name', 'age'])); 41 | // → {"name":"张三","age":30} 42 | 43 | // 5. 指定space(美化输出) 44 | console.log(JSON.stringify(person, null, 2)); 45 | 46 | /*{ 47 | "name": "张三", 48 | "age": 30, 49 | "sex": "男", 50 | "job": "前端工程师" 51 | }*/ 52 | 53 | // -- 特性1 54 | console.log(JSON.stringify(() => {})); 55 | console.log(JSON.stringify(Symbol('Tag'))); 56 | console.log(JSON.stringify(undefined)); 57 | 58 | // -- 特性2 59 | console.log( 60 | JSON.stringify({ 61 | name: new String('张三'), 62 | age: new Number(30), 63 | checked: new Boolean(false), 64 | }) 65 | ); 66 | // → {"name":"张三","age":30,"checked":false} 67 | 68 | // -- 特性五 69 | console.log( 70 | JSON.stringify({ 71 | name: '张三', 72 | job: '前端工程师', 73 | toJSON: function () { 74 | return `${this.name} - ${this.job}`; 75 | }, 76 | }) 77 | ); 78 | 79 | // → 张三 - 前端工程师 -------------------------------------------------------------------------------- /示例代码/ESNext/02.Proxy/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2023-05-30 16:31:23 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2023-05-30 16:45:14 6 | * @Description: 7 | */ 8 | 9 | // const object = { name: '张三', job: '前端工程师' }; 10 | // const p = new Proxy(object, { 11 | // get(target, property, receiver) { 12 | // const value = target[property]; 13 | // if (value) { 14 | // return value; 15 | // } else { 16 | // throw new ReferenceError(`Property ${property} does not exist.`); 17 | // } 18 | // }, 19 | // }); 20 | 21 | // console.log(p.name); // 张三 22 | // console.log(p.major); // ReferenceError: Property major does not exist. 23 | 24 | // const car = { 25 | // _brand: '东风本田', 26 | // color: '珍珠白', 27 | // }; 28 | // const p = new Proxy(car, { 29 | // get(target, property, receiver) { 30 | // // 实现私有属性的保护 31 | // if (/^_/.test(property)) { 32 | // throw new Error(`私有属性 ${property} 不可访问.`); 33 | // } 34 | // return Reflect.get(target, property, receiver); 35 | // }, 36 | // }); 37 | 38 | // console.log(p.color); // 珍珠白 39 | // console.log(p._brand); // Error: 私有属性 _brand 不可访问. 40 | 41 | const api = { 42 | _appsecret: '5732e4c9db7ff9f7', 43 | appID: 'wx1695393264bf7d', 44 | wx: 'gh_133b3cd88m3a', 45 | }; 46 | 47 | const p = new Proxy(api, { 48 | get(target, property, receiver) { 49 | if (/^_/.test(property)) { 50 | console.log(`私有属性 ${property} 不支持访问.`); 51 | return null; 52 | } 53 | return Reflect.get(target, property, receiver); 54 | }, 55 | set(target, property, value, receiver) { 56 | if (/^_/.test(property)) { 57 | console.log(`私有属性 ${property} 不支持赋值.`); 58 | return null; 59 | } 60 | return Reflect.set(target, property, value, receiver); 61 | }, 62 | }); 63 | 64 | console.log(p.appID); // - 5732e4c9db7ff9f7 65 | console.log(p._appsecret); // - 有属性 _appsecret 不支持访问. 66 | -------------------------------------------------------------------------------- /示例代码/Promise/01.基础用法/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2023-05-08 19:42:43 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2023-05-08 20:25:11 6 | * @Description: 7 | */ 8 | 9 | // 1. 基础用法 10 | const login = (username, password) => { 11 | return new Promise((resolve, reject) => { 12 | /** 模拟异步操作 */ 13 | setTimeout(() => { 14 | if (username === 'admin' && password === '123') { 15 | resolve(); 16 | } else { 17 | reject(); 18 | } 19 | }, 2000); 20 | }); 21 | }; 22 | login('admin', '123').then( 23 | () => { 24 | console.log('成功'); 25 | }, 26 | (error) => { 27 | console.log('失败'); 28 | } 29 | ); 30 | 31 | // 2. then 32 | 33 | // -- 改变值 34 | const promise = new Promise((resolve) => resolve('ACDB')); 35 | promise 36 | .then((resp) => { 37 | console.log(resp); // → ACDB 38 | return resp.split(''); 39 | }) 40 | .then((letters) => { 41 | console.log(letters); // → [ 'A', 'C', 'D', 'B' ] 42 | return letters.sort(); 43 | }) 44 | .then((sorted) => { 45 | console.log(sorted); // → [ 'A', 'B', 'C', 'D' ] 46 | return sorted.join(''); 47 | }) 48 | .then((result) => { 49 | console.log(result); // → ABCD 50 | }); 51 | 52 | // 3. catch 53 | 54 | login() 55 | .then(() => { 56 | console.log('Login success.'); 57 | }) 58 | .catch((error) => { 59 | console.log('Login failure.'); 60 | }); 61 | 62 | // 4. Promise.all 63 | // const promise1 = Promise.resolve(3); 64 | // const promise2 = 42; 65 | // const promise3 = new Promise((resolve, reject) => { 66 | // setTimeout(() => { 67 | // resolve('foo'); 68 | // }, 100); 69 | // }); 70 | 71 | // Promise.all([promise1, promise2, promise3]).then((values) => { 72 | // console.log(values); // 输出:[ 3, 42, 'foo' ] 73 | // }); 74 | 75 | // 5. Promise.race 76 | const promise1 = new Promise((resolve, reject) => { 77 | setTimeout(resolve, 500, 'one'); 78 | }); 79 | 80 | const promise2 = new Promise((resolve, reject) => { 81 | setTimeout(resolve, 100, 'two'); 82 | }); 83 | 84 | Promise.race([promise1, promise2]).then((value) => { 85 | console.log(value); 86 | // Both resolve, but promise2 is faster 87 | }); 88 | // Expected output: "two" 89 | -------------------------------------------------------------------------------- /示例代码/BrowserCaches/03_indexDB/index.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | // 数据库版本号 5 | const version = 1; 6 | 7 | // 初始化数据库 8 | const db = new DB("db-learns", version, { students: "id" }); 9 | 10 | // 新增数据 11 | async function onAdd() { 12 | if (!_name.value || !_age.value || !_job.value || !_city.value) { 13 | _tips.textContent = "温馨提示:请完善信息"; 14 | return; 15 | } 16 | try { 17 | const id = await db.add("students", { 18 | id: Date.now().toString(), 19 | name: _name.value, 20 | age: +_age.value, 21 | job: _job.value, 22 | city: _city.value, 23 | }); 24 | console.log(`新增成功,ID:${id}`); 25 | _tips.textContent = "新增成功!"; 26 | } catch (error) { 27 | console.error("新增失败:", error); 28 | _tips.textContent = "新增失败!"; 29 | } 30 | } 31 | 32 | // 删除数据 33 | async function onDelete() { 34 | if (!_flag.value) { 35 | _tips.textContent = "温馨提示:请填写操作标识(ID)"; 36 | return; 37 | } 38 | try { 39 | const resp = await db.delete("students", _flag.value); 40 | console.log(`删除结果:${resp}`); 41 | _tips.textContent = "删除成功!"; 42 | } catch (error) { 43 | console.error("删除失败:", error); 44 | _tips.textContent = "删除失败!"; 45 | } 46 | } 47 | 48 | // 更新数据 49 | async function onPut() { 50 | if (!_name.value || !_age.value || !_job.value || !_city.value || !_flag.value) { 51 | _tips.textContent = "温馨提示:请完善信息"; 52 | return; 53 | } 54 | try { 55 | const id = await db.put("students", { 56 | id: _flag.value, 57 | name: _name.value, 58 | age: +_age.value, 59 | job: _job.value, 60 | city: _city.value, 61 | }); 62 | console.log(`更新成功,ID:${id}`); 63 | _tips.textContent = "更新成功!"; 64 | } catch (error) { 65 | console.error("更新失败:", error); 66 | _tips.textContent = "更新失败!"; 67 | } 68 | } 69 | 70 | // 查询数据 71 | async function onGet() { 72 | if (!_flag.value) { 73 | _tips.textContent = "温馨提示:请填写操作标识(ID)"; 74 | return; 75 | } 76 | try { 77 | const resp = await db.get("students", _flag.value); 78 | console.log("查询结果:", resp); 79 | _tips.textContent = resp ? `查询成功:${JSON.stringify(resp)}` : "无此记录!"; 80 | } catch (error) { 81 | console.error("查询失败:", error); 82 | _tips.textContent = "查询失败!"; 83 | } 84 | } 85 | 86 | // 遍历数据 87 | async function onEach() { 88 | try { 89 | const resp = await db.each("students"); 90 | console.log("所有数据:", resp); 91 | _tips.textContent = "遍历成功,查看控制台日志!"; 92 | } catch (error) { 93 | console.error("遍历失败:", error); 94 | _tips.textContent = "遍历失败!"; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /第12章 定时器与延迟函数.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | 在实际开发中,我们可能需要延迟执行某个操作,比如页面加载后延迟 n 秒弹出广告,或者定期执行某些任务,比如轮询、倒计时等。这些场景可以通过 **setTimeout** 和 **setInterval** 来实现。 4 | 5 | # 延时函数 6 | 7 | ## 语法 8 | 9 | 语法形式: 10 | 11 | ```js 12 | setTimeout(callback, delay); 13 | ``` 14 | 15 | 语法解读: 16 | 17 | - `callback`:回调函数,在 delay 毫秒后执行 18 | - `delay`:延迟时间(单位:毫秒) 19 | 20 | ## 代码示例 21 | 22 | ```js 23 | console.log("Loading..."); 24 | setTimeout(() => console.log("Respect ~"), 2000); 25 | console.log("..."); 26 | /* 27 | Loading... 28 | ... 29 | Respect ~ */ 30 | ``` 31 | 32 | > **注意**:setTimeout 是异步执行的,不会阻塞线程。 33 | 34 | ## 取消延时 35 | 36 | 如果在延时执行前决定取消 setTimeout,可以使用 `clearTimeout()`: 37 | 38 | ```javascript 39 | console.log("Loading..."); 40 | const timer = setTimeout(() => console.log("Respect ~"), 2000); 41 | console.log("..."); 42 | clearTimeout(timer); // 取消延时 43 | ``` 44 | 45 | # 定时器 46 | 47 | ## 语法 48 | 49 | 语法形式: 50 | 51 | ```javascript 52 | setInterval(callback, interval); 53 | ``` 54 | 55 | 语法解读: 56 | 57 | - `callback`:每 interval 毫秒执行一次的函数 58 | - `interval`:时间间隔(单位:毫秒) 59 | 60 | ## 代码示例 61 | 62 | ```js 63 | let count = 10; 64 | const timer = setInterval(() => { 65 | console.log(--count); 66 | if (count === 0) { 67 | console.log("时间到!"); 68 | clearInterval(timer); // 清除定时器 69 | } 70 | }, 1000); 71 | ``` 72 | 73 | # 扩展应用 74 | 75 | ## 倒计时 76 | 77 | 思路: 78 | 79 | - 计算**目标时间**与**当前时间**的毫秒差 80 | 81 | - 转换为 天:时:分:秒 82 | 83 | 实现: 84 | 85 | ```js 86 | const countdown = (targetDate, callback) => { 87 | const format = (v) => v.toString().padStart(2, "0"); 88 | const timer = setInterval(() => { 89 | const ms = targetDate - new Date(); 90 | if (ms > 0) { 91 | const day = format(Math.floor(ms / 1000 / 60 / 60 / 24)); 92 | const hours = format(Math.floor((ms / 1000 / 60 / 60) % 24)); 93 | const minutes = format(Math.floor((ms / 1000 / 60) % 60)); 94 | const seconds = format(Math.floor((ms / 1000) % 60)); 95 | callback({ day, hours, minutes, seconds }); 96 | } else { 97 | clearInterval(timer); 98 | } 99 | }, 1000); 100 | }; 101 | 102 | // 使用示例 103 | countdown(new Date("2025-10-01"), ({ day, hours, minutes, seconds }) => { 104 | console.log(`距离2023年国庆还有 ${day}天 ${hours}时 ${minutes}分 ${seconds}秒`); 105 | }); 106 | ``` 107 | 108 | ## 函数防抖(Debounce) 109 | 110 | ### 概念 111 | 112 | 高频事件触发 n 秒后才执行函数,如果 n 秒内再次触发,则重新计时。 113 | 114 | ### 应用场景 115 | 116 | - **搜索输入框**:用户停止输入 n 秒后才请求接口 117 | - **窗口大小调整**:用户停止拖拽 n 秒后重新渲染 118 | 119 | ### 实现 120 | 121 | 思路:每次触发事件时都取消之前的延时调用方法 122 | 123 | ```js 124 | const debounce = (callback, delay = 500) => { 125 | let timer; 126 | return (...args) => { 127 | clearTimeout(timer); 128 | timer = setTimeout(() => callback.apply(this, args), delay); 129 | }; 130 | }; 131 | 132 | // 使用示例 133 | document.querySelector("input").oninput = debounce(() => { 134 | console.log("__Search__"); 135 | }, 800); 136 | ``` 137 | 138 | ## 函数节流 139 | 140 | ### 概念 141 | 142 | 高频事件触发时,每 n 秒内只执行一次。 143 | 144 | ### 应用场景 145 | 146 | - **滚动事件(onscroll)**:避免过度触发影响性能 147 | - **窗口调整(onresize)**:避免频繁执行 148 | 149 | ### 3.3. 实现 150 | 151 | 思路:每次触发事件时都判断当前是否有等待执行的延时函数 152 | 153 | ```js 154 | const throttle = (callback, delay = 500) => { 155 | // 1. 设置一个开关 156 | let isOn = true; 157 | return (...args) => { 158 | // 2. 如果当前正在执行某个任务,则忽略 159 | if (!isOn) return; 160 | // 3. 更新开关状态 161 | isOn = false; 162 | // 4. 启用定时器 163 | setTimeout(() => { 164 | callback.apply(this, args); 165 | isOn = true; 166 | }, delay); 167 | }; 168 | }; 169 | 170 | // 使用示例 171 | window.onresize = throttle((event) => { 172 | console.log(event.target.innerWidth, event.target.innerHeight); 173 | }, 1000); 174 | ``` 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /示例代码/BrowserCaches/01_Cookie/Cookies.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Lee 3 | * @Date: 2022-12-05 09:52:11 4 | * @LastEditors: Lee 5 | * @LastEditTime: 2023-05-04 14:41:12 6 | * @Description: 7 | */ 8 | 9 | /*\ 10 | |*| 11 | |*| :: cookies.js :: 12 | |*| 13 | |*| A complete cookies reader/writer framework with full unicode support. 14 | |*| 15 | |*| https://developer.mozilla.org/zh-CN/docs/Web/API/Document/cookie 16 | |*| 17 | |*| This framework is released under the GNU Public License, version 3 or later. 18 | |*| http://www.gnu.org/licenses/gpl-3.0-standalone.html 19 | |*| 20 | |*| Syntaxes: 21 | |*| 22 | |*| * docCookies.setItem(name, value[, end[, path[, domain[, secure]]]]) 23 | |*| * docCookies.getItem(name) 24 | |*| * docCookies.removeItem(name[, path], domain) 25 | |*| * docCookies.hasItem(name) 26 | |*| * docCookies.keys() 27 | |*| 28 | \*/ 29 | 30 | class DocCookies { 31 | /** 32 | * 得到Cookie 33 | * 读取一个 cookie。如果 cookie 不存在返回null。 34 | * @param {string} name 读取的 cookie 名。 35 | * @returns 36 | */ 37 | static getItem(name) { 38 | return ( 39 | decodeURIComponent( 40 | document.cookie.replace( 41 | new RegExp( 42 | '(?:(?:^|.*;)\\s*' + 43 | encodeURIComponent(name).replace(/[-.+*]/g, '\\$&') + 44 | '\\s*\\=\\s*([^;]*).*$)|^.*$' 45 | ), 46 | '$1' 47 | ) 48 | ) || null 49 | ); 50 | } 51 | 52 | /** 53 | * 写入Cookie 54 | * 创建或覆盖一个 cookie 55 | * @param {string} name 要创建或覆盖的 cookie 的名字 56 | * @param {any} value cookie 的值 57 | * @param {any} expires 过期时间,例如一年为 60*60*24*365(可选) 58 | * @param {string} path 存储路径,默认为当前文档位置的路径(可选) 59 | * @param {string} domain 存储域名,默认为当前文档位置的路径的域名部分(可选) 60 | * @param {boolean} secure cookie 只会被 https 传输(可选) 61 | * @returns 62 | */ 63 | static setItem(name, value, expires, path, domain, secure) { 64 | if (!name || /^(?:expires|max\-age|path|domain|secure)$/i.test(name)) { 65 | return false; 66 | } 67 | var sExpires = ''; 68 | if (expires) { 69 | switch (expires.constructor) { 70 | case Number: 71 | sExpires = 72 | expires === Infinity 73 | ? '; expires=Fri, 31 Dec 9999 23:59:59 GMT' 74 | : '; max-age=' + expires; 75 | break; 76 | case String: 77 | sExpires = '; expires=' + expires; 78 | break; 79 | case Date: 80 | sExpires = '; expires=' + expires.toUTCString(); 81 | break; 82 | } 83 | } 84 | document.cookie = 85 | encodeURIComponent(name) + 86 | '=' + 87 | encodeURIComponent(value) + 88 | sExpires + 89 | (domain ? '; domain=' + domain : '') + 90 | (path ? '; path=' + path : '') + 91 | (secure ? '; secure' : ''); 92 | return true; 93 | } 94 | 95 | /** 96 | * 移除Cookie 97 | * 删除一个 cookie 98 | * @param {string} name 要移除的 cookie 名 99 | * @param {string} path 存储路径,默认为当前文档位置的路径(可选) 100 | * @param {string} domain 存储域名,默认为当前文档位置的路径的域名部分(可选) 101 | * @returns 102 | */ 103 | static removeItem(name, path, domain) { 104 | if (!name || !this.hasItem(name)) { 105 | return false; 106 | } 107 | document.cookie = 108 | encodeURIComponent(name) + 109 | '=; expires=Thu, 01 Jan 1970 00:00:00 GMT' + 110 | (domain ? '; domain=' + domain : '') + 111 | (path ? '; path=' + path : ''); 112 | return true; 113 | } 114 | 115 | /** 116 | * 检测 Cookie 117 | * 检查一个 cookie 是否存在 118 | * @param {string} name 要检查的 cookie 名 119 | * @returns 120 | */ 121 | static hasItem(name) { 122 | return new RegExp( 123 | '(?:^|;\\s*)' + 124 | encodeURIComponent(name).replace(/[-.+*]/g, '\\$&') + 125 | '\\s*\\=' 126 | ).test(document.cookie); 127 | } 128 | 129 | /** 130 | * 得到所有 cookie 的列表 131 | * @returns 132 | */ 133 | static keys() { 134 | var aKeys = document.cookie 135 | .replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, '') 136 | .split(/\s*(?:\=[^;]*)?;\s*/); 137 | for (var nIdx = 0; nIdx < aKeys.length; nIdx++) { 138 | aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); 139 | } 140 | return aKeys; 141 | } 142 | } 143 | 144 | window.docCookies = DocCookies; 145 | -------------------------------------------------------------------------------- /第15章 异常处理.md: -------------------------------------------------------------------------------- 1 | # Errow 2 | 3 | 在 JavaScript 解析或执行过程中,一旦发生错误,引擎就会抛出一个错误对象。JavaScript 原生提供了 Error 构造函数,所有抛出的错误都是这个构造函数的实例。 4 | 5 | **创建 Error 实例** 6 | 7 | Error 构造函数接受一个参数,表示错误提示信息,可以从实例的 message 属性读取该信息。 8 | 9 | ```javascript 10 | const err = new Error("Validation failed!"); 11 | console.log(err.message); 12 | // → "Validation failed!" 13 | ``` 14 | 15 | # 原生错误类型 16 | 17 | Error 对象是 JavaScript 中最基本的错误类型,在其基础上,JavaScript 还定义了 6 种派生错误类型: 18 | 19 | 1. SyntaxError:语法错误 20 | 21 | 当 JavaScript 代码违反语法规则时,会抛出 SyntaxError。 22 | 23 | ```js 24 | const 1a = 10; 25 | // ❌ Uncaught SyntaxError: Unexpected token '1' 26 | 27 | if (true) { 28 | console.log('Hi); 29 | } 30 | // ❌ Uncaught SyntaxError: Invalid or unexpected token 31 | ``` 32 | 33 | 2. ReferenceError:引用错误 34 | 35 | 当访问的变量未定义或不可用时,会抛出 ReferenceError。 36 | 37 | ```js 38 | console.log(foo); 39 | // ❌ Uncaught ReferenceError: foo is not defined 40 | ``` 41 | 42 | 3. TypeError:类型错误 43 | 44 | 当对变量执行不适当的操作(例如调用 undefined 变量为函数)时,会抛出 TypeError。 45 | 46 | ```js 47 | const bar = new 'Hello'; 48 | // ❌ Uncaught TypeError: "Hello" is not a constructor 49 | 50 | const foo = {}; 51 | foo.test(); 52 | // ❌ Uncaught TypeError: foo.test is not a function 53 | ``` 54 | 55 | 4. RangeError:范围错误 56 | 57 | 当值超出允许的范围时,会抛出 RangeError。 58 | 59 | ```js 60 | function recursive() { 61 | return recursive(); 62 | } 63 | recursive(); 64 | // ❌ Uncaught RangeError: Maximum call stack size exceeded 65 | ``` 66 | 67 | 5. URIError:URI 处理错误 68 | 69 | 当全局 URI 处理函数(如 decodeURI、encodeURI)传入不正确的参数时,会抛出 URIError。 70 | 71 | ```js 72 | decodeURI('%'); 73 | // ❌ Uncaught URIError: URI malformed 74 | ``` 75 | 76 | 6. EvalError:`eval()` 函数中的错误 77 | 78 | 在 `eval()` 相关操作中,如果出现错误,可能会抛出 EvalError(现代浏览器基本不会抛出该错误)。 79 | 80 | # 异常处理方案 81 | 82 | ## throw 83 | 84 | throw 语句用于手动抛出异常,当程序运行过程中遇到无法继续执行的错误时,可以抛出异常中断程序执行,并提示错误信息。 85 | 86 | ```javascript 87 | throw new Error("异常提示信息"); 88 | throw "异常提示信息"; // 也可以抛出字符串,但不推荐 89 | ``` 90 | 91 | **console.assert()** 92 | 93 | `console.assert(condition, message)` 允许根据条件是否满足来输出异常信息,但不会中断程序执行。 94 | 95 | ```javascript 96 | const age = 12; 97 | console.assert(age > 18, "未满18岁!"); // 控制台输出:Assertion failed: 未满18岁! 98 | ``` 99 | 100 | ## try…catch 捕获异常 101 | 102 | try...catch 语句用于捕获和处理可能抛出的异常,如果 try 块中的代码抛出异常,则会跳转到 catch 块执行相应的处理逻辑。 103 | 104 | ```javascript 105 | try { 106 | alertt("Hello, World!"); // 语法错误 107 | } catch (err) { 108 | console.error("错误警告:" + err.message); 109 | } 110 | ``` 111 | 112 | > **注意**:try...catch 只能捕获同步代码的错误,无法捕获异步代码中的异常(如 setTimeout、Promise 等)。 113 | 114 | ## finally 代码块 115 | 116 | 无论 try 代码块是否抛出异常,finally 代码块都会执行,常用于资源释放或收尾操作。 117 | 118 | ```javascript 119 | try { 120 | console.log("执行 try 代码块"); 121 | throw new Error("异常发生"); 122 | } catch (err) { 123 | console.error("捕获错误:" + err.message); 124 | } finally { 125 | console.log("无论是否发生异常,都会执行 finally 代码块"); 126 | } 127 | ``` 128 | 129 | ## Promise.catch() 处理异步异常 130 | 131 | 在 Promise 对象中,可以使用 .catch() 方法捕获 reject 产生的异常。 132 | 133 | ```js 134 | fetch('invalid-url') 135 | .then(response => response.json()) 136 | .catch(error => console.error("捕获到异常:", error)); 137 | ``` 138 | 139 | ## Window.onerror 捕获全局异常 140 | 141 | window.onerror 可以用于捕获未被 try...catch 处理的异常(仅适用于同步代码)。 142 | 143 | ```js 144 | window.onerror = function(message, source, lineno, colno, error) { 145 | console.error("全局错误:", message, "at", source, ":", lineno, ":", colno); 146 | return true; // 返回 true 以防止默认的错误提示 147 | }; 148 | 149 | throw new Error("测试全局错误捕获"); 150 | ``` 151 | 152 | > **注意**:window.onerror 不能捕获 try...catch 内部已处理的错误。 153 | 154 | ## unhandledrejection 捕获未处理的 Promise 异常 155 | 156 | 对于 Promise 产生但未 catch 处理的错误,可以使用 unhandledrejection 事件捕获。 157 | 158 | ```js 159 | window.addEventListener("unhandledrejection", event => { 160 | console.error("捕获到未处理的 Promise 错误:", event.reason); 161 | }); 162 | 163 | Promise.reject("未处理的异常"); 164 | ``` 165 | 166 | # 最佳实践 167 | 168 | 1. **使用 try...catch 处理同步代码异常** 169 | 170 | ```js 171 | try { 172 | riskyOperation(); 173 | } catch (error) { 174 | console.error("发生错误:", error.message); 175 | } 176 | ``` 177 | 178 | 2. **在 Promise 中使用 .catch() 处理异步异常** 179 | 180 | ```js 181 | fetchData().catch(error => console.error("请求失败:", error)); 182 | ``` 183 | 184 | 3. **使用 finally 进行资源清理** 185 | 186 | ```js 187 | function processData() { 188 | try { 189 | console.log("正在处理数据..."); 190 | } finally { 191 | console.log("清理操作完成"); 192 | } 193 | } 194 | processData(); 195 | ``` 196 | 197 | 4. **使用 window.onerror 捕获未处理的同步错误** 198 | 199 | ```js 200 | window.onerror = function(message, source, lineno, colno, error) { 201 | console.error("全局错误:", message); 202 | }; 203 | ``` 204 | 205 | 5. **使用 window.addEventListener("unhandledrejection", callback) 处理未捕获的 Promise 错误** 206 | 207 | ```js 208 | window.addEventListener("unhandledrejection", event => { 209 | console.error("未处理的 Promise 错误:", event.reason); 210 | }); 211 | ``` 212 | 213 | 6. **避免 throw 字符串,使用 Error 对象** 214 | 215 | ```js 216 | throw new Error("请提供有效的参数"); 217 | ``` 218 | -------------------------------------------------------------------------------- /第11章 BOM.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | > The Browser Object Model(BOM) allows JavaScript to "talk to" the browser. 4 | 5 | **BOM**(**B**rowers **O**bject **M**odel,浏览器对象模型)是浏览器为js提供的一个API(**A**pplication **P**rogramming **I**nterface,应用编程接口),所以它不是原生js提供的。通过BOM我们可以访问和设置浏览器的一些属性和函数。 6 | 7 | BOM 的大部分操作都依赖于全局对象 window,由于它是全局对象,因此访问其子对象的属性和方法时可以省略 window,例如 window.console.log() 可简写为 console.log()。 8 | 9 | ## window 对象的主要子对象 10 | 11 | - **document**:文档对象 12 | - **frames**:浏览器的框架对象 13 | - **history**:浏览器历史记录对象 14 | - **location**:当前页面的位置信息 15 | - **navigator**:浏览器信息对象 16 | - **screen**:屏幕信息对象 17 | 18 | 此外,window 还提供了一些常见的方法,例如: 19 | 20 | - alert()、open()、close() 21 | - setTimeout()、clearTimeout() 22 | - setInterval()、clearInterval() 23 | 24 | 虽然 BOM 没有官方标准,但随着 Web 发展,各大浏览器厂商已在许多 BOM 相关功能上达成共识,使得大多数现代浏览器都能支持常见的 BOM 操作。 25 | 26 | ## window 对象的多种表示方式 27 | 28 | 在全局环境下,以下变量都指向 window: 29 | 30 | - **window** 31 | - **this** 32 | - **self** 33 | - **frames** 34 | 35 | 在 Chrome 控制台输入 window.(注意最后的 .),可以查看 window 下的所有属性和方法。由于其包含大量内容,掌握全部并不现实,我们只需了解常用部分即可。 36 | 37 | # 窗口属性 * 38 | 39 | 浏览器窗口的相关属性对于响应式设计至关重要,尤其是在支持从智能手表(160×160)到 4K 屏幕(4096×2160)的设备时,合理调整布局是前端开发中的难点。除了 CSS 框架,我们也可以借助 BOM 提供的窗口属性进行适配。 40 | 41 | 浏览器窗口相关的主要属性有以下(数值表示的单位统一为像素): 42 | 43 | ![](./IMGS/rect.jpeg) 44 | 45 | 1. innerWidth、innerHeight:浏览器视口的宽高(包含滚动条) 46 | 2. outerWidth、outerHeight:浏览器窗口的整体宽高 47 | 3. pageXOffset、pageYOffset:页面滚动的偏移量(等价于 scrollLeft 和 scrollTop) 48 | 4. screenX、screenY(或 screenLeft、screenTop):浏览器窗口相对于屏幕的坐标 49 | 50 | > **注意**:innerWidth、innerHeight 等属性都包含滚动条的宽度,且这些属性是只读的,会随窗口大小变化而动态更新。 51 | 52 | 如果要隐藏滚动条,可以使用以下 CSS 代码: 53 | 54 | ```css 55 | body::-webkit-scrollbar { 56 | display: none; 57 | } 58 | ``` 59 | 60 | # 窗口方法 * 61 | 62 | **基本窗口操作** 63 | 64 | - `open(url?, target?)`:打开新窗口 65 | - `close()`:关闭当前窗口 66 | 67 | **其他窗口方法** 68 | 69 | - `print()`:打印当前页面 70 | - `getSelection() `:获取选中的文本 71 | 72 | 【实例 1】获取选中内容 73 | 74 | ```html 75 |
76 |
曾经沧海难为水,除却巫山不是云。
77 |
取次花丛懒回顾,半缘修道半缘君。
78 |
79 |

您选中的内容是:

80 | ``` 81 | 82 | ```js 83 | const oDiv = document.querySelector('#selBox'); 84 | const oSel = document.querySelector('#selRes'); 85 | oDiv.onmouseup = function() { 86 | // 获取选中对象 87 | var selObj = getSelection(); 88 | // 将选中对象转为字符串 89 | var selTxt = selObj.toString(); 90 | oSel.innerHTML = "您选中的内容是:“" + selTxt + "”"; 91 | } 92 | ``` 93 | 94 | 示例中使用 mouseup 事件来触发选中文本的获取。 95 | 96 | # 窗口对象 97 | 98 | ## 1. document 99 | 100 | document 主要用于操作 DOM,具体内容可参考标准 DOM 操作相关文档。 101 | 102 | ## 2. frames 103 | 104 | 在Ajax不盛行的年代,\