JavaScript 简介 JavaScript(JS)是一种具有函数优先特性的轻量级、解释型或者说即时编译型的编程语言。在 Web 网页中,JavaScript 代码可以修改 HTML 内容、样式和结构,响应用户操作,以及与服务器进行交互。除此之外,JavaScript 还被应用到了很多非浏览器环境中,例如 Node.js。进一步说,JavaScript 是一种基于原型、多范式、单线程的动态语言,并且支持面向对象、命令式和声明式(如函数式编程)风格。
JavaScript 基础 变量和数据类型 JavaScript 中有三种声明变量的方式:var
、let
和 const
。
变量声明 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var name = "JavaScript" ;var name = "JS" ; let age = 25 ;age = 26 ; const PI = 3.14159 ;const person = { name : "Alice" , age : 30 };person.age = 31 ;
数据类型 JavaScript 有8种数据类型:
基本数据类型(原始类型):
String(字符串)
Number(数字)
Boolean(布尔)
Undefined(未定义)
Null(空)
Symbol(符号,ES6新增)
BigInt(大整数,ES2020新增)
引用数据类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 let str1 = "Hello" ;let str2 = 'World' ;let str3 = `Template: ${str1} ${str2} ` ; let num1 = 100 ; let num2 = 3.14 ; let num3 = 0xff ; let num4 = 3e8 ; let num5 = NaN ; let num6 = Infinity ; let isActive = true ;let isLoading = false ;let unknown;console .log (unknown); let empty = null ;let sym1 = Symbol ('id' );let sym2 = Symbol ('id' );console .log (sym1 === sym2); let bigNumber = 9007199254740991n ; let person = { name : "张三" , age : 30 , isStudent : false , greet : function ( ) { return `你好,我是${this .name} ` ; } }; let colors = ["红" , "绿" , "蓝" ];let mixed = [1 , "text" , true , null , {key : "value" }, [1 , 2 ]];function add (a, b ) { return a + b; } const multiply = (a, b ) => a * b;
类型检查与转换 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 console .log (typeof "Hello" ); console .log (typeof 123 ); console .log (typeof true ); console .log (typeof undefined ); console .log (typeof null ); console .log (typeof {}); console .log (typeof []); console .log (typeof function ( ){}); let num = Number ("123" ); let str = String (456 ); let bool = Boolean (1 ); let result1 = "3" + 2 ; let result2 = "3" - 2 ; let result3 = "3" * "2" ;
变量作用域 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 let globalVar = "我是全局变量" ;function testScope ( ) { let functionVar = "我是函数变量" ; if (true ) { let blockVar = "我是块级变量(let)" ; var varInBlock = "我是用var声明的变量" ; console .log (globalVar); console .log (functionVar); console .log (blockVar); } console .log (globalVar); console .log (functionVar); console .log (varInBlock); } testScope ();console .log (globalVar);
解构赋值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 let [a, b, c] = [1 , 2 , 3 ];console .log (a, b, c); let {name, age} = {name : "李四" , age : 25 };console .log (name, age); let [x = 0 , y = 0 ] = [5 ];console .log (x, y); let m = 10 , n = 20 ;[m, n] = [n, m]; console .log (m, n); let [first, , third] = [1 , 2 , 3 ];console .log (first, third); let [head, ...tail] = [1 , 2 , 3 , 4 ];console .log (head, tail);
运算符 JavaScript 提供了多种操作符用于执行不同类型的操作。
算术运算符 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 let sum = 10 + 5 ; let diff = 10 - 5 ; let product = 10 * 5 ; let quotient = 10 / 5 ; let remainder = 10 % 3 ;let exp = 2 ** 3 ; let count = 5 ;count++; ++count; count--; --count; let a = 5 ;let b = a++; let c = 5 ;let d = ++c;
赋值运算符 1 2 3 4 5 6 7 8 9 10 let x = 10 ;x += 5 ; x -= 3 ; x *= 2 ; x /= 4 ; x %= 4 ; x **= 2 ;
比较运算符 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 console .log (5 == 5 ); console .log (5 == "5" ); console .log (5 === "5" ); console .log (5 != 8 ); console .log (5 != "5" ); console .log (5 !== "5" ); console .log (5 > 3 ); console .log (5 >= 5 ); console .log (5 < 10 ); console .log (5 <= 4 ); console .log (null == undefined ); console .log (null === undefined ); console .log (NaN == NaN ); console .log (NaN === NaN );
逻辑运算符 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 console .log (true && true ); console .log (true && false ); console .log (false && true ); console .log (false && false ); console .log (true || true ); console .log (true || false ); console .log (false || true ); console .log (false || false ); console .log (!true ); console .log (!false ); console .log (false && someFunction ()); console .log (true || someFunction ()); console .log ("Hello" && "World" ); console .log ("" && "World" ); console .log ("Hello" || "World" ); console .log ("" || "World" );
条件(三元)运算符 1 2 3 4 5 6 7 8 9 let age = 20 ;let status = age >= 18 ? "成年" : "未成年" ;console .log (status); let score = 85 ;let grade = score >= 90 ? "A" : (score >= 80 ? "B" : (score >= 70 ? "C" : "D" ));console .log (grade);
其他运算符 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 console .log (typeof 42 ); console .log (typeof "hello" ); let arr = [];console .log (arr instanceof Array ); let car = {make : "Toyota" , model : "Corolla" };console .log ("make" in car); console .log ("color" in car); let user = null ;let displayName = user ?? "Guest" ; let obj = {outer : {inner : {value : 42 }}};console .log (obj?.outer ?.inner ?.value ); console .log (obj?.outer ?.missing ?.value );
控制流 条件语句 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 let temperature = 25 ;if (temperature > 30 ) { console .log ("天气炎热" ); } else if (temperature > 20 ) { console .log ("天气适宜" ); } else { console .log ("天气凉爽" ); } let day = "星期三" ;switch (day) { case "星期一" : console .log ("开始工作" ); break ; case "星期三" : console .log ("周中了" ); break ; case "星期五" : console .log ("周末来临" ); break ; default : console .log ("普通的一天" ); break ; }
循环语句 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 for (let i = 0 ; i < 5 ; i++) { console .log (`计数: ${i} ` ); } let count = 0 ;while (count < 5 ) { console .log (`while计数: ${count} ` ); count++; } let num = 0 ;do { console .log (`do-while计数: ${num} ` ); num++; } while (num < 5 ); let person = {name : "李华" , age : 25 , job : "工程师" };for (let key in person) { console .log (`${key} : ${person[key]} ` ); } let colors = ["红" , "绿" , "蓝" ];for (let color of colors) { console .log (color); } for (let i = 0 ; i < 10 ; i++) { if (i === 3 ) continue ; if (i === 7 ) break ; console .log (i); }
函数 函数声明与表达式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 function greet (name ) { return `你好,${name} !` ; } console .log (greet ("小明" )); const sayHello = function (name ) { return `你好,${name} !` ; }; console .log (sayHello ("小红" )); const welcome = (name ) => `欢迎,${name} !` ;console .log (welcome ("小张" )); function add (a, b = 0 ) { return a + b; } console .log (add (5 , 3 )); console .log (add (5 )); function sum (...numbers ) { return numbers.reduce ((total, num ) => total + num, 0 ); } console .log (sum (1 , 2 , 3 , 4 ));
作用域和闭包 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function createCounter ( ) { let count = 0 ; return function ( ) { count += 1 ; return count; }; } const counter = createCounter ();console .log (counter ()); console .log (counter ()); console .log (counter ());
this关键字 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 const user = { name : "张三" , sayHi ( ) { console .log (`你好,我是${this .name} ` ); } }; user.sayHi (); function showThis ( ) { console .log (this ); } showThis ();const obj = { name : "李四" , regularFunction : function ( ) { console .log (this .name ); const arrowFunction = ( ) => { console .log (this .name ); }; arrowFunction (); } }; obj.regularFunction ();
对象和数组 对象基础 对象是JavaScript中的复合数据类型,用于存储多个相关数据和功能的集合。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 const person = { firstName : "张" , lastName : "三" , age : 25 , isStudent : false , fullName ( ) { return this .firstName + this .lastName ; } }; console .log (person.firstName ); console .log (person["lastName" ]); console .log (person.fullName ()); person.email = "zhangsan@example.com" ; person.age = 26 ; delete person.isStudent ;console .log ("email" in person); console .log (person.hasOwnProperty ("age" )); for (let key in person) { console .log (`${key} : ${person[key]} ` ); } const keys = Object .keys (person); const values = Object .values (person); const entries = Object .entries (person);
对象方法和构造函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 function Person (firstName, lastName, age ) { this .firstName = firstName; this .lastName = lastName; this .age = age; this .fullName = function ( ) { return this .firstName + this .lastName ; }; } const person1 = new Person ("李" , "四" , 30 );const person2 = new Person ("王" , "五" , 25 );console .log (person1.fullName ()); console .log (person2.age ); const personProto = { greeting ( ) { return `你好,我是${this .name} ` ; } }; const student = Object .create (personProto);student.name = "小明" ; console .log (student.greeting ());
数组详解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 let fruits = ["苹果" , "香蕉" , "橙子" ];let numbers = new Array (1 , 2 , 3 , 4 , 5 );let mixed = [1 , "文本" , true , {name : "对象" }, [1 , 2 ]];console .log (fruits[0 ]); console .log (fruits[fruits.length - 1 ]); fruits[1 ] = "梨" ; console .log (fruits); fruits.push ("葡萄" ); let lastFruit = fruits.pop (); let firstFruit = fruits.shift (); fruits.unshift ("草莓" ); let index = fruits.indexOf ("梨" ); let includesOrange = fruits.includes ("橙子" ); let nums = [1 , 2 , 3 , 4 , 5 ];let doubled = nums.map (num => num * 2 ); let evens = nums.filter (num => num % 2 === 0 ); let sum = nums.reduce ((total, num ) => total + num, 0 ); nums.forEach (num => console .log (num)); let letters = ["c" , "a" , "d" , "b" ];letters.sort (); nums.sort ((a, b ) => b - a); let sliced = nums.slice (1 , 3 ); let removed = nums.splice (1 , 2 ); let combined = [1 , 2 ].concat ([3 , 4 ], [5 ]); let combined2 = [...[1 , 2 ], ...[3 , 4 ], ...[5 ]]; let flattened = [1 , [2 , [3 , 4 ]]].flat (2 );
ES6+ 新特性 ES6(ECMAScript 2015)及后续版本引入了许多重要的JavaScript语言特性。
箭头函数详解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 const add = (a, b ) => a + b;const square = x => x * x;const greet = name => { const message = `你好,${name} !` ; return message; }; const person = { name : "张三" , sayHiLater : function ( ) { setTimeout (function ( ) { console .log (`你好,我是${this .name} ` ); }, 1000 ); }, sayHiLaterArrow : function ( ) { setTimeout (() => { console .log (`你好,我是${this .name} ` ); }, 1000 ); } };
模板字符串 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 const name = "JavaScript" ;const greeting = `Hello, ${name} !` ;const multiLine = ` 这是第一行 这是第二行 这是第三行 ` ;const a = 10 , b = 5 ;const result = `${a} + ${b} = ${a + b} ` ;function highlight (strings, ...values ) { return strings.reduce ((result, str, i ) => { const value = values[i] || '' ; return `${result} ${str} <span class="highlight">${value} </span>` ; }, '' ); } const user = "张三" ;const role = "管理员" ;const html = highlight`用户 ${user} 是 ${role} ` ;
解构赋值详解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const [first, ...rest] = [1 , 2 , 3 , 4 ]; const [a, , c] = [1 , 2 , 3 ]; const [x = 0 , y = 0 ] = []; const { name, age = 20 } = { name : "李四" }; const { name : fullName } = { name : "王五" }; const { a : { b } } = { a : { b : 'nested' } }; function printPersonInfo ({ name, age = 18 , city = "北京" } ) { console .log (`${name} , ${age} 岁, 来自${city} ` ); } printPersonInfo ({ name : "赵六" , age : 25 });
扩展运算符 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 const arr1 = [1 , 2 , 3 ];const arr2 = [...arr1, 4 , 5 ]; function sum (a, b, c ) { return a + b + c; } const numbers = [1 , 2 , 3 ];console .log (sum (...numbers)); const obj1 = { a : 1 , b : 2 };const obj2 = { ...obj1, c : 3 , b : 3 }; const originalArray = [1 , 2 , 3 ];const copyArray = [...originalArray]; const originalObject = { a : 1 , b : { c : 2 } };const copyObject = { ...originalObject };
类(Class) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class Person { constructor (name, age ) { this .name = name; this .age = age; } sayHello ( ) { return `你好,我是${this .name} ,${this .age} 岁` ; } static createAnonymous ( ) { return new Person ("无名氏" , 0 ); } } const person = new Person ("张三" , 30 );console .log (person.sayHello ()); const anonymous = Person .createAnonymous ();class Student extends Person { constructor (name, age, grade ) { super (name, age); this .grade = grade; } sayHello ( ) { return `${super .sayHello()} ,我在${this .grade} 年级` ; } study ( ) { return `${this .name} 正在学习` ; } } const student = new Student ("小明" , 15 , "初三" );console .log (student.sayHello ());
模块系统 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 export const PI = 3.14159 ;export function add (a, b ) { return a + b; } export function multiply (a, b ) { return a * b; } export default class Calculator { add (a, b ) { return a + b; } } import Calculator , { PI , add, multiply as mult } from './math.js' ;console .log (PI ); console .log (add (2 , 3 )); console .log (mult (2 , 3 )); const calc = new Calculator ();console .log (calc.add (5 , 3 )); import * as MathUtils from './math.js' ;console .log (MathUtils .PI ); console .log (MathUtils .add (2 , 3 ));
异步编程 回调函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 function fetchData (callback ) { setTimeout (() => { const data = { name : "示例数据" , timestamp : Date .now () }; callback (null , data); }, 1000 ); } fetchData ((error, data ) => { if (error) { console .error ("发生错误:" , error); return ; } console .log ("数据:" , data); fetchData ((error, moreData ) => { if (error) { console .error ("发生错误:" , error); return ; } console .log ("更多数据:" , moreData); fetchData ((error, evenMoreData ) => { }); }); });
Promise 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 function fetchData ( ) { return new Promise ((resolve, reject ) => { setTimeout (() => { const success = Math .random () > 0.3 ; if (success) { resolve ({ name : "示例数据" , timestamp : Date .now () }); } else { reject (new Error ("无法获取数据" )); } }, 1000 ); }); } fetchData () .then (data => { console .log ("数据:" , data); return fetchData (); }) .then (moreData => { console .log ("更多数据:" , moreData); return fetchData (); }) .then (evenMoreData => { console .log ("更多更多数据:" , evenMoreData); }) .catch (error => { console .error ("发生错误:" , error); }) .finally (() => { console .log ("请求完成" ); }); Promise .all ([fetchData (), fetchData (), fetchData ()]) .then (resultsArray => { console .log ("所有请求完成:" , resultsArray); }) .catch (error => { console .error ("至少一个请求失败:" , error); }); Promise .race ([fetchData (), fetchData (), fetchData ()]) .then (firstResult => { console .log ("最快的请求结果:" , firstResult); }) .catch (error => { console .error ("最快的请求失败:" , error); });
Async/Await 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 async function fetchAllData ( ) { try { const data = await fetchData (); console .log ("第一组数据:" , data); const moreData = await fetchData (); console .log ("第二组数据:" , moreData); const [result1, result2] = await Promise .all ([ fetchData (), fetchData () ]); console .log ("并行结果:" , result1, result2); return "所有数据获取成功" ; } catch (error) { console .error ("处理数据时出错:" , error); throw error; } } fetchAllData () .then (message => console .log (message)) .catch (error => console .error ("最外层捕获:" , error)); (async () => { try { const result = await fetchAllData (); console .log (result); } catch (error) { console .error (error); } })();
DOM操作与浏览器API DOM选择与操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 const heading = document .getElementById ('main-heading' );const paragraphs = document .getElementsByTagName ('p' );const specialElements = document .getElementsByClassName ('special' );const firstButton = document .querySelector ('button' );const allLinks = document .querySelectorAll ('a.external' );heading.textContent = '新标题' ; heading.innerHTML = '新标题 <span>带HTML</span>' ; const img = document .querySelector ('img' );img.src = 'new-image.jpg' ; img.alt = '图片描述' ; img.setAttribute ('data-category' , 'nature' ); const category = img.getAttribute ('data-category' );img.dataset .category = 'nature' ; const category2 = img.dataset .category ;const element = document .querySelector ('.highlight' );element.style .color = 'red' ; element.style .fontSize = '20px' ; element.style .display = 'none' ; element.classList .add ('active' ); element.classList .remove ('hidden' ); element.classList .toggle ('visible' ); element.classList .contains ('active' ); const newParagraph = document .createElement ('p' );newParagraph.textContent = '这是新段落' ; document .body .appendChild (newParagraph);const container = document .querySelector ('.container' );container.insertBefore (newParagraph, container.firstChild ); container.removeChild (newParagraph); newParagraph.remove ();
事件处理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 const button = document .querySelector ('button' );button.addEventListener ('click' , function (event ) { console .log ('按钮被点击了!' ); console .log ('事件对象:' , event); event.preventDefault (); event.stopPropagation (); }); const input = document .querySelector ('input' );input.addEventListener ('input' , (e ) => { console .log ('输入值:' , e.target .value ); }); function handleClick ( ) { console .log ('处理点击' ); } button.addEventListener ('click' , handleClick); button.removeEventListener ('click' , handleClick); const list = document .querySelector ('ul' );list.addEventListener ('click' , (event ) => { if (event.target .tagName === 'LI' ) { console .log ('点击了列表项:' , event.target .textContent ); } }); document .addEventListener ('DOMContentLoaded' , () => { console .log ('DOM完全加载' ); }); window .addEventListener ('load' , () => { console .log ('页面完全加载,包括所有资源' ); }); window .addEventListener ('resize' , () => { console .log ('窗口大小改变' ); }); document .addEventListener ('scroll' , () => { console .log ('页面滚动' ); });
Fetch API 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 fetch ('https://api.example.com/data' ) .then (response => { if (!response.ok ) { throw new Error (`HTTP错误 ${response.status} ` ); } return response.json (); }) .then (data => { console .log ('数据:' , data); }) .catch (error => { console .error ('获取数据出错:' , error); }); fetch ('https://api.example.com/create' , { method : 'POST' , headers : { 'Content-Type' : 'application/json' , 'Authorization' : 'Bearer token123' }, body : JSON .stringify ({ name : '新项目' , description : '项目描述' }) }) .then (response => response.json ()) .then (data => console .log ('创建结果:' , data)) .catch (error => console .error ('错误:' , error)); async function fetchUserData (userId ) { try { const response = await fetch (`https://api.example.com/users/${userId} ` ); if (!response.ok ) { throw new Error (`HTTP错误 ${response.status} ` ); } const userData = await response.json (); return userData; } catch (error) { console .error ('获取用户数据失败:' , error); throw error; } } async function uploadFile (file ) { const formData = new FormData (); formData.append ('file' , file); try { const response = await fetch ('https://api.example.com/upload' , { method : 'POST' , body : formData }); return await response.json (); } catch (error) { console .error ('文件上传失败:' , error); throw error; } } const controller = new AbortController ();const { signal } = controller;fetch ('https://api.example.com/data' , { signal }) .then (response => response.json ()) .then (data => console .log ('数据:' , data)) .catch (error => { if (error.name === 'AbortError' ) { console .log ('请求被取消' ); } else { console .error ('错误:' , error); } }); setTimeout (() => controller.abort (), 5000 );
错误处理与调试 try…catch使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 try { const result = riskyOperation (); console .log ('操作成功:' , result); } catch (error) { console .error ('捕获到错误:' , error.message ); if (error instanceof TypeError ) { console .log ('类型错误' ); } else if (error instanceof ReferenceError ) { console .log ('引用错误' ); } } finally { console .log ('清理资源' ); } async function processData ( ) { try { const data = await fetchData (); const processed = await processResult (data); return processed; } catch (error) { console .error ('处理数据时出错:' , error); return { error : true , message : error.message }; } } class ValidationError extends Error { constructor (message, field ) { super (message); this .name = 'ValidationError' ; this .field = field; } } function validateUser (user ) { if (!user.name ) { throw new ValidationError ('名称不能为空' , 'name' ); } if (!user.email ) { throw new ValidationError ('邮箱不能为空' , 'email' ); } } try { validateUser ({ name : 'Alice' }); } catch (error) { if (error instanceof ValidationError ) { console .log (`字段 ${error.field} 验证失败: ${error.message} ` ); } else { console .error ('未知错误:' , error); } } window .addEventListener ('error' , (event ) => { console .error ('全局错误:' , event.error ); event.preventDefault (); }); window .addEventListener ('unhandledrejection' , (event ) => { console .warn ('未处理的Promise拒绝:' , event.reason ); event.preventDefault (); });
调试技巧 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 function complexFunction (a, b ) { let result = a * 2 ; result += b; return result * b; } function findBug (data ) { let processed = []; for (let i = 0 ; i < data.length ; i++) { if (data[i].value < 0 ) { debugger ; processed.push (data[i].value * -1 ); } else { processed.push (data[i].value ); } } return processed; } console .log ('普通信息' );console .info ('信息' ); console .warn ('警告' ); console .error ('错误' ); console .table ([ { name : '张三' , age : 25 }, { name : '李四' , age : 30 } ]); console .group ('分组标题' );console .log ('分组内的消息1' );console .log ('分组内的消息2' );console .groupEnd ();console .time ('操作耗时' );for (let i = 0 ; i < 1000000 ; i++) { } console .timeEnd ('操作耗时' ); function a ( ) { b (); }function b ( ) { c (); }function c ( ) { console .trace ('函数调用堆栈' ); }a ();
推荐的 JavaScript 学习资源 课程推荐:
W3Schools:🛫 MDN Web Docs:🛫
项目实践:FreeCodeCamp:🛫
❗❗❗ 学习重点 🤔:
基本语法和数据类型
变量声明 :var
、let
和 const
的区别及作用
变量提升现象与暂时性死区
全局变量与window对象的关系
何时使用const与let的最佳实践
块级作用域与函数作用域的实际应用场景
数据类型 :字符串、数字、布尔值、undefined、null、对象(Object)、数组(Array)、Symbol 和 BigInt
原始类型vs引用类型的内存模型
Symbol的实际应用场景与唯一性保证
BigInt处理大数字计算的使用方法
null与undefined的区别与应用场景
NaN的特性与isNaN/Number.isNaN的区别
类型转换 :隐式转换与显式转换(如 String()
, Number()
等)
强制类型转换的常见陷阱
运算符导致的隐式转换规则
parseInt/parseFloat与Number转换的区别
valueOf与toString方法在转换中的作用
操作符 :算术操作符、比较操作符、逻辑操作符、赋值操作符、三元运算符、位运算符等
位运算在实际开发中的高效应用
逻辑运算符短路求值的应用技巧
==与===的区别及何时使用
复合赋值操作符及其优化
控制流
条件语句 :if
、else
、switch
语句
条件表达式的真值与假值评估
switch语句与策略模式的结合
多重条件的优化方法
使用对象字面量替代switch语句
循环语句 :for
、while
、do...while
循环,for...in
、for...of
各种循环的性能比较与最佳使用场景
for…in遍历原型链问题及防范
for…of与迭代器协议的关系
无限循环的合理应用
跳出循环 :break
、continue
、return
标签语句与多层循环跳出
continue与循环优化
提前返回模式优化代码结构
函数与作用域
函数声明与表达式 :普通函数、匿名函数、命名函数表达式
函数声明提升vs函数表达式提升
立即执行函数表达式(IIFE)及其应用
命名函数表达式对调试的好处
高阶函数的概念与实践
箭头函数 :如何简化函数表达式,并理解它与普通函数的 this
指向不同
箭头函数没有arguments对象的解决方案
箭头函数实现对象方法的注意事项
隐式返回值的各种情况
何时不应使用箭头函数
作用域 :全局作用域、函数作用域、块级作用域
词法作用域与动态作用域的区别
作用域链的工作原理
模块作用域在ES模块中的应用
eval对作用域的影响
闭包 :函数可以”记住”并访问定义时的作用域
闭包在实际开发中的常见用例
闭包导致的内存泄漏及防范
工厂函数与闭包的关系
闭包与模块模式
this :理解 this
在不同情况下的指向(例如在函数内、对象方法内、箭头函数中等)
call/apply/bind方法对this的影响
构造函数中的this行为
严格模式vs非严格模式下this的区别
DOM事件处理程序中的this
对象与数组
对象 :如何创建对象、访问属性、方法、遍历对象(如 for...in
)
对象属性特性与Object.defineProperty
getter/setter方法定义与使用
对象原型链与继承机制
Object.create与原型继承
对象深拷贝与浅拷贝的实现
对象解构 :从对象中提取多个属性到变量
嵌套解构的复杂案例
解构时的默认值与重命名
解构与函数参数结合使用
解构失败的行为与处理
数组 :常用数组方法(push
、pop
、shift
、unshift
、map
、filter
、reduce
)
稀疏数组与密集数组的区别
reduce方法实现复杂数据处理
数组方法链式调用与性能
类数组对象转换为真数组
多维数组的操作技巧
数组解构 :从数组中提取多个元素到变量
剩余参数与数组解构结合
跳过某些元素的解构方法
解构赋值用于交换变量
嵌套数组解构的实际应用
对象与数组的迭代 :如 forEach
、map
、filter
等
数组方法的返回值与链式调用
迭代方法中的this参数使用
迭代方法与for循环的性能比较
自定义迭代器实现
ES6+ 新特性
解构赋值 :对象和数组的解构
复杂嵌套解构模式
解构用于API响应处理
解构与默认参数结合
函数参数解构的最佳实践
模板字符串 :使用反引号包围字符串,插入表达式
标签模板函数的高级应用
多行字符串处理与格式化
嵌套模板字符串的处理
转义序列的处理
扩展运算符 :用于对象和数组的合并与解构
多个对象合并时的属性覆盖规则
在函数参数中的应用
与解构赋值结合使用
实现浅拷贝的方法与限制
箭头函数 :简化函数声明,自动绑定 this
在回调函数中的优势
隐式返回对象字面量的语法
不适合使用箭头函数的场景
与事件处理函数结合使用
类(Class) :ES6 的面向对象编程,如何定义类与继承
私有字段与方法(#语法)
静态属性与静态方法
getter/setter在类中的应用
继承与super关键字的使用
混入模式实现多继承
Promise :处理异步操作的对象,如何链式调用(then
/catch
)以及捕获错误
Promise嵌套与扁平化
Promise.all/race/allSettled/any的区别
自定义Promise实现
微任务队列与事件循环的关系
Set 和 Map :新的数据结构,用于存储唯一值和键值对
WeakSet与WeakMap的特性与应用
实现高效的数据去重
Map与Object作为字典的对比
Set/Map的迭代方法
其他ES6+特性
Proxy与Reflect API的使用
装饰器语法与应用(Stage 3)
可选链操作符(?.)与空值合并(??)
顶层await的使用(ES2022)
私有类字段与方法
异步编程
回调函数 :理解回调的使用,及回调地狱问题
错误优先回调约定
异步回调与同步回调的区别
实现控制流程的各种回调模式
回调地狱的重构方法
Promise :如何创建和使用 Promise 来解决异步问题
Promise链中断的处理
并行Promise操作的实现方法
Promise错误处理的最佳实践
超时与竞态处理
async/await :通过 async
和 await
简化异步代码,使其看起来像同步代码
顺序执行vs并行执行
错误处理策略
与Promise混合使用
在循环中使用await的陷阱
错误处理 :如何通过 try/catch
捕获异步错误,确保代码的健壮性
全局错误处理
特定类型错误处理
错误传播与处理策略
自定义错误类型
其他异步模式
发布/订阅模式
生成器与异步迭代
可取消的异步操作
RxJS与响应式编程
模块化
模块化引入 :import
和 export
语法,如何将代码分割到不同文件并导入使用
命名导出vs默认导出
动态导入与代码分割
导入时重命名模块成员
导入多个模块成员的模式
CommonJS 与 ES6 Modules :区别与使用场景
两种模块系统的主要差异
混合使用两种模块系统
Node.js中的模块解析策略
循环依赖处理
模块打包与构建
使用Webpack/Rollup等工具
Tree-shaking机制
代码分割与懒加载
模块热替换(HMR)
模块设计模式
揭示模块模式
单例模式与模块
依赖注入
模块组合与聚合
事件处理
事件监听 :如何在 DOM 元素上绑定事件监听器,理解事件的冒泡与捕获
行内事件vs addEventListener
多事件处理程序注册
once选项与单次触发
passive选项与滚动性能
事件对象 :如何访问事件信息(例如点击的元素、键盘按键等)
常用事件属性与方法
不同事件类型的特有属性
Event与CustomEvent的区别
合成事件与原生事件
事件委托 :在父元素上监听事件,提高性能和代码简洁性
事件委托的性能优势
动态元素的事件处理
复杂嵌套结构中的事件委托
委托事件的过滤技术
自定义事件
创建与分发自定义事件
事件总线/发布订阅模式
跨组件通信
事件命名空间
事件流控制
事件冒泡与捕获机制详解
preventDefault与stopPropagation
event.stopImmediatePropagation
事件顺序与执行时机
错误处理与调试
**try...catch
**:捕获并处理同步代码的错误
try…catch…finally的完整使用
各种内置错误类型的识别
错误包装与重抛出
多重catch块与特定错误处理
调试工具 :使用浏览器的开发者工具进行调试,console.log()
、console.error()
等调试方法
条件断点设置
监视表达式与断点
调用栈分析
性能分析工具
网络请求分析
自定义错误 :创建和抛出自定义错误,例如 throw new Error('message')
继承Error类创建自定义错误
错误层次结构设计
带错误代码的错误
错误本地化
错误日志与监控
错误上报系统
生产环境错误捕获
用户行为追踪
异常分析与处理流程
防御式编程
输入验证
参数类型检查
边界条件测试
安全错误处理
性能优化
防抖与节流 :减少高频事件的执行,尤其是输入框、窗口大小调整等
自定义防抖函数实现
自定义节流函数实现
立即执行的防抖变体
适合防抖与节流的场景分析
懒加载 :推迟不必要的资源加载,提升初始加载速度
图片懒加载实现
组件懒加载技术
Intersection Observer API应用
预加载与懒加载结合
内存管理 :理解垃圾回收机制,避免内存泄漏(如无用的闭包、循环引用等)
检测内存泄漏的工具与方法
常见的内存泄漏模式
WeakMap/WeakSet预防内存泄漏
大型应用的内存管理策略
算法优化 :理解时间复杂度和空间复杂度,优化循环和递归操作
常见排序算法的JavaScript实现
数据结构选择对性能的影响
递归优化与尾调用
动态规划与记忆化
批量DOM操作 :使用文档片段(DocumentFragment)和离线DOM操作减少重排和重绘
DocumentFragment优化DOM操作
虚拟DOM原理
最小化重排与重绘
requestAnimationFrame应用
渲染性能
硬件加速与will-change
复合层与层管理
高效动画实现
栅格化与绘制优化
JavaScript执行优化
Web Worker多线程处理
代码分割与按需加载
函数去抖与节流
JIT优化友好的代码
Web APIs与本地存储
localStorage 和 sessionStorage :客户端存储键值对的不同方式和使用场景
存储限制与处理方法
数据序列化与反序列化
跨域存储访问限制
存储事件与同步
Cookies :了解cookie的设置、读取、参数和安全性考虑
Cookie属性详解(HttpOnly, Secure, SameSite)
第一方Cookie vs 第三方Cookie
Cookie安全最佳实践
服务器与客户端Cookie操作
IndexedDB :客户端结构化数据存储,适用于大量数据存储和复杂查询
数据库创建与版本管理
事务与CRUD操作
索引创建与高效查询
异步API使用模式
Cache API :理解浏览器缓存机制和Service Worker配合使用
缓存策略(Cache-First, Network-First等)
缓存失效与更新
预加载与离线访问
与Service Worker集成
Geolocation API :获取用户位置信息
位置权限管理
高精度vs低功耗选项
位置监视与更新
错误处理与降级策略
Web Workers :在后台线程执行计算密集型任务,避免阻塞主线程
创建与使用Worker
Worker间通信
SharedWorker与跨标签页通信
Worker中可用的API
其他重要Web APIs
Fetch API与网络请求
Web Sockets实时通信
File API与本地文件操作
Web Audio API音频处理
Canvas与WebGL图形渲染
Drag and Drop API
现代JavaScript与最佳实践
函数式编程 :纯函数、不可变性和高阶函数的概念和使用
纯函数概念与实践
高阶函数与函数组合
柯里化与偏函数应用
不可变数据处理
函数式编程库(Ramda, Lodash/fp)
代码分割 :动态导入和懒加载模块,提高应用加载性能
基于路由的代码分割
基于组件的代码分割
import()语法与webpack集成
预加载与预获取技术
空值处理 :使用空值合并运算符(??)和可选链操作符(?.)
空值合并与默认值的区别
深层属性访问安全策略
空值处理的模式与反模式
Maybe模式与Option类型
TypeScript基础 :类型系统、接口和泛型的基本概念
基本类型注解
接口与类型别名
泛型编程
TypeScript配置与集成
类型声明文件(.d.ts)
状态管理 :了解常见的状态管理模式和原则
单向数据流
不可变状态原则
状态容器设计
发布/订阅模式
Context API与Redux比较
测试技术 :单元测试、集成测试的基本概念和工具
Jest, Mocha等测试框架
BDD vs TDD方法论
测试覆盖率与质量度量
模拟与存根
E2E测试与Cypress
代码规范 :了解ESLint、Prettier等工具,保持代码一致性和质量
配置ESLint规则
Prettier代码格式化
Git hooks与提交前检查
风格指南与团队规范
JSDoc文档注释
设计模式与架构
常用JavaScript设计模式
组件化与模块化设计
SOLID原则应用
微前端架构
服务端渲染vs客户端渲染