【前端】【JavaScript】【總復習】四萬字詳解JavaScript知識體系

JavaScript 前端知識體系


📌 說明:本大綱從基礎到高級、從語法到應用、從面試到實戰,分層級講解 JavaScript 的核心內容。

一、JavaScript 基礎語法

1.1 基本概念

1.1.1 JavaScript 的發展史與用途
1. 發展簡史
  • 1995 年:JavaScript 由 Netscape 工程師 Brendan Eich 在 10 天 內創建,最初叫 LiveScript,后更名為 JavaScript。
  • 早期用途:僅用于網頁中的簡單表單校驗和交互動畫。
  • 1997 年:被 ECMA 國際標準化組織采納,形成 ECMAScript 標準。
  • 2009 年:Node.js 橫空出世,JS 從瀏覽器進入服務端。
  • 2015 年:ES6(ECMAScript 2015)發布,成為 JS 的重大飛躍。
2. 現代用途

JavaScript 已不再只是“網頁腳本語言”,現在幾乎無所不能

  • 瀏覽器交互開發(HTML+CSS+JS)
  • Web 應用開發(React/Vue/Angular)
  • 服務端開發(Node.js)
  • 移動端開發(React Native)
  • 桌面應用開發(Electron)
  • 游戲開發(Pixi.js、Three.js)
  • 自動化測試、爬蟲、AI 前端可視化等

🎯 一句話總結:JS 是一門“瀏覽器起家、全棧統治、無處不在”的語言。


1.1.2 瀏覽器中的 JS 與 Node.js 的區別
特性瀏覽器中的 JSNode.js
運行環境瀏覽器(Chrome、Firefox 等)服務端(基于 V8 引擎)
核心目標實現用戶交互、DOM 操作搭建 Web 服務、處理后端邏輯
可訪問的 APIDOM、BOM(window、document)等文件系統(fs)、網絡模塊(http)
模塊系統ES Module(ES6后支持)CommonJS
全局對象windowglobal
適合應用場景網頁開發、瀏覽器插件接口服務、工具腳本、構建工具等

🚀 一句話記憶:瀏覽器 JS 用于“看得見的交互”,Node.js 用于“看不見的服務”。


1.1.3 動態類型語言 vs 靜態類型語言
1. 類型系統簡介
  • 類型:變量可以表示的數據類型,例如字符串、數字、布爾值等。
  • 類型系統:語言如何檢測、限制這些數據類型的規則體系。
2. 對比分析
特性動態類型語言(如 JS)靜態類型語言(如 Java、C++)
聲明變量不需指定類型,運行時才知道聲明時必須指定類型
類型檢查在運行時進行在編譯階段進行
靈活性高,變量可變類型低,但可提升可靠性
出錯時間點運行時才報錯編譯時就能發現類型錯誤
開發體驗快速開發,適合原型迭代安全穩定,適合大型項目
3. 示例對比
// JS - 動態類型
let x = 10;     
x = "hello";    // 合法,x 類型變為 string
// Java - 靜態類型
int x = 10;
x = "hello";  // ? 報錯,類型不匹配

💡 總結一句話:JS 是“你想放什么我都裝”,Java 是“你不給我指定我不干活”。


1.2 數據類型

JavaScript 中的數據類型分為兩大類:原始類型(Primitive Type)引用類型(Reference Type)


1.2.1 原始類型(7 種)

原始類型是不可變值,每個變量直接存儲值本身,保存在棧內存中。

類型示例值說明
String"hello"表示文本
Number42, 3.14, NaN所有數字(包含整數和浮點數)
Booleantrue, false邏輯值
Undefinedundefined未賦值變量的默認值
Nullnull表示“無值”
SymbolSymbol("id")創建獨一無二的標識符(ES6)
BigInt12345678901234567890n表示任意精度整數(ES11)

示例:

let name = "Alice";         // String
let age = 30;               // Number
let isAdmin = true;         // Boolean
let user;                   // Undefined
let empty = null;           // Null
let key = Symbol("id");     // Symbol
let bigNumber = 123456789012345678901234567890n; // BigInt

🧠 注意typeof null === "object" 是歷史遺留 bug,不代表 null 是引用類型!


1.2.2 引用類型(常見 5 類)

引用類型是可變對象,變量保存的是指向值的地址(引用),保存在堆內存中。

類型示例特點
Object{name: "Tom"}萬物皆對象的基礎類型
Array[1, 2, 3]有序集合,索引訪問
Functionfunction() {}可調用對象,函數是一等公民
Datenew Date()日期對象
RegExp/\d+/正則表達式對象

示例:

let person = { name: "Tom", age: 25 };   // Object
let numbers = [1, 2, 3];                 // Array
let greet = function() { console.log("Hi"); }; // Function
let now = new Date();                   // Date
let pattern = /\d+/;                    // RegExp

1.2.3 原始類型 vs 引用類型 對比總結
特性原始類型引用類型
存儲方式棧內存,值拷貝堆內存,引用拷貝(指針)
是否可變不可變(每次修改都創建新值)可變(修改對象本身)
比較方式值比較(===)引用地址比較
復制行為復制值復制引用,多個變量指向同一對象

示例比較:

let a = 100;
let b = a;
b = 200;
console.log(a); // 100(原始類型,值獨立)let obj1 = { x: 1 };
let obj2 = obj1;
obj2.x = 99;
console.log(obj1.x); // 99(引用類型,地址共享)

📌 一句話總結:原始類型像“復制粘貼”,引用類型像“共享文件夾”。


1.3 變量聲明

1.3.1 varletconst 的區別
特性varletconst
聲明方式ES5,函數級作用域ES6,塊級作用域ES6,塊級作用域
變量提升? 有提升,值為 undefined? 有提升但不初始化? 有提升但不初始化
允許重復聲明? 允許? 報錯? 報錯
可重新賦值? 可以? 可以? 不可重新賦值
是否必須初始化? 不需要? 不需要? 必須初始化

示例:

// var
console.log(a); // undefined(已提升)
var a = 10;// let
console.log(b); // ReferenceError(暫時性死區)
let b = 20;// const
const c = 30;
c = 40; // ? 報錯,不能重新賦值

🔒 記憶口訣var 會提升,let 會保護,const 定值不可改。


1.3.2 作用域與變量提升(Hoisting)
  • 函數作用域(Function Scope)var 聲明的變量只在函數內部有效。
  • 塊級作用域(Block Scope)letconst 聲明的變量只在當前代碼塊 {} 內有效。
function test() {if (true) {var x = 10;let y = 20;}console.log(x); // ? 輸出 10console.log(y); // ? 報錯
}
  • 變量提升(Hoisting):JavaScript 在運行前會“預處理”變量和函數聲明,使它們“看起來”被提升到作用域頂部。
console.log(a); // undefined
var a = 5;

1.4 運算符與表達式

1.4.1 算術、比較、邏輯運算符
  • 算術運算符+ - * / % **
  • 比較運算符> < >= <= == === != !==
  • 邏輯運算符&& || !
2 ** 3     // 8,冪運算
3 > 2      // true
true && false // false

1.4.2 其他運算符
  • 三元運算符條件 ? 值1 : 值2
let result = score >= 60 ? "及格" : "不及格";
  • 位運算符& | ^ ~ << >>
    (適用于底層優化,如權限控制、性能壓縮)
  • 空值合并運算符(??:僅在左值為 nullundefined 時使用右值。
let name = userName ?? "默認用戶";

1.5 流程控制

1.5.1 條件判斷
  • if…else
if (score >= 90) {console.log("優秀");
} else if (score >= 60) {console.log("及格");
} else {console.log("不及格");
}
  • switch…case
let color = "green";
switch (color) {case "red":console.log("紅色");break;case "green":console.log("綠色");break;default:console.log("未知顏色");
}

1.5.2 循環結構
  • for 循環
for (let i = 0; i < 3; i++) {console.log(i);
}
  • while / do…while
let i = 0;
while (i < 3) {console.log(i);i++;
}do {console.log(i);i--;
} while (i > 0);
  • for…in:遍歷對象的
let obj = { a: 1, b: 2 };
for (let key in obj) {console.log(key);      // "a", "b"
}
  • for…of:遍歷可迭代對象的(如數組、字符串)
for (let value of [10, 20, 30]) {console.log(value);    // 10, 20, 30
}

🔁 記憶總結

  • for...in 用來遍歷“對象鍵名”,
  • for...of 用來遍歷“數組值”。

二、函數與作用域

2.1 函數定義方式


2.1.1 函數聲明(Function Declaration)
function sayHi(name) {return `Hello, ${name}`;
}
  • ? 支持提升:可以在函數聲明之前調用
  • ? 語義清晰,適合通用工具函數
  • 📌 函數體內 this 指向調用者
greet(); // ? 輸出 "Hi there!"function greet() {console.log("Hi there!");
}

2.1.2 函數表達式(Function Expression)
const sayHi = function(name) {return `Hello, ${name}`;
};
  • ? 不支持提升:調用必須在定義之后
  • ? 更靈活:可作為參數傳遞、閉包使用
  • ? 命名 or 匿名:支持匿名函數
// 報錯:Cannot access 'greet' before initialization
greet();const greet = function () {console.log("Hello");
};

2.1.3 箭頭函數(Arrow Function)
const sayHi = (name) => {return `Hello, ${name}`;
};
  • ? 語法簡潔
  • ? 沒有自己的 thisarguments
  • ? 不能當構造函數使用

簡寫形式(單參數、單表達式可省略括號與 return):

const double = x => x * 2;

this 對比示例:

const obj = {normal: function() {console.log(this); // 指向 obj},arrow: () => {console.log(this); // 指向定義時外部的 this(可能是 window 或 undefined)}
};

🧠 一圖記憶

類型是否提升是否有 this是否能 new是否簡潔
函數聲明????
函數表達式????
箭頭函數??(繼承)????

2.2 作用域與閉包


2.2.1 詞法作用域(Lexical Scope)

定義:詞法作用域是指變量的作用范圍由代碼書寫位置決定,而非函數的調用方式。

function outer() {const a = 10;function inner() {console.log(a); // 可以訪問 a}inner();
}
outer();
  • 📌 函數定義在哪里,就決定了它能訪問哪些變量。
  • ? 內部函數可以訪問其外部函數作用域中的變量,這就是閉包的基礎。

💡 記憶口訣:作用域查找看“定義位置”,不是“調用位置”。


2.2.2 閉包原理與應用場景
📘 什么是閉包?

閉包(Closure)是函數與其詞法環境的組合。當函數在其定義的作用域外被調用時,它仍然能夠記住并訪問其定義時的作用域鏈

function createCounter() {let count = 0;return function () {count++;return count;};
}const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
  • 🔁 count 沒有被銷毀,因為返回的函數一直引用它,這就是閉包。
  • 💡 JS 的函數是一等對象,可以被返回、賦值、傳參,而閉包能讓這些函數帶上“記憶”。

📌 閉包的常見應用場景
場景示例
數據私有封裝內部變量不暴露到全局作用域
函數工廠動態生成具有“私有數據”的函數
防抖節流利用閉包保存定時器引用等狀態
記憶函數緩存函數執行結果(Memoization)
// 數據私有:模擬私有變量
function Secret() {let secret = "密碼123";return {get: () => secret,set: (val) => secret = val};
}
const s = Secret();
console.log(s.get()); // 密碼123

🧠 一句話總結:閉包 = 函數 + 定義時的作用域鏈,是 JS 中實現“私有狀態”和“記憶能力”的核心機制。


2.3 this 指向與 call/apply/bind


2.3.1 this 在不同上下文的指向規則

this 在 JavaScript 中非常靈活,它的指向是動態的,依賴于函數的調用方式。我們可以將它分為幾種主要的調用方式進行分類講解。


一、隱式綁定(Implicit Binding)

隱式綁定指的是 在對象的方法中調用函數時,this 指向調用該方法的對象

const person = {name: "Alice",greet() {console.log(this.name);}
};
person.greet(); // "Alice"
  • 在這個例子中,this 指向 person 對象。

二、顯式綁定(Explicit Binding)

顯式綁定是通過 callapplybind 等方法顯式地指定 this 的指向

  1. call():立即調用函數,傳入 this 指定的對象和后續參數。

    function greet() {console.log(`Hello, ${this.name}`);
    }
    const person = { name: "Bob" };
    greet.call(person); // "Hello, Bob"
    
  2. apply():類似 call(),但接收一個數組作為參數。

    greet.apply(person); // "Hello, Bob"
    
  3. bind():返回一個新函數,綁定了 this,但不立即執行。

    const boundGreet = greet.bind(person);
    boundGreet(); // "Hello, Bob"
    
  • 總結callapply 立即執行,而 bind 返回一個新的函數。

三、默認綁定(Default Binding)

當函數被直接調用(例如普通函數調用時),this 的默認指向規則會根據執行環境有所不同:

  • 非嚴格模式下,this 會指向全局對象(瀏覽器中是 window,Node 中是 global)。
  • 嚴格模式下,thisundefined
function greet() {console.log(this);
}greet(); // 在非嚴格模式下,指向 window;嚴格模式下,指向 undefined

四、構造函數綁定(Constructor Binding)

當函數作為構造函數通過 new 關鍵字調用時,this 會指向新創建的實例對象。

function Person(name) {this.name = name;
}const person1 = new Person("Alice");
console.log(person1.name); // "Alice"
  • new 關鍵字使得 this 指向新創建的實例對象。

五、箭頭函數(Arrow Function)

箭頭函數沒有自己的 this,它會繼承外層上下文的 this。也就是說,箭頭函數的 this 是在定義時就確定的,而不是在調用時確定。

const obj = {name: "Alice",greet() {const arrowFunc = () => {console.log(this.name);};arrowFunc(); // "Alice"}
};obj.greet(); // "Alice"
  • arrowFuncthis 指向的是外部的 greet 方法中的 this,即 obj

🎯 總結

調用方式this 指向
隱式綁定調用方法的對象
顯式綁定callapplybind 參數指定的對象
默認綁定非嚴格模式下為 window,嚴格模式下為 undefined
構造函數綁定新創建的對象(實例)
箭頭函數繼承外部作用域的 this

2.3.2 手動改變 this 指向的方法

有三個方法可以手動改變函數內部的 this 指向


🧩 1)call()

立即調用函數,傳入第一個參數作為 this,后續參數依次傳給函數本體。

function greet(who) {console.log(`Hello, ${who}, from ${this.name}`);
}
const person = { name: "Alice" };
greet.call(person, "Bob"); // Hello, Bob, from Alice

🧩 2)apply()

call 類似,但參數必須用數組傳入:

greet.apply(person, ["Charlie"]); // Hello, Charlie, from Alice

🧩 3)bind()

不會立即調用,而是返回一個新的函數,綁定了 this

const boundGreet = greet.bind(person, "Diana");
boundGreet(); // Hello, Diana, from Alice

🎯 對比總結

方法是否立即執行參數傳遞方式返回值
call? 是普通參數列表函數執行結果
apply? 是參數數組函數執行結果
bind? 否參數列表(可預設)新函數

🧠 記憶口訣
call 馬上叫、apply 數組搞、bind 等你叫。


三、對象與原型鏈

3.1 對象創建與屬性操作

3.1.1 對象的創建方式
  1. 字面量法
    使用大括號 {} 直接定義對象,簡單直觀。

    const person = {name: "Alice",age: 30
    };
    
  2. 構造函數法
    使用 new Object() 或通過自定義構造函數創建對象。

    const person = new Object();
    person.name = "Bob";
    person.age = 25;
    
  3. Object.create()
    使用指定的原型對象創建一個新對象,適用于原型鏈繼承。

    const personProto = {greet() {console.log(`Hello, ${this.name}`);}
    };const person = Object.create(personProto);
    person.name = "Charlie";
    person.greet(); // Hello, Charlie
    
  4. class 關鍵字
    使用 ES6 中的 class 語法創建對象及其構造函數。

    class Person {constructor(name, age) {this.name = name;this.age = age;}
    }
    const person = new Person("David", 28);
    

3.1.2 屬性描述符與 Object.defineProperty()

屬性描述符定義了對象屬性的特性(如是否可寫、可枚舉等)。

  • 數據描述符:包含 valuewritable(是否可修改)。
  • 訪問器描述符:包含 getset

Object.defineProperty() 方法允許你直接設置屬性的描述符,并能夠控制屬性的行為(例如是否能修改、是否能枚舉等)。

const person = {};
Object.defineProperty(person, "name", {value: "Eve",writable: false,    // 不可修改enumerable: true,   // 可枚舉configurable: true  // 可配置
});console.log(person.name); // Eve
person.name = "John";    // 不會修改
console.log(person.name); // Eve
  • writable: false 使得 name 屬性不可修改。
  • configurable: false 防止刪除該屬性或修改其特性。

3.2 原型與原型鏈

3.2.1 __proto__ vs prototype
  1. prototype
    每個函數對象都有一個 prototype 屬性,指向該函數的原型對象。構造函數的實例會繼承該原型對象上的屬性和方法。

    function Person(name) {this.name = name;
    }const person = new Person("Alice");
    console.log(person.__proto__ === Person.prototype); // true
    
  2. __proto__
    __proto__ 是每個對象的內部屬性,指向該對象的構造函數的原型對象。它指示了對象的原型鏈的“父級”。

    const obj = {};
    console.log(obj.__proto__ === Object.prototype); // true
    
  • prototype 是函數的屬性,而 __proto__ 是對象的屬性。

3.2.2 原型鏈查找機制

當訪問對象的屬性時,JS 引擎會先在對象自身查找,如果沒有找到,再沿著原型鏈向上查找,直到找到該屬性或到達 null 為止。

  • 每個對象都有一個 __proto__ 屬性,它指向該對象的構造函數的原型對象。
  • 原型對象也有 __proto__,形成一個鏈條,最終鏈條的盡頭是 Object.prototype,它的 __proto__null
const obj = { name: "Alice" };
console.log(obj.name); // "Alice"
console.log(obj.toString()); // 調用 Object.prototype.toString
  • obj 沒有 toString 方法,它會向原型鏈上的 Object.prototype 查找 toString 方法。

3.3 繼承方式

3.3.1 ES5 原型繼承

在 ES5 中,原型繼承是通過構造函數和 prototype 屬性實現的。基本的繼承方式是通過讓子類的 prototype 指向父類的 prototype

function Animal(name) {this.name = name;
}Animal.prototype.sayHello = function() {console.log(`Hello, I am a ${this.name}`);
};function Dog(name) {Animal.call(this, name); // 繼承屬性
}Dog.prototype = Object.create(Animal.prototype); // 繼承方法
Dog.prototype.constructor = Dog; // 修復構造函數指向const dog = new Dog("Buddy");
dog.sayHello(); // Hello, I am a Buddy
  • Object.create() 用于創建一個新的對象,將原型鏈指向父類的原型對象,從而實現繼承。
3.3.2 組合繼承

組合繼承(又叫偽經典繼承)是 構造函數繼承原型繼承 的組合,它解決了原型繼承的缺點:子類會繼承父類的所有實例屬性,但每個子類實例都會重復父類的實例屬性。

function Animal(name) {this.name = name;
}Animal.prototype.sayHello = function() {console.log(`Hello, I am a ${this.name}`);
};function Dog(name, breed) {Animal.call(this, name); // 繼承實例屬性this.breed = breed;
}Dog.prototype = new Animal(); // 繼承方法
Dog.prototype.constructor = Dog;const dog = new Dog("Buddy", "Golden Retriever");
dog.sayHello(); // Hello, I am a Buddy
console.log(dog.breed); // Golden Retriever
  • 缺點:構造函數 Animal.call(this) 被調用了兩次。new Animal() 會創建父類的實例,并將父類的屬性賦給子類原型。
3.3.3 類似寄生繼承的方式

寄生繼承 是通過 借用構造函數 的方式繼承父類的屬性,但不改變原型鏈。

function Animal(name) {this.name = name;
}Animal.prototype.sayHello = function() {console.log(`Hello, I am a ${this.name}`);
};function Dog(name, breed) {Animal.call(this, name); // 繼承屬性this.breed = breed;
}Dog.prototype = Object.create(Animal.prototype); // 繼承方法
Dog.prototype.constructor = Dog;const dog = new Dog("Buddy", "Golden Retriever");
dog.sayHello(); // Hello, I am a Buddy
console.log(dog.breed); // Golden Retriever
  • 這個方式在繼承父類方法時,依然保持了父類原型鏈的正確性,解決了構造函數重復調用的問題。
3.3.4 寄生組合繼承

寄生組合繼承(parasitic combination inheritance)是一種優化的方式,它結合了 寄生繼承組合繼承 的優點。通過 Object.create() 繼承父類的方法,并通過構造函數繼承父類的實例屬性,避免了重復調用父類構造函數。

function Animal(name) {this.name = name;
}Animal.prototype.sayHello = function() {console.log(`Hello, I am a ${this.name}`);
};function Dog(name, breed) {Animal.call(this, name); // 繼承屬性this.breed = breed;
}// 使用寄生組合繼承來避免重復調用父類構造函數
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;const dog = new Dog("Buddy", "Golden Retriever");
dog.sayHello(); // Hello, I am a Buddy
console.log(dog.breed); // Golden Retriever
  • 優化點:只調用一次父類的構造函數,通過 Object.create() 來繼承父類的原型方法,避免了組合繼承的性能問題。
3.3.5 ES6 class 繼承 (extendssuper)

ES6 引入了 classextends 語法,使得繼承更加簡潔和直觀。super 用于調用父類的構造函數或方法。

class Animal {constructor(name) {this.name = name;}sayHello() {console.log(`Hello, I am a ${this.name}`);}
}class Dog extends Animal {constructor(name, breed) {super(name); // 調用父類構造函數this.breed = breed;}bark() {console.log("Woof!");}
}const dog = new Dog("Buddy", "Golden Retriever");
dog.sayHello(); // Hello, I am a Buddy
dog.bark();     // Woof!
  • extends 用于實現繼承。
  • super 用于調用父類的構造函數或方法。

3.3 總結

繼承方式描述優缺點
原型繼承通過設置子類原型為父類原型的實例來實現繼承缺點:父類實例屬性會被所有子類實例共享
組合繼承結合構造函數繼承和原型繼承缺點:構造函數被調用兩次
寄生繼承通過借用構造函數繼承父類實例屬性,不改變原型適用于不需要創建新對象的場景
寄生組合繼承結合了寄生繼承與組合繼承的優點,優化了性能解決了組合繼承的缺點,避免了重復調用構造函數
ES6 class使用 classextends 語法簡化繼承語法簡潔,易于理解,但仍然是基于原型鏈的繼承

四、數組與內置對象

4.1 數組操作

4.1.1 創建與轉換
方法返回值是否修改原數組作用
Array.of(...items)新數組(包含所有參數)創建一個包含所有參數的數組
Array.from(obj)新數組(類數組轉數組)將類數組或可迭代對象轉換為數組
arr.toString()字符串(元素用逗號連接)將數組元素轉換為字符串,用逗號分隔
arr.join(sep)字符串(自定義分隔符)將數組元素連接成字符串,使用指定的分隔符

4.1.2 增刪元素
方法返回值是否修改原數組作用
push(...items)新長度在數組末尾添加一個或多個元素
pop()被刪除的元素刪除并返回數組的最后一個元素
unshift(...items)新長度在數組開頭添加一個或多個元素
shift()被刪除的元素刪除并返回數組的第一個元素
splice(start, del, ...items)被刪除的元素數組從指定位置刪除指定數量的元素,并可以插入新元素
slice(start, end)新數組(部分元素)返回數組的一個淺拷貝(部分)

4.1.3 查找與過濾
方法返回值是否修改原數組作用
indexOf(item)首個匹配索引(-1 表示不存在)查找元素首次出現的位置
lastIndexOf(item)最后匹配索引(-1 表示不存在)查找元素最后一次出現的位置
includes(item)布爾值(是否包含)判斷數組是否包含某個元素
find(fn)首個匹配元素(undefined 表示不存在)查找并返回第一個滿足條件的元素
findIndex(fn)首個匹配索引(-1 表示不存在)查找并返回第一個滿足條件的元素索引
filter(fn)新數組(所有匹配元素)返回一個包含所有滿足條件元素的新數組

4.1.4 遍歷與轉換
方法返回值是否修改原數組作用
forEach(fn)undefined否(但可修改元素)遍歷數組,執行給定的函數,適用于副作用操作
map(fn)新數組(每個元素處理后)返回一個新的數組,每個元素經過給定函數處理
flat(depth)新數組(扁平化后)將嵌套的數組結構“拉平”至指定深度
flatMap(fn)新數組(先 map 再 flat)先對數組進行 map 操作,再進行扁平化

4.1.5 排序與反轉
方法返回值是否修改原數組作用
sort(fn)原數組(排序后)對數組進行排序,默認按字符順序排列
reverse()原數組(反轉后)將數組元素的順序顛倒

4.1.6 合并與拆分
方法返回值是否修改原數組作用
concat(...arrays)新數組(合并后)合并多個數組或值到一個新數組
split(sep)字符串 → 數組否(操作字符串)將字符串分割為數組
join(sep)數組 → 字符串將數組元素連接成一個字符串,使用指定的分隔符

4.1.7 歸約方法
方法返回值是否修改原數組作用
reduce(fn, init)累計值對數組元素執行累加操作,返回累計值
reduceRight(fn, init)累計值(從右到左)從右到左對數組元素執行累加操作,返回累計值

4.1.8 判定方法
方法返回值是否修改原數組作用
every(fn)布爾值(所有元素滿足)判斷數組中的每個元素是否都滿足條件
some(fn)布爾值(至少一個滿足)判斷數組中是否至少有一個元素滿足條件
isArray(value)布爾值(是否為數組)否(靜態方法)判斷給定值是否為數組

4.1.9 其他方法
方法返回值是否修改原數組作用
fill(value, start, end)原數組(填充后)用指定的值填充數組的某部分元素
copyWithin(target, start, end)原數組(復制后)將數組中的一部分復制到同一數組的指定位置
entries()迭代器(索引-值對)返回一個數組的遍歷器對象,包含索引和對應值
keys()迭代器(索引)返回一個包含數組索引的遍歷器對象
values()迭代器(值)返回一個包含數組值的遍歷器對象

記憶技巧

  1. 修改原數組的方法
    push/pop/unshift/shift/splice/sort/reverse/fill/copyWithin
    (口訣:增刪改查排序反轉填充復制
  2. 返回新數組的方法
    slice/map/filter/concat/flat/flatMap
    (口訣:切片映射過濾合并扁平化
  3. 歸約與判定
    reduce/every/some/find/findIndex/includes
    (口訣:累計判定查找包含

4.2 常用內置對象

4.2.1 String 對象
1. 字符操作
方法返回值作用
charAt(index)字符返回指定位置的字符
charCodeAt(index)數字返回指定位置字符的 Unicode 編碼
codePointAt(index)數字返回指定位置字符的 Unicode 代碼點
fromCharCode(...codes)字符串從 Unicode 編碼返回字符
fromCodePoint(...codePoints)字符串從 Unicode 代碼點返回字符
2. 查找與替換
方法返回值作用
includes(searchString)布爾值判斷字符串是否包含指定的子串
indexOf(searchValue)索引返回子串首次出現的位置
lastIndexOf(searchValue)索引返回子串最后一次出現的位置
match(regexp)數組匹配正則表達式并返回結果
replace(searchValue, newValue)新字符串替換匹配的子字符串
3. 大小寫轉換
方法返回值作用
toLowerCase()小寫字符串返回將所有字符轉換為小寫的新字符串
toUpperCase()大寫字符串返回將所有字符轉換為大寫的新字符串
4. 切割與連接
方法返回值作用
slice(start, end)子字符串返回字符串的一個部分
split(separator)數組按照指定分隔符拆分字符串
concat(...strings)字符串連接多個字符串并返回新字符串
join(sep)字符串數組元素連接為字符串

4.2.2 Date 對象
1. 獲取日期與時間
方法返回值作用
getFullYear()年份返回完整的年份(4位)
getMonth()月份返回月份(0-11)
getDate()日期返回一個月中的日期(1-31)
getDay()星期幾返回星期幾(0-6,0為星期天)
getHours()小時返回小時(0-23)
getMinutes()分鐘返回分鐘(0-59)
getSeconds()秒數返回秒數(0-59)
getMilliseconds()毫秒返回毫秒數(0-999)
2. 設置日期與時間
方法返回值作用
setFullYear(year)設置年份設置年份(4位)
setMonth(month)設置月份設置月份(0-11)
setDate(day)設置日期設置日期(1-31)
setHours(hours)設置小時設置小時(0-23)
setMinutes(minutes)設置分鐘設置分鐘(0-59)
setSeconds(seconds)設置秒數設置秒數(0-59)
setMilliseconds(milliseconds)設置毫秒設置毫秒(0-999)

4.2.3 Math 對象
1. 數學常用方法
方法返回值作用
Math.abs(x)數值返回 x 的絕對值
Math.ceil(x)數值返回大于或等于 x 的最小整數
Math.floor(x)數值返回小于或等于 x 的最大整數
Math.round(x)數值返回四舍五入后的值
Math.random()數值返回一個 0 到 1 之間的隨機數
Math.sqrt(x)數值返回 x 的平方根
2. 極值與范圍
方法返回值作用
Math.max(...values)數值返回一組數中的最大值
Math.min(...values)數值返回一組數中的最小值
Math.pow(x, y)數值返回 x 的 y 次方
Math.PI數值返回圓周率常量 π

4.2.4 JSON 對象
1. JSON 解析與字符串化
方法返回值作用
JSON.parse(text)對象/數組將 JSON 字符串解析為 JavaScript 對象
JSON.stringify(value)JSON 字符串將 JavaScript 對象轉換為 JSON 字符串

4.2.5 RegExp 對象
1. 正則表達式方法
方法返回值作用
test(str)布爾值測試正則表達式是否匹配字符串
exec(str)數組返回正則表達式與字符串匹配的結果(如果有)

五、異步編程與事件機制

5.1 異步基礎

5.1.1 同步 vs 異步
  • 同步(Synchronous):任務按順序逐行執行,前一個任務不完成,后一個任務無法開始。
  • 異步(Asynchronous):某些操作可在“等待結果”的同時繼續執行其他任務。

📌 示例:

console.log('A');
setTimeout(() => console.log('B'), 1000);
console.log('C');
// 輸出順序:A → C → B
5.1.2 回調函數與 Callback Hell
  • 回調函數:將一個函數作為參數傳給另一個函數,用于異步任務完成后執行。
  • 回調地獄(Callback Hell):多個嵌套回調,導致代碼結構混亂、難以維護。

📌 示例:

doSomething(function(result1) {doSomethingElse(result1, function(result2) {doThirdThing(result2, function(result3) {console.log('All done!');});});
});

5.2 Promise 與 async/await


5.2.1 Promise 構造與鏈式調用(進階版)
  • Promise 是異步編程的核心機制,表示一個可能現在、將來或永不完成的值
  • 狀態只能從 pendingfulfilledpendingrejected,不可逆。

? 一、創建 Promise 實例
const p = new Promise((resolve, reject) => {const data = getData();if (data) resolve(data);else reject(new Error("獲取失敗"));
});
  • resolve(value):表示成功,進入 .then() 分支
  • reject(error):表示失敗,進入 .catch() 分支

? 二、鏈式調用(then / catch / finally)
p.then(result => {console.log("成功:", result);return result + "!";
}).then(modified => {console.log("鏈式處理:", modified);
}).catch(err => {console.error("捕獲錯誤:", err);
}).finally(() => {console.log("無論成功失敗都會執行");
});
  • .then() 可以返回新值傳遞給下一個 .then()
  • .catch() 捕獲任意前面出現的錯誤
  • .finally() 不處理值,僅用于收尾動作(如關閉 loading)

? 三、錯誤傳播機制

.then() 中拋出錯誤,會直接被后面的 .catch() 捕獲。

p.then(() => {throw new Error("出錯了");
}).catch(err => {console.log("捕獲到錯誤", err.message);
});

? 四、Promise 嵌套與避免回調地獄
getUserInfo().then(user => {return getPostsByUser(user.id);
}).then(posts => {return getCommentsForPost(posts[0].id);
});
  • 通過鏈式結構代替回調嵌套,實現邏輯扁平化
  • 若返回的是一個新的 Promise,則自動等待其執行完成

? 五、常見錯誤使用案例(警示)
// ?? 不要這樣寫
p.then(res => {doSomething(res, function(result) {// 回調地獄又來了});
});

應改寫為:

p.then(res => doSomethingAsync(res)).then(next => console.log(next));

非常好,Promise 除了構造函數和鏈式調用外,還有一組非常實用的靜態方法(類方法),適用于多個異步任務的管理與控制。以下是完整補充,按照清晰的結構歸類呈現:


🔹 5.2.2 Promise 所有方法匯總


? 一、構造函數實例方法
方法作用特點
new Promise(fn)創建一個新的 Promise 實例傳入 resolvereject 兩個函數參數
.then(onFulfilled)注冊成功回調函數支持鏈式調用
.catch(onRejected)注冊失敗回調函數.then(null, onRejected) 的語法糖
.finally(fn)無論成功/失敗都會執行不影響返回值傳遞

? 二、靜態方法(類方法)
1. Promise.resolve(value)
  • 返回一個狀態為 fulfilled 的 Promise
  • 如果傳入的是一個 Promise,會直接返回
Promise.resolve(42).then(console.log); // 42
2. Promise.reject(error)
  • 返回一個狀態為 rejected 的 Promise
  • 通常用于封裝異常
Promise.reject("失敗").catch(console.error); // 失敗

3. Promise.all([p1, p2, …])
  • 等待所有 Promise 成功,才 resolve,否則立即 reject
  • 返回值是所有結果的數組(按順序)
Promise.all([p1, p2]).then(([r1, r2]) => {console.log(r1, r2);
});

🧠 常用于:并發請求,必須都成功


4. Promise.race([p1, p2, …])
  • 誰先完成(成功或失敗),就采用誰的結果
  • 競速場景:如加載動畫 vs 請求超時
Promise.race([fetchData(),timeoutPromise(3000)
]).then(console.log).catch(console.error);

5. Promise.allSettled([p1, p2, …])
  • 等待所有 Promise 都結束(無論成功或失敗)
  • 每一項返回 { status, value }{ status, reason }
Promise.allSettled([p1, p2]).then(results => {results.forEach(r => console.log(r.status));
});

🧠 常用于:統計、批處理,不能因為一個失敗而中斷


6. Promise.any([p1, p2, …])
  • 誰先成功就 resolve全部失敗才 reject
  • ES2021 新增
Promise.any([Promise.reject("失敗1"),Promise.resolve("成功"),Promise.reject("失敗2")
]).then(console.log); // 輸出:"成功"

🧠 常用于:只需一個成功即可,如鏡像 CDN 請求


? 三、對比總結
方法成功策略失敗策略典型應用
Promise.all全部成功任意失敗立即中止并行任務且都要成功
Promise.race誰先返回誰先返回超時控制
Promise.allSettled不關心不關心全部結果分析
Promise.any任意一個成功即可全部失敗才失敗多鏡像請求、降級處理
? 小貼士:手寫模擬 Promise.all(核心思維訓練)
function promiseAll(promises) {return new Promise((resolve, reject) => {let result = [], count = 0;promises.forEach((p, i) => {Promise.resolve(p).then(val => {result[i] = val;count++;if (count === promises.length) resolve(result);}).catch(reject);});});
}
5.2.3 async/await
  • async 聲明函數返回一個 Promise。
  • await 暫停異步函數執行,等待 Promise 結果。

📌 示例:

async function fetchData() {try {const data = await getData();console.log(data);} catch (error) {console.error('Error:', error);}
}

5.3 事件循環機制(Event Loop)

5.3.1 宏任務 vs 微任務
類型示例執行時機
宏任務setTimeoutsetIntervalI/OsetImmediate(Node)每輪事件循環開始時調度
微任務Promise.thenqueueMicrotaskMutationObserver(瀏覽器)當前宏任務執行完立即執行所有微任務

📌 執行順序示例:

console.log('start');setTimeout(() => console.log('setTimeout'), 0);
Promise.resolve().then(() => console.log('promise'));
queueMicrotask(() => console.log('microtask'));
console.log('end');// 輸出:start → end → promise → microtask → setTimeout

5.3.2 瀏覽器中的事件循環流程
  1. 執行全局同步代碼(主線程 → 調用棧)
  2. 執行所有微任務隊列
  3. 執行一個宏任務隊列中的任務
  4. 重復步驟 2 → 3,直到所有任務完成

5.3.3 Node.js 中的事件循環階段

Node.js 的事件循環更復雜,包含 6 個階段(基于 libuv):

階段描述
timers執行 setTimeoutsetInterval 回調
pending callbacks執行一些系統操作的回調(如 TCP 錯誤)
idle/prepare內部使用
poll處理 I/O 事件,如果沒有則可能進入 check 階段或等待
check執行 setImmediate() 的回調
close callbacks執行如 socket.on('close', fn) 等關閉回調

? 每個階段之間都會清空微任務隊列(process.nextTick & Promise)

📌 微任務優先級:

process.nextTick > Promise.then > 宏任務(setTimeout、setImmediate)

📌 Node 示例:

setTimeout(() => console.log('timeout'), 0);
setImmediate(() => console.log('immediate'));Promise.resolve().then(() => console.log('promise'));
process.nextTick(() => console.log('nextTick'));// 輸出順序:nextTick → promise → timeout/immediate(取決于系統)

? 總結:執行順序記憶口訣

  • 瀏覽器中:同步 → 微任務 → 宏任務
  • Node.js 中:同步 → nextTick → Promise → 各階段宏任務

💡提示:Node.js 中的 setImmediate 可能比 setTimeout(fn, 0) 更快執行,但不保證一致順序。


六、DOM 與 BOM 操作

6.1 DOM 基礎(全面分類)


6.1.1 節點獲取與遍歷
方法描述返回類型
getElementById(id)根據 ID 獲取節點單個元素
getElementsByClassName(class)根據類名獲取類數組
getElementsByTagName(tag)根據標簽名獲取類數組
querySelector(selector)CSS 選擇器,獲取首個匹配節點單個元素
querySelectorAll(selector)CSS 選擇器,獲取全部匹配節點NodeList(類數組)
parentNode / childNodes / nextSiblingDOM 樹節點關系遍歷節點對象

6.1.2 節點創建、插入、刪除、克隆
操作方法示例
創建元素createElement(tag)let div = document.createElement('div')
插入appendChild()append()insertBefore()parent.appendChild(child)
刪除removeChild()remove()parent.removeChild(el)
替換replaceChild(newEl, oldEl)替換節點
克隆cloneNode(true)復制節點

6.1.3 節點內容與屬性操作
操作方法 / 屬性示例
獲取/設置文本innerText / textContentel.textContent = 'Hello'
獲取/設置 HTMLinnerHTMLel.innerHTML = '<b>Hi</b>'
獲取/設置屬性getAttribute() / setAttribute()el.setAttribute('href', '#')
移除屬性removeAttribute()el.removeAttribute('title')
操作類名classList.add/remove/toggle/containsel.classList.toggle('show')
操作樣式style.propertyel.style.color = 'red'

6.1.4 元素位置與尺寸獲取
屬性 / 方法描述示例
offsetTop / offsetLeft元素相對 offsetParent 的偏移el.offsetTop
offsetWidth / offsetHeight包含 padding 和 borderel.offsetHeight
clientWidth / clientHeight包含 padding 不含 borderel.clientWidth
scrollTop / scrollLeft滾動距離el.scrollTop
getBoundingClientRect()獲取元素相對視口的位置與尺寸el.getBoundingClientRect()

6.1.5 常用事件分類
📌 一)鼠標事件
事件名說明
click / dblclick點擊 / 雙擊
mousedown / mouseup按下 / 彈起
mousemove鼠標移動
mouseenter / mouseleave進入 / 離開元素(不冒泡)
mouseover / mouseout進入 / 離開(冒泡)
contextmenu右鍵菜單
📌 二)鍵盤事件
事件名說明
keydown鍵盤按下
keyup鍵盤松開
keypress輸入字符(已廢棄)
📌 三)表單事件
事件名說明
submit表單提交
change表單值變化(如 select)
input輸入變化(推薦用于 text 輸入)
focus / blur聚焦 / 失焦
📌 四)窗口事件
事件名說明
load頁面加載完成
resize窗口尺寸變化
scroll頁面或元素滾動
beforeunload頁面關閉前

6.1.6 事件監聽與代理
操作示例
綁定事件el.addEventListener('click', fn)
移除事件el.removeEventListener('click', fn)
阻止默認行為event.preventDefault()
阻止冒泡event.stopPropagation()
事件代理綁定父級,判斷 e.target
list.addEventListener('click', e => {if (e.target.tagName === 'LI') {console.log('點擊了第', e.target.innerText);}
});

6.1.7 拖拽與監聽移動
功能方法
拖拽事件dragstart / dragover / drop
鼠標監聽移動結合 mousedownmousemovemouseup 實現

示例偽代碼實現拖動:

let isDragging = false;
el.onmousedown = () => isDragging = true;
document.onmousemove = (e) => {if (isDragging) el.style.left = e.clientX + 'px';
};
document.onmouseup = () => isDragging = false;

6.2 事件模型(瀏覽器)

6.2.1 事件傳播機制:捕獲 & 冒泡

事件傳播分為 三個階段

階段順序階段名稱描述
捕獲階段(Capture Phase)window 自頂向下,沿著 DOM 樹傳遞到目標元素
目標階段(Target Phase)實際目標元素上觸發的事件
冒泡階段(Bubble Phase)從目標元素沿 DOM 樹向上傳遞回 window

📌 示例:

element.addEventListener('click', handler, true); // 第三個參數 true 表示捕獲階段監聽
element.addEventListener('click', handler, false); // false 表示冒泡階段監聽(默認)

6.2.2 阻止事件傳播
方法作用
event.stopPropagation()阻止事件繼續冒泡或捕獲
event.stopImmediatePropagation()阻止同一元素上后續所有事件監聽器執行
event.preventDefault()阻止默認行為(如表單提交、a 鏈接跳轉)

6.2.3 自定義事件(CustomEvent)

用于手動觸發和傳遞自定義數據的事件。

1?? 創建并觸發事件:
const event = new CustomEvent('myEvent', {detail: { name: 'ChatGPT', level: 99 }
});
element.dispatchEvent(event);
2?? 監聽事件:
element.addEventListener('myEvent', function(e) {console.log(e.detail.name); // 輸出:ChatGPT
});

6.2.4 事件對象 Event

當事件觸發時,監聽函數會自動接收一個事件對象:

屬性/方法描述
event.target實際觸發事件的元素
event.currentTarget當前綁定事件的元素
event.type事件類型(如 click)
event.timeStamp觸發事件的時間戳
event.defaultPrevented是否已調用 preventDefault()
event.bubbles該事件是否支持冒泡
event.cancelable是否可以取消默認操作

6.2.5 補充:事件委托(推薦實踐)

通過把事件綁定在父節點上,提高性能和可維護性。

ul.addEventListener('click', function(e) {if (e.target.tagName === 'LI') {console.log('點擊了:', e.target.innerText);}
});

? 好處:

  • 減少事件監聽數量
  • 支持動態添加子元素的事件響應
6.2.6 事件綁定優先級順序

在瀏覽器中,當同一元素綁定了多種事件方式,它們的觸發順序如下:

? 優先級順序(由高到低):
  1. 內聯綁定(HTML 屬性):如 <button onclick="alert(1)">
  2. DOM0 綁定(傳統方式):如 element.onclick = fn
  3. DOM2 綁定(推薦方式):如 element.addEventListener('click', fn)
?? 示例說明:
<button id="btn" onclick="console.log('inline')">點擊</button>
const btn = document.getElementById('btn');
btn.onclick = () => console.log('DOM0');
btn.addEventListener('click', () => console.log('DOM2'));

輸出順序:

inline
DOM0
DOM2
6.2.7 DOM 0 / DOM 2 級事件模型差異
比較項DOM 0 級事件(傳統)DOM 2 級事件(標準)
綁定方式element.onclick = fnaddEventListener('click', fn, useCapture)
是否支持多個監聽器? 只能綁定一個? 可綁定多個
是否支持捕獲階段? 不支持? 支持(通過第三個參數)
是否兼容 IE 低版本?IE9+
是否標準推薦?? W3C 推薦標準方式
6.2.8 React 合成事件機制(SyntheticEvent)

React 并不直接綁定原生事件,而是通過自己的事件系統(合成事件)實現更高效的管理。

📌 特點:
特性描述
合成封裝對原生事件進行封裝,統一不同瀏覽器差異
自動綁定自動使用事件委托,綁定在根節點(提高性能)
統一池化使用事件池提升性能(v17 前),需注意事件異步訪問
命名風格使用駝峰命名:如 onClickonChange
? 示例:
<button onClick={handleClick}>點擊</button>function handleClick(e) {console.log(e.nativeEvent); // 原生事件console.log(e);             // 合成事件
}
?? 注意事項:
  • 異步中訪問事件屬性需要調用 e.persist()(在 React17 以前)
  • React 17+ 不再使用事件池,不再需要 e.persist()

6.3 BOM 操作

6.3.1 window 對象
  • 瀏覽器的全局對象,所有全局變量和函數都是其屬性或方法。
  • 也是 BOM 的頂層對象。
常見屬性/方法:
屬性/方法作用
window.innerWidth / innerHeight獲取窗口內容區域的寬/高(不含滾動條)
window.open(url)打開新窗口或標簽頁
window.alert() / confirm() / prompt()瀏覽器彈窗
window.scrollTo(x, y)滾動到指定位置

6.3.2 location 對象
  • 用于獲取或修改當前頁面的 URL。
屬性/方法說明
location.href當前完整 URL,可讀取或賦值跳轉
location.protocol協議,如 https:
location.host / hostname / port主機、主機名、端口號
location.pathname路徑部分
location.search查詢字符串(如 ?id=1
location.reload()重新加載頁面
location.assign(url)跳轉到新 URL(有歷史記錄)
location.replace(url)替換當前頁面(無歷史記錄)

6.3.3 navigator 對象
  • 描述用戶瀏覽器的信息。
屬性說明
navigator.userAgent瀏覽器/設備詳細信息
navigator.platform操作系統平臺(如 Win32)
navigator.language當前瀏覽器語言
navigator.onLine當前是否聯網(布爾值)

6.3.4 history 對象
  • 用于操作瀏覽器歷史記錄。
方法說明
history.back()返回上一頁(等同于點擊后退)
history.forward()前進一頁
history.go(n)前進或后退 n
history.pushState(state, title, url)添加歷史記錄(不會刷新頁面)
history.replaceState(...)替換當前歷史記錄

注意:pushStatereplaceState 是 HTML5 的新特性,常用于 SPA 前端路由。


6.3.5 定時器:setTimeoutsetInterval
方法作用返回值
setTimeout(fn, delay)延遲執行一次返回定時器 ID
setInterval(fn, delay)每隔一段時間重復執行返回定時器 ID
clearTimeout(id)取消 setTimeout
clearInterval(id)取消 setInterval
示例:
const id = setTimeout(() => console.log("一次性延遲"), 1000);
clearTimeout(id);const loopId = setInterval(() => console.log("每秒執行"), 1000);
clearInterval(loopId);

?? 注意內存泄漏風險:組件銷毀/頁面離開應清理定時器。

好的,以下是對 6.3 BOM 操作 的進一步補充,涵蓋瀏覽器窗口通信、全局錯誤處理,以及實用 Web API 技巧,幫助你建立更加系統的 JavaScript 瀏覽器編程知識體系。

6.3.6 瀏覽器窗口通信:postMessage
? 場景:
  • 不同窗口/iframe 之間傳遞數據(甚至跨域);
  • 通常用于父頁面與子頁面之間的數據通信。
💡 基本語法:
// 發送方(通常是父窗口或 iframe)
otherWindow.postMessage(message, targetOrigin);// 接收方
window.addEventListener("message", function(event) {// event.data 是傳遞過來的數據// event.origin 是消息來源的域名
}, false);
? 參數說明:
參數說明
message發送的數據(可以是對象)
targetOrigin接收方的 origin(例如:"https://example.com")用于安全校驗-w41hk4oxqyc3z0h1aq79f/)
📌 示例:
// 子頁面向父頁面發送消息
window.parent.postMessage({ type: "resize", height: 600 }, "https://yourdomain.com");// 父頁面接收子頁面消息
window.addEventListener("message", (event) => {if (event.origin !== "https://yourdomain.com") return; // 安全校驗console.log("子頁面消息:", event.data);
});
6.3.7 全局錯誤處理機制
? window.onerror

用于捕獲運行時錯誤,防止頁面崩潰時無反饋。

window.onerror = function (message, source, lineno, colno, error) {console.error("捕獲錯誤:", message, "位置:", source, lineno, colno);// 可上傳日志服務器return true; // 阻止默認報錯行為
};
? window.addEventListener('error')

更強大,可以捕獲資源加載錯誤(如圖片、腳本加載失敗):

window.addEventListener("error", function (e) {if (e.target instanceof HTMLImageElement) {console.warn("圖片加載失敗:", e.target.src);}
}, true); // 第三個參數設為 true 才能捕獲資源加載錯誤
? window.addEventListener('unhandledrejection')

用于捕獲未被 .catch() 捕獲的 Promise 錯誤:

window.addEventListener("unhandledrejection", (event) => {console.error("未處理的 Promise 錯誤:", event.reason);
});
6.3.8 Web API 實用技巧
? 剪貼板 API
// 復制文本到剪貼板
navigator.clipboard.writeText("復制的內容").then(() => alert("已復制")).catch(err => console.error("復制失敗", err));// 讀取剪貼板內容(需 HTTPS 環境+用戶觸發)
navigator.clipboard.readText().then(text => console.log("讀取到剪貼板內容:", text));

?? 注意安全性:大多瀏覽器要求用戶手勢觸發(如點擊)

? 頁面可見性 API(Page Visibility)

判斷頁面是否處于活躍(當前標簽頁是否可見),適合用于:

  • 暫停動畫、視頻播放;
  • 控制數據輪詢行為等。
document.addEventListener("visibilitychange", () => {if (document.visibilityState === "hidden") {console.log("頁面不可見,暫停輪詢");} else {console.log("頁面可見,恢復輪詢");}
});
? 屏幕尺寸與滾動監聽
// 獲取滾動位置
window.scrollY; // 垂直滾動距離
window.scrollX; // 水平滾動距離// 監聽頁面滾動
window.addEventListener("scroll", () => {console.log("滾動中...", window.scrollY);
});

七、模塊化與工具鏈

7.1 模塊化發展歷程

模塊化是前端工程化的核心。它的演化反映了前端開發復雜度的提升和工具生態的進化。


7.1.1 IIFE(立即執行函數表達式)

最原始的模塊化方式,用閉包封裝變量避免污染全局作用域。

(function () {var name = "模塊內部變量";console.log(name);
})();
  • ? 優點:避免全局變量污染
  • ? 缺點:無模塊復用能力、缺乏依賴管理

7.1.2 CommonJS(Node.js 中使用)
// a.js
module.exports = {sayHi: () => console.log("Hi"),
};// b.js
const a = require("./a.js");
a.sayHi();
  • ? 特點:同步加載,適用于服務器端
  • ? 瀏覽器不支持,需要打包工具(如 Webpack)轉換

7.1.3 AMD(Asynchronous Module Definition)

瀏覽器端模塊化規范,代表庫:RequireJS

define(["moduleA"], function (moduleA) {moduleA.doSomething();
});
  • ? 特點:異步加載,適合瀏覽器
  • ? 缺點:語法繁瑣、可讀性差

7.1.4 UMD(Universal Module Definition)

兼容 CommonJS、AMD 和瀏覽器全局變量

(function (root, factory) {if (typeof define === "function" && define.amd) {define([], factory);} else if (typeof exports === "object") {module.exports = factory();} else {root.myModule = factory();}
})(this, function () {return {};
});

7.1.5 ES6 模塊化(現代主流)
// module.js
export const name = "JS模塊";
export default function greet() {console.log("Hello ES Module");
}// main.js
import greet, { name } from "./module.js";
greet();
  • ? 靜態加載、編譯時可分析依賴
  • ? 瀏覽器原生支持(需 type=“module”)
  • ? 與打包工具完美結合

7.2 前端開發工具鏈概覽

從代碼撰寫 → 轉譯兼容 → 打包構建 → 代碼規范 → 性能優化,全流程涉及以下關鍵工具:


7.2.1 構建與打包工具
工具主要用途特點
Webpack模塊打包器配置靈活、插件強大、學習曲線略高
Vite新一代構建工具極速啟動、基于原生 ESM、現代開發優選
Rollup打包庫的首選工具構建體積小,Tree-shaking 效果好

7.2.2 代碼轉譯與語法支持
工具作用
Babel將 ES6+ 代碼轉為向后兼容的 JavaScript
TypeScript增加類型系統、增強開發體驗

7.2.3 代碼質量與風格規范
工具用途
ESLint靜態代碼檢查,防止潛在錯誤
Prettier統一代碼格式,提升團隊協作效率

? 推薦配合 IDE 插件 + Git Hooks 實現自動檢查 + 修復


7.2.4 常見工具集成方式
  • 項目初始化:npm init vite@latest / create-react-app
  • 構建命令:npm run build
  • 開發模式:npm run dev(通常開啟熱更新)
  • 檢查格式:eslint src/prettier --write .

🔧 補充建議

? 強烈建議配合 husky + lint-staged 實現提交前校驗:

npx husky-init && npm install
npx husky add .husky/pre-commit "npx lint-staged"

八、ES6+ 新特性

ES6 是 ECMAScript 的重大升級版本,后續 ES7+ 持續增強語法和內置能力,使 JavaScript 更現代、更強大。以下按功能模塊系統歸納。


8.1 語法增強與數據結構

8.1.1 解構賦值

快速提取對象或數組中的值

const { name, age } = person;
const [a, b] = [1, 2];
  • ? 默認值、嵌套解構
  • ? 可用于函數參數

8.1.2 模板字符串

多行字符串 & 插值表達式

const msg = `Hello, ${user.name}!`;

8.1.3 擴展與收集運算符(...
  • 展開:將數組/對象拆開

    const arr2 = [...arr1];
    const obj2 = { ...obj1 };
    
  • 收集:函數剩余參數

    function fn(...args) {}
    

8.1.4 Symbol(獨一無二的值)

創建唯一鍵,適合定義私有屬性

const sym = Symbol('key');
obj[sym] = 'value';

8.1.5 Set & Map(全新數據結構)
特性SetMap
存儲值的集合鍵值對
是否重復否(鍵唯一)
常用方法add, has, deleteset, get, has, delete
const s = new Set([1, 2, 2]); // 去重
const m = new Map([["a", 1]]);

8.1.6 可迭代對象與 for…of

可使用 for...of...展開符 的對象:Array、Map、Set、字符串等

for (const item of set) {}

8.2 Class 與模塊系統

8.2.1 class 類定義與繼承
class Person {constructor(name) {this.name = name;}greet() {console.log(`Hi, ${this.name}`);}
}
  • ? extends 實現繼承
  • ? super() 調用父類構造器
  • ? 私有屬性:#privateName

8.2.2 模塊系統(import / export
// 導出
export const name = "Tom";
export default function greet() {}// 導入
import greet, { name } from "./module.js";
  • 支持:默認導出 / 命名導出 / 重命名 / 整體導入

8.3 常用內置 API 與語法糖

8.3.1 新增 API
方法作用
Object.entries(obj)返回鍵值對數組
Object.values(obj)返回值數組
Array.flat(depth)扁平化嵌套數組
Array.includes(val)判斷是否包含
Promise.allSettled()所有 Promise 返回后統一處理,無論成功失敗

8.3.2 Nullish Coalescing(??

只有 nullundefined 才觸發右側默認值

const val = input ?? "默認值";
  • ? 不會因 ''0 而觸發

8.3.3 Optional Chaining(?.

安全讀取深層屬性,避免報錯

const city = user?.address?.city;

🔍 記憶建議:

  • ? 解構 & 展開:多寫函數參數和對象操作
  • ? Symbol:對象私有成員
  • ? Set/Map:處理去重與映射優于 Object
  • ? ?? 與 ?.:null 安全寫法,高頻出現于項目中

九、瀏覽器通信與網絡

現代前端開發離不開瀏覽器與服務器之間的高效通信,本章將系統梳理 AJAX、跨域機制、本地存儲方案與 Web 通信能力。


9.1 瀏覽器請求方式

9.1.1 XMLHttpRequest 基礎(XHR)
  • 原始的 AJAX 技術核心
  • 支持事件監聽與狀態碼處理
const xhr = new XMLHttpRequest();
xhr.open('GET', '/api/data');
xhr.onreadystatechange = function () {if (xhr.readyState === 4 && xhr.status === 200) {console.log(xhr.responseText);}
};
xhr.send();

9.1.2 Fetch API

更現代的異步請求方式,基于 Promise

fetch('/api/data').then(res => res.json()).then(data => console.log(data)).catch(err => console.error(err));
  • ? 更簡潔
  • ? 默認不攜帶 cookie(需配置)
  • ? 不會自動 reject 4xx/5xx(需手動判斷 res.ok

9.1.3 封裝 Fetch 常用方法
async function request(url, options = {}) {const res = await fetch(url, options);if (!res.ok) throw new Error('網絡錯誤');return res.json();
}

9.2 跨域處理策略

9.2.1 同源策略

協議 + 域名 + 端口號 三者相同才算同源
不同源會受到限制(如 DOM 操作、AJAX 請求)


9.2.2 解決方式對比
方法原理優缺點
CORS設置響應頭 Access-Control-Allow-Origin推薦,標準方案
JSONP利用 <script> 標簽不受同源限制僅支持 GET,請求安全性差
代理轉發本地服務器轉發請求,繞過瀏覽器限制需后端支持,常見于開發環境
PostMessage窗口間通信(iframe 或新窗口)跨域數據安全通信

9.3 本地存儲方式對比

9.3.1 Cookie
  • 每次請求自動攜帶,常用于身份驗證
  • 有大小限制(~4KB)
  • 支持設置過期時間、路徑、域
document.cookie = "token=123;path=/;max-age=3600";

9.3.2 localStorage
  • 永久存儲(直到手動清除)
  • 單域名下最大約 5MB
  • 僅支持字符串
localStorage.setItem("key", "value");
localStorage.getItem("key");

9.3.3 sessionStorage
  • 頁面會話級別,標簽頁關閉即清除
  • API 與 localStorage 相同

? 對比總結:
特性CookielocalStoragesessionStorage
是否隨請求發送???
生命周期可設置永久會話
大小限制4KB5MB+5MB+
跨標簽頁共享???

9.4 實用通信機制補充

9.4.1 瀏覽器窗口通信:postMessage

用于主窗口與 iframe / 子窗口 / 彈窗間安全通信

window.postMessage("數據", "https://other.com");window.addEventListener("message", (event) => {console.log(event.origin, event.data);
});

9.4.2 全局錯誤監聽
  • 捕獲 JS 報錯信息,便于上報與監控
window.onerror = function (msg, url, line, col, error) {console.error('捕獲錯誤:', msg, error);
};window.addEventListener('error', (event) => {console.log('資源加載錯誤:', event.target);
});

9.4.3 實用 Web API 技巧
API功能示例
navigator.clipboard.writeText()寫入剪貼板復制文本
document.visibilityState頁面可見性檢測visibilitychange 監聽
navigator.onLine網絡狀態檢測離線/在線判斷
Performance API頁面性能分析performance.now()

好的,下面是第九章:瀏覽器通信與網絡的進一步補充,涵蓋更深入的網絡通信機制及相關 API,包括 WebSocket、服務端事件(SSE)、網絡狀態檢測、離線緩存等內容。


9.5 實時通信技術

9.5.1 WebSocket 長連接

一種在單個 TCP 連接上進行全雙工通信的協議,適合實時聊天、推送通知等場景。

使用示例:

const socket = new WebSocket('wss://example.com/socket');socket.onopen = () => {socket.send('Hello Server!');
};socket.onmessage = (event) => {console.log('收到消息:', event.data);
};socket.onerror = (err) => console.error('連接錯誤:', err);
socket.onclose = () => console.log('連接關閉');
  • ? 持久連接,適合高頻交互
  • ? 需服務端配套支持,維護成本高

9.5.2 Server-Sent Events(SSE)

瀏覽器從服務端接收單向推送數據(基于 HTTP)

const source = new EventSource('/api/events');source.onmessage = function (event) {console.log('服務端推送:', event.data);
};
  • ? 簡潔、自動重連、支持事件命名
  • ? 只支持單向、部分瀏覽器支持

9.6 網絡狀態與頁面生命周期

9.6.1 網絡狀態檢測
console.log(navigator.onLine); // true or falsewindow.addEventListener('online', () => console.log('網絡恢復'));
window.addEventListener('offline', () => console.log('網絡斷開'));

9.6.2 頁面可見性檢測
document.addEventListener('visibilitychange', () => {if (document.visibilityState === 'hidden') {console.log('頁面隱藏');} else {console.log('頁面可見');}
});
  • 可用于暫停動畫、視頻、輪詢請求

9.7 離線緩存與存儲技術

9.7.1 Cache API(Service Worker)

配合 Service Worker 實現離線緩存、離線訪問頁面內容

caches.open('v1').then(cache => {cache.addAll(['/index.html', '/styles.css']);
});
  • 與 fetch 結合,可攔截請求并返回緩存
  • 需 HTTPS 環境下注冊 Service Worker

9.7.2 IndexedDB

瀏覽器提供的事務型數據庫,可存儲結構化數據

const request = indexedDB.open('myDB', 1);
request.onsuccess = (event) => {const db = event.target.result;console.log('數據庫打開成功');
};
  • 支持索引、事務、高容量數據
  • 常用于大型離線 Web 應用(PWA)

9.8 網絡調優與安全

9.8.1 請求優化技巧
  • 開啟 Keep-Alive 復用連接
  • 使用 CDN 緩存靜態資源
  • 圖片懶加載 + 資源壓縮
  • 合理使用緩存頭部(Cache-Control、ETag)

9.8.2 網絡安全機制
  • HTTPS 加密傳輸
  • 防 XSS/CSRF 攻擊
  • 輸入校驗與輸出轉義
  • 設置 Content-Security-Policy 安全策略頭

十、性能優化與安全

10.1 性能優化

10.1.1 資源懶加載

將不在視口內的資源延遲加載,減少初始加載時間。

  • 圖片懶加載:
<img data-src="image.jpg" class="lazyload" alt="Lazy Load Image">
  • JavaScript 懶加載:
const script = document.createElement('script');
script.src = 'path/to/your/script.js';
document.body.appendChild(script);
  • 適用場景: 圖片、視頻、JavaScript 等
10.1.2 事件節流與防抖

節流 (Throttling)防抖 (Debouncing) 用于控制頻繁觸發的事件,如滾動、輸入等。

  • 防抖:
function debounce(fn, delay) {let timer;return function (...args) {clearTimeout(timer);timer = setTimeout(() => fn(...args), delay);};
}
  • 節流:
function throttle(fn, delay) {let last = 0;return function (...args) {const now = Date.now();if (now - last >= delay) {last = now;fn(...args);}};
}
10.1.3 DOM 優化
  • 減少 DOM 操作: 批量更新、避免頻繁重排與重繪(例如使用 DocumentFragment
  • 緩存查詢結果: 存儲對 DOM 的查詢結果,避免重復查找
const button = document.getElementById('myButton');
// 使用變量緩存 DOM 查找
10.1.4 異步加載與延遲加載
  • 異步加載: 使用 asyncdefer 屬性來異步加載 JavaScript 文件,避免阻塞渲染。
<script src="script.js" async></script>
<script src="script.js" defer></script>
  • 分塊加載: 使用 Webpack 等工具進行代碼分塊,按需加載,提升初次加載速度。
10.1.5 緩存策略

緩存能夠顯著提高性能,減少重復的網絡請求。

  • Service Worker + Cache API: 在瀏覽器端緩存資源,離線訪問。
  • HTTP 緩存: 使用 Cache-ControlETag 頭部進行緩存控制。
// 在 Service Worker 中緩存請求資源
caches.open('v1').then((cache) => {cache.add('/index.html');
});
  • LocalStorage / IndexedDB: 在本地存儲應用數據,避免頻繁請求數據。
10.1.6 圖片與視頻優化
  • 圖片格式優化: 使用現代格式(如 WebP)來減少圖片大小。
  • SVG 圖標替代位圖圖標:SVG 比 PNG/JPG 更加靈活且文件更小。
  • 懶加載: 只在用戶滾動到頁面時才加載圖片。

10.2 前端安全

10.2.1 XSS(跨站腳本攻擊)

攻擊者通過注入惡意腳本,竊取用戶數據或篡改網頁內容。

  • 防御方法:
    • 輸入驗證與輸出編碼: 對用戶輸入進行嚴格的驗證和轉義,避免腳本執行。
    • 使用 CSP(內容安全策略) 來限制加載的腳本源。
<meta http-equiv="Content-Security-Policy" content="script-src 'self'">
  • 避免內聯腳本: 使用外部腳本文件,禁止內聯 JavaScript 代碼。
10.2.2 CSRF(跨站請求偽造)

攻擊者偽造用戶請求,造成未授權操作。

  • 防御方法:
    • Token 驗證: 每次提交請求時,附加一個唯一的 CSRF Token(在表單或請求頭中傳遞),服務器驗證是否匹配。
    • SameSite Cookies: 使用 SameSite 屬性,限制 Cookie 在跨站請求時是否隨請求一起發送。
document.cookie = "token=your_token; SameSite=Strict;";
10.2.3 Clickjacking(點擊劫持)

攻擊者通過透明 iframe 誘使用戶點擊其并非意圖點擊的內容。

  • 防御方法:
    • 使用 X-Frame-Options 頭部阻止頁面被嵌套在 iframe 中。
<meta http-equiv="X-Frame-Options" content="DENY">
10.2.4 內容安全策略(CSP)

CSP 是一種防止 XSS 攻擊的安全機制,限制瀏覽器加載資源的源。

  • 基本 CSP 配置:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline';">
  • 策略設計:
    • default-src:指定默認的加載源
    • script-src:限制腳本的來源
    • style-src:限制樣式的來源
10.2.5 其他前端安全防護
  • HTTPOnly Cookie: 防止 JavaScript 訪問 Cookie,增強安全性。
  • HSTS(HTTP 嚴格傳輸安全): 強制瀏覽器與服務器之間使用 HTTPS 通信。
// 在服務器上啟用 HSTS
Strict-Transport-Security: max-age=31536000; includeSubDomains
  • 兩步驗證: 通過發送驗證碼或短信來加強用戶的身份驗證。

十一、項目實戰與面試要點

11.1 項目實踐

  • Todo List、畫板、購物車、小型 SPA 實現
  • 調試技巧與錯誤捕獲(Try/Catch、window.onerror)

11.2 面試高頻題

  • 手寫 Promise、深拷貝、節流/防抖
  • 輸出題、閉包題、原型繼承題

十二、進階方向推薦

  • TypeScript 基礎與應用
  • React / Vue / Svelte 框架精通
  • 前端架構、微前端、性能監控
  • WebAssembly、Serverless、PWA

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/905401.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/905401.shtml
英文地址,請注明出處:http://en.pswp.cn/news/905401.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[Java實戰]Spring Boot 3 整合 Apache Shiro(二十一)

[Java實戰]Spring Boot 3 整合 Apache Shiro&#xff08;二十一&#xff09; 引言 在復雜的業務系統中&#xff0c;安全控制&#xff08;認證、授權、加密&#xff09;是核心需求。相比于 Spring Security 的重量級設計&#xff0c;Apache Shiro 憑借其簡潔的 API 和靈活的擴…

PyTorch API 6 - 編譯、fft、fx、函數轉換、調試、符號追蹤

文章目錄 torch.compiler延伸閱讀 torch.fft快速傅里葉變換輔助函數 torch.func什么是可組合的函數變換&#xff1f;為什么需要可組合的函數變換&#xff1f;延伸閱讀 torch.futurestorch.fx概述編寫轉換函數圖結構快速入門圖操作直接操作計算圖使用 replace_pattern() 進行子圖…

可觀測性方案怎么選?SelectDB vs Elasticsearch vs ClickHouse

可觀測性&#xff08;Observability&#xff09;是指通過系統的外部輸出數據&#xff0c;推斷其內部狀態的能力。可觀測性平臺通過采集、存儲、可視化分析三大可觀測性數據&#xff1a;日志&#xff08;Logging&#xff09;、鏈路追蹤&#xff08;Tracing&#xff09;和指標&am…

機器人廚師上崗!AI在餐飲界掀起新風潮!

想要了解人工智能在其他各個領域的應用&#xff0c;可以查看下面一篇文章 《AI在各領域的應用》 餐飲業是與我們日常生活息息相關的行業&#xff0c;而人工智能&#xff08;AI&#xff09;正在迅速改變這個傳統行業的面貌。從智能點餐到食材管理&#xff0c;再到個性化推薦&a…

Linux動態庫靜態庫總結

靜態庫生成 g -c mylib.cpp -o mylib.o ar rcs libmylib.a mylib.o 動態庫生成 g -fPIC -shared mylib.cpp -o libmylib.so -fPIC&#xff1a;生成位置無關代碼&#xff08;Position-Independent Code&#xff09;&#xff0c;對動態庫必需。 庫文件使用&#xff1a; 靜態庫&…

通過user-agent來源判斷阻止爬蟲訪問網站,并防止生成[ error ] NULL日志

一、TP5.0通過行為&#xff08;Behavior&#xff09;攔截爬蟲并避免生成 [ error ] NULL 錯誤日志 1. 創建行為類&#xff08;攔截爬蟲&#xff09; 在 application/common/behavior 目錄下新建BlockBot.php &#xff0c;用于識別并攔截爬蟲請求&#xff1a; <?php name…

OpenHarmony平臺驅動開發(十五),SDIO

OpenHarmony平臺驅動開發&#xff08;十五&#xff09; SDIO 概述 功能簡介 SDIO&#xff08;Secure Digital Input and Output&#xff09;由SD卡發展而來&#xff0c;與SD卡統稱為MMC&#xff08;MultiMediaCard&#xff09;&#xff0c;二者使用相同的通信協議。SDIO接口…

使用FastAPI和React以及MongoDB構建全棧Web應用03 全棧開發快速入門

一、什么是全棧開發 A full-stack web application is a complete software application that encompasses both the frontend and backend components. It’s designed to interact with users through a web browser and perform actions that involve data processing and …

Coco AI 開源應用程序 - 搜索、連接、協作、您的個人 AI 搜索和助手,都在一個空間中。

一、軟件介紹 文末提供程序和源碼下載 Coco AI 是一個統一的搜索平臺&#xff0c;可將您的所有企業應用程序和數據&#xff08;Google Workspace、Dropbox、Confluent Wiki、GitHub 等&#xff09;連接到一個功能強大的搜索界面中。此存儲庫包含為桌面和移動設備構建的 Coco 應…

CSS經典布局之圣杯布局和雙飛翼布局

目標&#xff1a; 中間自適應&#xff0c;兩邊定寬&#xff0c;并且三欄布局在一行展示。 圣杯布局 實現方法&#xff1a; 通過float搭建布局margin使三列布局到一行上relative相對定位調整位置&#xff1b; 給外部容器添加padding&#xff0c;通過相對定位調整左右兩列的…

# 實時英文 OCR 文字識別:從攝像頭到 PyQt5 界面的實現

實時英文 OCR 文字識別&#xff1a;從攝像頭到 PyQt5 界面的實現 引言 在數字化時代&#xff0c;文字識別技術&#xff08;OCR&#xff09;在眾多領域中發揮著重要作用。無論是文檔掃描、車牌識別還是實時視頻流中的文字提取&#xff0c;OCR 技術都能提供高效且準確的解決方案…

<C#>log4net 的配置文件配置項詳細介紹

log4net 是一個功能強大的日志記錄工具&#xff0c;通過配置文件可以靈活地控制日志的輸出方式、格式、級別等。以下是對 log4net 配置文件常見配置項的詳細介紹&#xff1a; 根元素 <log4net> 這是 log4net 配置文件的根元素&#xff0c;所有配置項都要包含在該元素內…

編譯docker版openresty

使用alpine為基礎鏡像 # 使用Alpine作為基礎鏡像 FROM alpine:3.18# 替換為阿里云鏡像源&#xff0c;并安裝必要的依賴 RUN sed -i s|https://dl-cdn.alpinelinux.org/alpine|https://mirrors.aliyun.com/alpine|g /etc/apk/repositories && \apk add --no-cache \bui…

conda 輸出指定python環境的庫 輸出為 yaml文件

conda 輸出指定python環境的庫 輸出為 yaml文件。 有時為了項目部署&#xff0c;需要匹配之前的python環境&#xff0c;需要輸出對應的python依賴庫。 假設你的目標環境名為 myenv&#xff0c;運行以下命令&#xff1a; conda env export -n myenv > myenv_environment.ym…

[Java][Leetcode middle] 121. 買賣股票的最佳時機

暴力循環 總是以最低的價格買入&#xff0c;以最高的價格賣出: 例如第一天買入&#xff0c;去找剩下n-1天的最高價格&#xff0c;計算利潤 依次計算到n-1天買入&#xff1b; 比較上述利潤 // 運行時間超時。 o(n^2)public int maxProfit1(int[] prices) {int profit 0;for (i…

克隆虛擬機組成集群

一、克隆虛擬機 1. 準備基礎虛擬機 確保基礎虛擬機已安裝好操作系統&#xff08;如 Ubuntu&#xff09;、Java 和 Hadoop。關閉防火墻并禁用 SELinux&#xff08;如適用&#xff09;&#xff1a; bash sudo ufw disable # Ubuntu sudo systemctl disable firewalld # CentO…

記錄一次使用thinkphp使用PhpSpreadsheet擴展導出數據,解決身份證號碼等信息科學計數法問題處理

PhpSpreadsheet官網 PhpSpreadsheet安裝 composer require phpoffice/phpspreadsheet使用composer安裝時一定要下載php對應的版本&#xff0c;下載之前使用php -v檢查當前php版本 簡單使用 <?php require vendor/autoload.php;use PhpOffice\PhpSpreadsheet\Spreadshee…

前端工程化:從 Webpack 到 Vite

引言 前端工程化是現代Web開發不可或缺的一部分&#xff0c;它通過自動化流程和標準化實踐&#xff0c;提高了開發效率和代碼質量。在這個領域中&#xff0c;構建工具扮演著核心角色&#xff0c;而Webpack和Vite則是其中的兩位重要角色。本文將探討前端工程化的演進歷程&#…

Leetcode 3543. Maximum Weighted K-Edge Path

Leetcode 3543. Maximum Weighted K-Edge Path 1. 解題思路2. 代碼實現 題目鏈接&#xff1a;3543. Maximum Weighted K-Edge Path 1. 解題思路 這一題思路上就是一個遍歷的思路&#xff0c;我們只需要考察每一個節點作為起點時&#xff0c;所有長為 k k k的線段的長度&…

香橙派zero3 安卓TV12,更換桌面launcher,開機自啟動kodi

打開開發者模式&#xff0c;連擊版本號&#xff0c;基本上都是這樣。 adb連接 查找桌面包名 adb shell dumpsys activity activities | findstr mResumedActivity 禁用原桌面com.android.tv.launcher&#xff0c;已經安裝了projectivylauncher434.apk桌面。 adb shell pm …