目錄
一、聲明變量
(1)let
(2)const
(3)var
var、let 和 const 的作用域差異
二、數據類型?
(1)基本類型
undefined和null
String?
模板字符串拼接:
number和bigint?
字符串轉換為整數?:
?boolean
symbol
二、對象類型?
(1)Function函數
1.函數聲明
2.函數表達式?
3.箭頭函數
4.匿名函數
函數作用域
閉包?
(2)Array數組
常用數組方法
1.添加/刪除元素
?2.合并/拼接數組
?3.查找元素
?4.遍歷數組
?5.排序和反轉
?6.其他實用方法
7. ES6+ 新增數組特性
1.擴展運算符
2. 解構賦值
?3.Array.from()
(3)Object對象
創建對象
訪問屬性
添加/修改屬性
刪除屬性
常用靜態方法
?對象實例方法
原型與繼承
原型基礎
更規范的繼承方式
構造函數與原型
ES6+ 對象新特性
屬性簡寫
計算屬性名
對象解構
擴展運算符
對象與JSON
一、聲明變量
(1)let
- let聲明的變量可以多次賦值。
(2)const
- const修飾的值叫常量,只能賦值一次。
(3)var
- var聲明的變量可以多次賦值。
var、let 和 const 的作用域差異
-
var:函數作用域
- 在函數內部聲明的變量只能在函數內部訪問
- 沒有塊級作用域
-
let/const:塊級作用域
- 在 {} 塊中聲明的變量只能在該塊中訪問
- 解決了 var 的變量提升和重復聲明問題
function varExample() {if (true) {var x = 10;let y = 20;}console.log(x); // 10 (var 沒有塊級作用域)console.log(y); // 報錯:y is not defined (let 有塊級作用域)
}varExample();
二、數據類型?
(1)基本類型
undefined和null
undefined表示變量已被聲明,但尚未被賦值。也就是說,變量存在,但沒有具體的值。
-
變量聲明后未賦值時,默認值為
undefined
。 -
如果函數沒有返回值,那么它的返回值默認也是
undefined
。 -
如果訪問對象中不存在的屬性,其值也是
undefined
。let a; // 聲明變量 a,未賦值 console.log(a); // 輸出:undefinedfunction test() {// 沒有返回值 } console.log(test()); // 輸出:undefinedconst obj = {}; console.log(obj.property); // 輸出:undefined
null表示“空值”或“無對象”。
-
明確表示變量的值為空,而不是未賦值。
-
在類型檢查中,
null
是一個獨立的類型,即null
的類型是object
總結:
-
undefined
表示變量未被賦值,是一個“未定義”的狀態。 -
null
表示變量被明確賦值為空,是一個“空值”或“無對象”的狀態。
String?
字符串是由字符組成的序列,用于表示文本數據。在 JavaScript 中,字符串可以用單引號('
)、雙引號("
)或反引號(`
)來定義。?
let singleQuoted = 'Hello, world!';
let doubleQuoted = "Hello, world!";
let backtickQuoted = `Hello, world!`;console.log(singleQuoted); // 輸出:Hello, world!
console.log(doubleQuoted); // 輸出:Hello, world!
console.log(backtickQuoted); // 輸出:Hello, world!
傳統字符串拼接:
let name = "Alice";
let age = 30;
let greeting = "Hello, " + name + "! You are " + age + " years old.";
console.log(greeting); // 輸出:Hello, Alice! You are 30 years old.
模板字符串拼接:
(模板字符串是 ES6 的新特性)
模板字符串(Template Literals)是 ES6 引入的一種新的字符串表示方式,使用反引號(`
)定義,并支持嵌入表達式和多行字符串。
let name = "Alice";
let age = 30;
let greeting = `Hello, ${name}! You are ${age} years old.`;
console.log(greeting); // 輸出:Hello, Alice! You are 30 years old.
number和bigint?
Number
類型基于 IEEE 754 標準的雙精度浮點數表示,因此可以表示小數。可以表示的數值范圍是 -2^53 + 1
到 2^53 - 1。
由于 Number
是基于浮點數表示的,因此在處理大整數或高精度計算時可能會出現精度問題。
console.log(0.1 + 0.2); // 輸出:0.30000000000000004
console.log(9007199254740991 + 1); // 輸出:9007199254740992
console.log(9007199254740992 + 1); // 輸出:9007199254740992(精度丟失)
字符串轉換為整數?:
1.parseInt
console.log(parseInt("12345")); // 輸出:12345
console.log(parseInt("123.45")); // 輸出:123(忽略小數部分)
console.log(parseInt("123abc")); // 輸出:123(忽略非數字部分)
console.log(parseInt("abc123")); // 輸出:NaN(開頭不是數字)
?2.Number
構造函數
console.log(Number("123.45")); // 輸出:123.45
console.log(Number("123abc")); // 輸出:NaN
?3.一元加號運算符
console.log(+ "123.45"); // 輸出:123.45
console.log(+ "123abc"); // 輸出:NaN
?BigInt
是 ES2020 引入的一種新的數值類型,用于表示任意大小的整數。BigInt
可以表示任意大小的整數,沒有上限。BigInt
保證整數的精確表示,不會出現精度問題。BigInt
字面量以 n
結尾,例如 123n。BigInt
支持基本的算術運算,但不能與 Number
類型直接進行運算,需要顯式轉換。
// Number
let num1 = 12345678901234567890;
let num2 = 12345678901234567890;
console.log(num1 + num2); // 輸出:24691357802469135780,但可能會有精度問題// BigInt
let bigInt1 = 12345678901234567890n;
let bigInt2 = 12345678901234567890n;
console.log(bigInt1 + bigInt2); // 輸出:24691357802469135780n,精確無誤
?boolean
在 JavaScript 中,truthy 和 falsy 是兩個非常重要的概念,用于描述值在布爾上下文中的表現。這些概念在條件語句(如 if
、while
等)和邏輯運算中非常重要。
falsy:false、0、-0、""(空字符串)、null、undefined、NaN
truthy:true、1、{}(空對象)、[](空數組)等。
symbol
在 JavaScript 中,Symbol
是一種原始數據類型,用于表示唯一的、不可變的值。Symbol
是 ES6(ECMAScript 2015)引入的,旨在解決對象屬性名稱沖突的問題,并提供一種更安全的方式來定義對象的屬性。
二、對象類型?
(1)Function函數
函數本質上是對象。這使得函數具有對象的特性,例如可以擁有屬性和方法,可以作為變量賦值,可以作為參數傳遞,也可以作為返回值。這種特性使得 JavaScript 的函數非常強大和靈活。
1.函數聲明
function greet(name) {return `Hello, ${name}!`;
}console.log(greet("Alice")); // 輸出:Hello, Alice!
2.函數表達式?
const greet = function(name) {return `Hello, ${name}!`;
};console.log(greet("Bob")); // 輸出:Hello, Bob!
3.箭頭函數
ES6 引入了箭頭函數(Arrow Function),它是一種更簡潔的匿名函數語法。箭頭函數省略了 function
關鍵字,并且可以省略花括號和 return
關鍵字(如果函數體只有一條語句)。
const greet = (name) => `Hello, ${name}!`;console.log(greet("Charlie")); // 輸出:Hello, Charlie!
4.匿名函數
匿名函數也經常被用作高階函數的參數,例如 map
、filter
和 reduce
。
const numbers = [1, 2, 3, 4, 5];
const squared = numbers.map(function(num) {return num * num;
});console.log(squared); // 輸出:[1, 4, 9, 16, 25]
函數作用域
- 函數作用域:在函數內部聲明的變量只能在函數內部訪問
- 局部變量:函數內部聲明的變量
- 全局變量:函數外部聲明的變量
JavaScript 使用作用域鏈來解析變量:
- 首先在當前函數作用域查找
- 如果找不到,向上一級作用域查找
- 直到全局作用域
- 如果全局作用域也沒有,則報錯
var a = 1;function outer() {var b = 2;function inner() {var c = 3;console.log(a + b + c); // 6 (可以訪問所有外層變量)}inner();
}outer();
閉包?
閉包是指一個函數能夠記住并訪問其詞法作用域,即使該函數在其詞法作用域之外執行。
簡單來說,閉包讓函數可以"記住"它被創建時的環境,即使這個函數在創建它的環境之外被調用。
function outer() {let count = 0; // 外部函數的局部變量function inner() {count++; // 內部函數訪問外部函數的變量console.log(count);}return inner; // 返回內部函數
}const counter = outer();
counter(); // 1
counter(); // 2
counter(); // 3
?在這個例子中,inner
函數就是一個閉包,它可以訪問 outer
函數的 count
變量,即使 outer
函數已經執行完畢
閉包的特點
1.記憶環境:閉包會記住創建時的詞法環境
2.持久性:閉包中的變量會一直存在,不會被垃圾回收
3.私有性:可以創建私有變量和方法
(2)Array數組
常用數組方法
1.添加/刪除元素
方法 | 描述 | 返回值 | 是否修改原數組 |
---|---|---|---|
push() | 末尾添加一個或多個元素 | 新長度 | 是 |
pop() | 刪除最后一個元素 | 被刪除元素 | 是 |
unshift() | 開頭添加一個或多個元素 | 新長度 | 是 |
shift() | 刪除第一個元素 | 被刪除元素 | 是 |
let arr = [1, 2, 3];arr.push(4); // [1, 2, 3, 4]
arr.pop(); // [1, 2, 3]
arr.unshift(0); // [0, 1, 2, 3]
arr.shift(); // [1, 2, 3]
?2.合并/拼接數組
// concat() - 合并數組(不修改原數組)
let arr1 = [1, 2];
let arr2 = [3, 4];
let combined = arr1.concat(arr2); // [1, 2, 3, 4]// splice() - 強大的數組修改方法(修改原數組)
let fruits = ['Apple', 'Banana', 'Orange'];
fruits.splice(1, 1, 'Mango', 'Peach');
// 從索引1開始,刪除1個元素,插入'Mango'和'Peach'
// 結果: ['Apple', 'Mango', 'Peach', 'Orange']
?3.查找元素
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];// indexOf() - 查找元素首次出現的位置
console.log(numbers.indexOf(3)); // 2// lastIndexOf() - 查找元素最后一次出現的位置
console.log(numbers.lastIndexOf(3)); // 6// includes() - 檢查是否包含某元素
console.log(numbers.includes(5)); // true// find() - 查找第一個符合條件的元素
let found = numbers.find(item => item > 3); // 4// findIndex() - 查找第一個符合條件的元素索引
let foundIndex = numbers.findIndex(item => item > 3); // 3
?4.遍歷數組
let fruits = ['Apple', 'Banana', 'Orange'];// forEach() - 遍歷數組
fruits.forEach(function(item, index) {console.log(index, item);
});// map() - 映射新數組
let lengths = fruits.map(fruit => fruit.length); // [5, 6, 6]// filter() - 過濾數組
let longFruits = fruits.filter(fruit => fruit.length > 5); // ['Banana', 'Orange']// reduce() - 累積計算
let numbers = [1, 2, 3, 4];
let sum = numbers.reduce((total, num) => total + num, 0); // 10
?5.排序和反轉
let numbers = [3, 1, 4, 2, 5];// sort() - 排序(修改原數組)
numbers.sort(); // [1, 2, 3, 4, 5]// 自定義排序
let scores = [88, 95, 70, 92];
scores.sort((a, b) => b - a); // 降序排序 [95, 92, 88, 70]// reverse() - 反轉數組(修改原數組)
numbers.reverse(); // [5, 4, 3, 2, 1]
?6.其他實用方法
// slice() - 截取數組(不修改原數組)
let arr = [1, 2, 3, 4, 5];
let part = arr.slice(1, 3); // [2, 3]// join() - 數組轉字符串
let str = arr.join('-'); // "1-2-3-4-5"// Array.isArray() - 檢查是否為數組
console.log(Array.isArray(arr)); // true// fill() - 填充數組
let newArr = new Array(3).fill(0); // [0, 0, 0]// flat() - 扁平化數組
let nested = [1, [2, [3]]];
let flatArr = nested.flat(2); // [1, 2, 3]
7. ES6+ 新增數組特性
1.擴展運算符
// 復制數組
let arr = [1, 2, 3];
let arrCopy = [...arr]; // [1, 2, 3]// 合并數組
let combined = [...arr, 4, 5, ...[6, 7]]; // [1, 2, 3, 4, 5, 6, 7]
2. 解構賦值
let [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]
?3.Array.from()
// 從類數組對象創建數組
let arrayLike = {0: 'a', 1: 'b', length: 2};
let realArray = Array.from(arrayLike); // ['a', 'b']// 從可迭代對象創建數組
let set = new Set([1, 2, 3]);
let arrayFromSet = Array.from(set); // [1, 2, 3]
(3)Object對象
對象是 JavaScript 中最重要的數據類型之一,用于存儲鍵值對集合。幾乎所有 JavaScript 的值都可以視為對象,除了原始類型(string、number、boolean、null、undefined、symbol、bigint)。
創建對象
// 1. 對象字面量語法(最常用)
let person = {name: '張三',age: 30,isStudent: false
};// 2. 使用 Object 構造函數
let car = new Object();
car.make = 'Toyota';
car.model = 'Camry';// 3. 使用 Object.create()
let animal = Object.create(null);
animal.type = 'dog';
訪問屬性
// 點表示法
console.log(person.name); // '張三'// 方括號表示法(適用于動態屬性名或包含特殊字符的屬性名)
console.log(person['age']); // 30let key = 'isStudent';
console.log(person[key]); // false
添加/修改屬性
// 添加新屬性
person.job = '工程師';// 修改現有屬性
person.age = 31;// 使用方括號表示法
person['favorite color'] = '藍色'; // 屬性名包含空格時
刪除屬性
delete person.isStudent; // 刪除屬性
console.log(person.isStudent); // undefined
常用靜態方法
// Object.keys() - 獲取對象所有可枚舉屬性的鍵
let keys = Object.keys(person); // ['name', 'age', 'job', 'favorite color']// Object.values() - 獲取對象所有可枚舉屬性的值
let values = Object.values(person); // ['張三', 31, '工程師', '藍色']// Object.entries() - 獲取鍵值對數組
let entries = Object.entries(person);
// [ ['name', '張三'], ['age', 31], ['job', '工程師'], ['favorite color', '藍色'] ]// Object.assign() - 合并對象(淺拷貝)
let target = { a: 1 };
let source = { b: 2, c: 3 };
Object.assign(target, source); // { a: 1, b: 2, c: 3 }// Object.freeze() - 凍結對象,防止修改
let frozenObj = Object.freeze({ x: 1 });
frozenObj.x = 2; // 靜默失敗(嚴格模式下會報錯)
?對象實例方法
let obj = {name: '示例對象',// 定義方法greet: function() {return `你好,我是${this.name}`;},// ES6簡寫方法語法sayHello() {return 'Hello!';}
};console.log(obj.greet()); // "你好,我是示例對象"
console.log(obj.sayHello()); // "Hello!"
原型與繼承
原型基礎
// 每個對象都有一個原型(__proto__屬性,不推薦直接使用)
let animal = {eats: true
};let rabbit = {jumps: true,__proto__: animal // 設置原型(現代寫法應使用Object.create)
};console.log(rabbit.eats); // true (通過原型繼承)
更規范的繼承方式
// 使用Object.create()創建帶有指定原型的對象
let animal = {eats: true
};let rabbit = Object.create(animal);
rabbit.jumps = true;console.log(rabbit.eats); // true
構造函數與原型
// 構造函數
function Person(name, age) {this.name = name;this.age = age;
}// 通過原型添加方法
Person.prototype.greet = function() {return `你好,我是${this.name},今年${this.age}歲`;
};let john = new Person('John', 30);
console.log(john.greet()); // "你好,我是John,今年30歲"
ES6+ 對象新特性
屬性簡寫
let name = '李四';
let age = 25;let person = {name, // 等同于 name: nameage, // 等同于 age: agegreet() {return `我是${this.name}`;}
};
計算屬性名
let propKey = 'foo';let obj = {[propKey]: true,['b' + 'ar']: 123,[Symbol('id')]: 'symbolId'
};console.log(obj.foo); // true
console.log(obj.bar); // 123
對象解構
let options = {title: '菜單',width: 100,height: 200
};// 解構賦值
let { title, width, height } = options;console.log(title); // '菜單'
console.log(width); // 100
console.log(height); // 200
擴展運算符
let obj1 = { a: 1, b: 2 };
let obj2 = { c: 3, d: 4 };let merged = { ...obj1, ...obj2 }; // { a: 1, b: 2, c: 3, d: 4 }
對象與JSON
// 對象轉JSON字符串
let user = {name: "張三",age: 30
};let json = JSON.stringify(user);
console.log(json); // '{"name":"張三","age":30}'// JSON字符串轉對象
let parsed = JSON.parse(json);
console.log(parsed.name); // "張三"