JavaScript 對象說明
1. 對象的基本概念
在 JavaScript 中,對象是一種復合數據類型,用于存儲相關聯的屬性和方法。對象可以看作是屬性的集合,其中每個屬性都由一個鍵(key)和一個值(value)組成。值可以是任何 JavaScript 數據類型,包括數字、字符串、布爾值、數組、函數,甚至是其他對象。
JavaScript 對象具有以下特點:
- 是一種引用數據類型
- 具有動態特性,可以隨時添加、修改或刪除屬性
- 支持原型繼承
- 可以通過多種方式創建
2. 創建對象的方法
2.1 對象字面量
對象字面量是創建對象最常用和最簡潔的方法,使用花括號 {}
定義。
// 空對象
const emptyObject = {};// 包含屬性的對象
const person = {name: "張三",age: 30,isStudent: false,hobbies: ["閱讀", "編程", "旅行"],address: {city: "北京",district: "朝陽區"},sayHello: function() {console.log(`你好,我是${this.name}!`);}
};
2.2 使用 new Object() 構造函數
const person = new Object();
person.name = "張三";
person.age = 30;
person.sayHello = function() {console.log(`你好,我是${this.name}!`);
};
2.3 使用 Object.create() 方法
Object.create()
方法創建一個新對象,使用現有的對象作為新對象的原型。
// 創建一個原型對象
const personPrototype = {sayHello: function() {console.log(`你好,我是${this.name}!`);}
};// 使用原型對象創建新對象
const person = Object.create(personPrototype);
person.name = "張三";
person.age = 30;
2.4 構造函數模式
使用構造函數可以創建多個具有相同屬性和方法的對象實例。
// 定義構造函數
function Person(name, age) {this.name = name;this.age = age;this.sayHello = function() {console.log(`你好,我是${this.name}!`);};
}// 使用 new 關鍵字創建對象實例
const person1 = new Person("張三", 30);
const person2 = new Person("李四", 25);
2.5 原型模式
將方法定義在構造函數的原型上,可以讓所有實例共享這些方法,節省內存。
// 定義構造函數
function Person(name, age) {this.name = name;this.age = age;
}// 在原型上定義方法
Person.prototype.sayHello = function() {console.log(`你好,我是${this.name}!`);
};// 創建對象實例
const person1 = new Person("張三", 30);
const person2 = new Person("李四", 25);
2.6 ES6 類語法
ES6 引入了類(class)語法,提供了更接近傳統面向對象語言的語法糖,但底層仍然基于原型。
// 使用 class 定義類
class Person {constructor(name, age) {this.name = name;this.age = age;}sayHello() {console.log(`你好,我是${this.name}!`);}
}// 創建類的實例
const person = new Person("張三", 30);
3. 對象的屬性操作
3.1 訪問對象屬性
有兩種方式可以訪問對象的屬性:點表示法(.)和方括號表示法([])。
const person = {name: "張三",age: 30,"full-name": "張三先生"
};// 點表示法
console.log(person.name); // 輸出: 張三// 方括號表示法
console.log(person["age"]); // 輸出: 30
console.log(person["full-name"]); // 輸出: 張三先生 (適用于包含特殊字符的屬性名)// 使用變量作為屬性名
const prop = "name";
console.log(person[prop]); // 輸出: 張三
3.2 添加新屬性
可以隨時為對象添加新屬性。
const person = {name: "張三",age: 30
};// 添加新屬性
person.email = "zhangsan@example.com";
person["phone"] = "13800138000";console.log(person);
// 輸出: { name: '張三', age: 30, email: 'zhangsan@example.com', phone: '13800138000' }
3.3 修改屬性值
const person = {name: "張三",age: 30
};// 修改屬性值
person.age = 31;
person["name"] = "張三豐";console.log(person);
// 輸出: { name: '張三豐', age: 31 }
3.4 刪除屬性
使用 delete
操作符可以刪除對象的屬性。
const person = {name: "張三",age: 30,email: "zhangsan@example.com"
};// 刪除屬性
delete person.email;console.log(person);
// 輸出: { name: '張三', age: 30 }
console.log(person.email); // 輸出: undefined
3.5 檢查屬性是否存在
使用 in
操作符或 hasOwnProperty()
方法可以檢查對象是否包含特定屬性。
const person = {name: "張三",age: 30
};// 使用 in 操作符
console.log("name" in person); // 輸出: true
console.log("email" in person); // 輸出: false// 使用 hasOwnProperty() 方法
console.log(person.hasOwnProperty("name")); // 輸出: true
console.log(person.hasOwnProperty("toString")); // 輸出: false (toString 是原型鏈上的方法)
4. 對象的方法
4.1 定義方法
方法是存儲在對象屬性中的函數。
const calculator = {add: function(a, b) {return a + b;},subtract: function(a, b) {return a - b;},// ES6 簡寫語法multiply(a, b) {return a * b;},divide(a, b) {if (b === 0) {return "除數不能為零";}return a / b;}
};console.log(calculator.add(5, 3)); // 輸出: 8
console.log(calculator.multiply(5, 3)); // 輸出: 15
4.2 this 關鍵字
在對象方法中,this
指向調用該方法的對象。
const person = {name: "張三",age: 30,sayHello: function() {console.log(`你好,我是${this.name},今年${this.age}歲。`);},birthday: function() {this.age += 1;console.log(`${this.name}生日快樂!現在${this.age}歲了。`);}
};person.sayHello(); // 輸出: 你好,我是張三,今年30歲。
person.birthday(); // 輸出: 張三生日快樂!現在31歲了。
4.3 箭頭函數與 this
注意:在箭頭函數中,this
不綁定到調用該函數的對象,而是繼承自外層作用域。
const person = {name: "張三",age: 30,// 普通函數,this 指向 person 對象sayHello: function() {console.log(`你好,我是${this.name}。`);},// 箭頭函數,this 不指向 person 對象greet: () => {console.log(`你好,我是${this.name}。`); // 這里的 this 可能是全局對象或 undefined(嚴格模式下)}
};person.sayHello(); // 輸出: 你好,我是張三。
person.greet(); // 輸出: 你好,我是undefined。(瀏覽器環境中可能顯示為空)
5. 對象的遍歷
5.1 for…in 循環
for...in
循環可以遍歷對象的所有可枚舉屬性(包括繼承的屬性)。
const person = {name: "張三",age: 30,email: "zhangsan@example.com"
};// 遍歷對象的所有可枚舉屬性
for (let key in person) {// 通常使用 hasOwnProperty() 過濾掉繼承的屬性if (person.hasOwnProperty(key)) {console.log(`${key}: ${person[key]}`);}
}
// 輸出:
// name: 張三
// age: 30
// email: zhangsan@example.com
5.2 Object.keys()
Object.keys()
方法返回一個包含對象自身所有可枚舉屬性名稱的數組。
const person = {name: "張三",age: 30,email: "zhangsan@example.com"
};const keys = Object.keys(person);
console.log(keys); // 輸出: [ 'name', 'age', 'email' ]// 使用 forEach 遍歷
keys.forEach(key => {console.log(`${key}: ${person[key]}`);
});
5.3 Object.values()
Object.values()
方法返回一個包含對象自身所有可枚舉屬性值的數組。
const person = {name: "張三",age: 30,email: "zhangsan@example.com"
};const values = Object.values(person);
console.log(values); // 輸出: [ '張三', 30, 'zhangsan@example.com' ]
5.4 Object.entries()
Object.entries()
方法返回一個包含對象自身所有可枚舉屬性的鍵值對數組。
const person = {name: "張三",age: 30,email: "zhangsan@example.com"
};const entries = Object.entries(person);
console.log(entries);
// 輸出: [ [ 'name', '張三' ], [ 'age', 30 ], [ 'email', 'zhangsan@example.com' ] ]// 使用 for...of 遍歷
for (let [key, value] of entries) {console.log(`${key}: ${value}`);
}
6. 對象的高級特性
6.1 對象解構賦值
ES6 引入了對象解構賦值,可以從對象中提取屬性并賦值給變量。
const person = {name: "張三",age: 30,email: "zhangsan@example.com",address: {city: "北京",district: "朝陽區"}
};// 基本解構賦值
const { name, age } = person;
console.log(name); // 輸出: 張三
console.log(age); // 輸出: 30// 重命名變量
const { name: fullName, email: contactEmail } = person;
console.log(fullName); // 輸出: 張三
console.log(contactEmail); // 輸出: zhangsan@example.com// 默認值
const { phone = "未知" } = person;
console.log(phone); // 輸出: 未知// 嵌套對象解構
const { address: { city, district } } = person;
console.log(city); // 輸出: 北京
console.log(district); // 輸出: 朝陽區
6.2 對象展開運算符
ES6 引入了展開運算符(...
),可以用于復制對象屬性或合并對象。
const person1 = {name: "張三",age: 30
};// 復制對象
const person2 = { ...person1 };
console.log(person2); // 輸出: { name: '張三', age: 30 }// 合并對象
const contactInfo = {email: "zhangsan@example.com",phone: "13800138000"
};const completePerson = { ...person1, ...contactInfo };
console.log(completePerson);
// 輸出: { name: '張三', age: 30, email: 'zhangsan@example.com', phone: '13800138000' }// 覆蓋屬性
const updatedPerson = { ...person1, age: 31 };
console.log(updatedPerson); // 輸出: { name: '張三', age: 31 }
6.3 Object.assign() 方法
Object.assign()
方法用于將所有可枚舉屬性從一個或多個源對象復制到目標對象。
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3, a: 4 };const result = Object.assign(target, source1, source2);console.log(target); // 輸出: { a: 4, b: 2, c: 3 }
console.log(result); // 輸出: { a: 4, b: 2, c: 3 } (返回修改后的目標對象)
注意:Object.assign()
執行的是淺拷貝,對于嵌套對象,只會復制引用。
6.4 深度拷貝對象
對于包含嵌套對象的復雜對象,需要進行深度拷貝。
// 使用 JSON 序列化和反序列化(有局限性,不支持函數、Symbol、循環引用等)
const original = {name: "張三",address: {city: "北京"}
};const deepCopy = JSON.parse(JSON.stringify(original));// 修改拷貝后的對象不會影響原對象
deepCopy.address.city = "上海";
console.log(original.address.city); // 輸出: 北京
console.log(deepCopy.address.city); // 輸出: 上海// 自定義深度拷貝函數(處理更復雜的情況)
function deepClone(obj) {// 處理 null 或非對象類型if (obj === null || typeof obj !== 'object') {return obj;}// 處理日期對象if (obj instanceof Date) {return new Date(obj.getTime());}// 處理數組if (Array.isArray(obj)) {return obj.map(item => deepClone(item));}// 處理普通對象const clonedObj = {};for (let key in obj) {if (obj.hasOwnProperty(key)) {clonedObj[key] = deepClone(obj[key]);}}return clonedObj;
}
6.5 對象的屬性描述符
JavaScript 允許通過屬性描述符來精確控制對象屬性的行為。
const person = {};// 使用 Object.defineProperty() 定義屬性
Object.defineProperty(person, 'name', {value: '張三',writable: false, // 是否可寫enumerable: true, // 是否可枚舉configurable: false // 是否可配置(刪除或修改描述符)
});console.log(person.name); // 輸出: 張三
person.name = '李四'; // 在非嚴格模式下靜默失敗
console.log(person.name); // 輸出: 張三(值未改變)// 定義多個屬性
Object.defineProperties(person, {age: {value: 30,writable: true,enumerable: true},email: {value: 'zhangsan@example.com',enumerable: false}
});console.log(Object.keys(person)); // 輸出: [ 'name', 'age' ] (email 不可枚舉)// 獲取屬性描述符
const nameDescriptor = Object.getOwnPropertyDescriptor(person, 'name');
console.log(nameDescriptor);
// 輸出: { value: '張三', writable: false, enumerable: true, configurable: false }// 獲取所有屬性描述符
const allDescriptors = Object.getOwnPropertyDescriptors(person);
6.6 getter 和 setter
通過 getter 和 setter 可以定義對象的訪問器屬性,實現屬性的讀取和賦值控制。
const person = {firstName: "張",lastName: "三",// getter 方法get fullName() {return `${this.firstName}${this.lastName}`;},// setter 方法set fullName(name) {const parts = name.split(" ");this.firstName = parts[0];this.lastName = parts[1] || "";}
};console.log(person.fullName); // 輸出: 張三// 使用 setter 設置值
person.fullName = "李 四";
console.log(person.firstName); // 輸出: 李
console.log(person.lastName); // 輸出: 四
console.log(person.fullName); // 輸出: 李四
7. JavaScript 中的繼承
JavaScript 使用原型鏈實現繼承。每個對象都有一個原型對象,對象從原型繼承方法和屬性。
7.1 原型鏈繼承
// 父類構造函數
function Person(name) {this.name = name;
}// 在原型上定義方法
Person.prototype.sayHello = function() {console.log(`Hello, I'm ${this.name}`);
};// 子類構造函數
function Student(name, studentId) {// 調用父類構造函數Person.call(this, name);this.studentId = studentId;
}// 設置子類的原型為父類的實例
Student.prototype = Object.create(Person.prototype);// 修復 constructor 指向
Student.prototype.constructor = Student;// 在子類原型上添加方法
Student.prototype.study = function() {console.log(`${this.name} with ID ${this.studentId} is studying.`);
};// 創建實例
const student = new Student("張三", "1001");
student.sayHello(); // 輸出: Hello, I'm 張三 (繼承自父類)
student.study(); // 輸出: 張三 with ID 1001 is studying. (子類自己的方法)// 檢查原型鏈
console.log(student instanceof Student); // 輸出: true
console.log(student instanceof Person); // 輸出: true
console.log(student instanceof Object); // 輸出: true
7.2 ES6 類的繼承
ES6 引入的類語法使繼承更加直觀。
// 父類
class Person {constructor(name) {this.name = name;}sayHello() {console.log(`Hello, I'm ${this.name}`);}
}// 子類繼承父類
class Student extends Person {constructor(name, studentId) {// 調用父類構造函數super(name);this.studentId = studentId;}study() {console.log(`${this.name} with ID ${this.studentId} is studying.`);}
}// 創建實例
const student = new Student("張三", "1001");
student.sayHello(); // 輸出: Hello, I'm 張三
student.study(); // 輸出: 張三 with ID 1001 is studying.
8. 常用的內置對象
JavaScript 提供了許多內置對象,可以直接使用它們的屬性和方法。
8.1 Object 對象
Object
是 JavaScript 中所有對象的基類,提供了許多用于操作對象的靜態方法。
// 常用的 Object 方法
Object.create(proto[, propertiesObject]) // 創建新對象
Object.defineProperty(obj, prop, descriptor) // 定義對象的屬性
Object.defineProperties(obj, props) // 定義對象的多個屬性
Object.getOwnPropertyDescriptor(obj, prop) // 獲取屬性描述符
Object.getOwnPropertyNames(obj) // 獲取所有屬性名(包括不可枚舉的)
Object.keys(obj) // 獲取所有可枚舉屬性名
Object.values(obj) // 獲取所有可枚舉屬性值
Object.entries(obj) // 獲取所有可枚舉鍵值對
Object.assign(target, ...sources) // 合并對象
Object.freeze(obj) // 凍結對象,使其不可修改
Object.seal(obj) // 密封對象,不能添加或刪除屬性
Object.isFrozen(obj) // 檢查對象是否被凍結
Object.isSealed(obj) // 檢查對象是否被密封
Object.hasOwnProperty(prop) // 檢查對象是否有指定的自有屬性
8.2 Array 對象
Array
是用于處理數組的內置對象。
// 創建數組
const arr1 = new Array(1, 2, 3);
const arr2 = [1, 2, 3];// 數組的常用方法
arr.length // 獲取或設置數組長度
arr.push(item1, ..., itemN) // 向數組末尾添加元素
arr.pop() // 刪除并返回數組最后一個元素
arr.shift() // 刪除并返回數組第一個元素
arr.unshift(item1, ..., itemN) // 向數組開頭添加元素
arr.slice(start, end) // 返回數組的一部分
arr.splice(start, deleteCount, item1, ..., itemN) // 添加/刪除元素
arr.indexOf(searchElement, fromIndex) // 查找元素位置
arr.includes(searchElement, fromIndex) // 檢查數組是否包含元素
arr.forEach(callback, thisArg) // 對數組的每個元素執行函數
arr.map(callback, thisArg) // 創建一個新數組,包含對每個元素調用函數的結果
arr.filter(callback, thisArg) // 創建一個新數組,包含通過測試的元素
arr.reduce(callback, initialValue) // 對數組元素執行歸約操作
arr.sort(compareFunction) // 對數組元素進行排序
arr.reverse() // 反轉數組元素
8.3 String 對象
String
對象用于處理文本(字符串)。
// 創建字符串
const str1 = new String("Hello");
const str2 = "Hello";// 字符串的常用方法
str.length // 獲取字符串長度
str.charAt(index) // 返回指定索引位置的字符
str.charCodeAt(index) // 返回指定索引位置字符的 Unicode 值
str.concat(str1, str2, ...) // 連接字符串
str.includes(searchString, position) // 檢查字符串是否包含子字符串
str.indexOf(searchValue, fromIndex) // 查找子字符串首次出現的位置
str.lastIndexOf(searchValue, fromIndex) // 查找子字符串最后出現的位置
str.slice(beginIndex, endIndex) // 提取字符串的一部分
str.substring(indexStart, indexEnd) // 提取字符串的子串
str.substr(start, length) // 提取字符串的子串(不推薦使用)
str.split(separator, limit) // 將字符串分割為字符串數組
str.toLowerCase() // 將字符串轉換為小寫
str.toUpperCase() // 將字符串轉換為大寫
str.trim() // 去除字符串兩端的空白字符
str.replace(searchValue, replaceValue) // 替換字符串中的子串
str.match(regexp) // 查找匹配的字符串
8.4 Number 對象
Number
對象用于處理數值。
// 創建數字
const num1 = new Number(123);
const num2 = 123;// Number 的常用方法和屬性
Number.MAX_VALUE // 表示最大的正數
Number.MIN_VALUE // 表示最小的正數
Number.MAX_SAFE_INTEGER // 表示最大的安全整數
Number.MIN_SAFE_INTEGER // 表示最小的安全整數
Number.isNaN(value) // 檢查值是否為 NaN
Number.isFinite(value) // 檢查值是否為有限數
Number.isInteger(value) // 檢查值是否為整數
Number.parseInt(string, radix) // 將字符串轉換為整數
Number.parseFloat(string) // 將字符串轉換為浮點數
num.toFixed(digits) // 格式化為指定小數位數的字符串
num.toPrecision(precision) // 格式化為指定精度的字符串
num.toString(radix) // 將數字轉換為字符串
8.5 Date 對象
Date
對象用于處理日期和時間。
// 創建日期對象
const now = new Date();
const specificDate = new Date(2023, 0, 1); // 2023年1月1日(注意月份從0開始)
const dateString = new Date("2023-01-01");// Date 的常用方法
date.getFullYear() // 獲取年份
date.getMonth() // 獲取月份(0-11)
date.getDate() // 獲取日期(1-31)
date.getDay() // 獲取星期幾(0-6,0表示星期日)
date.getHours() // 獲取小時(0-23)
date.getMinutes() // 獲取分鐘(0-59)
date.getSeconds() // 獲取秒(0-59)
date.getMilliseconds() // 獲取毫秒(0-999)
date.getTime() // 獲取時間戳(從1970-01-01開始的毫秒數)// 設置日期和時間
date.setFullYear(year)
date.setMonth(month)
date.setDate(date)
date.setHours(hours)
date.setMinutes(minutes)
date.setSeconds(seconds)// 日期格式化
date.toDateString() // 返回日期部分的字符串
date.toTimeString() // 返回時間部分的字符串
date.toISOString() // 返回 ISO 格式的字符串
8.6 Math 對象
Math
對象提供了數學常量和函數。
// Math 的常用屬性和方法
Math.PI // 圓周率 π
Math.E // 自然對數的底 e
Math.abs(x) // 絕對值
Math.ceil(x) // 向上取整
Math.floor(x) // 向下取整
Math.round(x) // 四舍五入
Math.max(x1, x2, ...) // 返回最大值
Math.min(x1, x2, ...) // 返回最小值
Math.pow(x, y) // x 的 y 次方
Math.sqrt(x) // 平方根
Math.random() // 返回 0 到 1 之間的隨機數
Math.sin(x) // 正弦函數
Math.cos(x) // 余弦函數
Math.tan(x) // 正切函數
Math.log(x) // 自然對數
Math.exp(x) // e 的 x 次方
8.7 Map 和 Set
ES6 引入的 Map
和 Set
是用于存儲鍵值對和唯一值的集合。
// Map 對象
const map = new Map();// 添加元素
map.set("name", "張三");
map.set("age", 30);// 獲取元素
console.log(map.get("name")); // 輸出: 張三// 檢查元素是否存在
console.log(map.has("email")); // 輸出: false// 獲取 Map 的大小
console.log(map.size); // 輸出: 2// 刪除元素
map.delete("age");// 遍歷 Map
map.forEach((value, key) => {console.log(`${key}: ${value}`);
});for (let [key, value] of map) {console.log(`${key}: ${value}`);
}// Set 對象
const set = new Set([1, 2, 3, 3, 4]);// Set 自動去重
console.log(set.size); // 輸出: 4 (重復的 3 只保留一個)// 添加元素
set.add(5);// 檢查元素是否存在
console.log(set.has(3)); // 輸出: true// 刪除元素
set.delete(2);// 遍歷 Set
set.forEach(value => {console.log(value);
});for (let value of set) {console.log(value);
}
8.8 JSON 對象
JSON
對象提供了用于解析和生成 JSON 數據的方法。
// JSON 字符串
const jsonString = '{"name":"張三","age":30,"hobbies":["閱讀","編程"]}';// 解析 JSON 字符串
const obj = JSON.parse(jsonString);
console.log(obj.name); // 輸出: 張三// 將對象轉換為 JSON 字符串
const person = {name: "張三",age: 30,hobbies: ["閱讀", "編程"]
};const json = JSON.stringify(person);
console.log(json);
// 輸出: {"name":"張三","age":30,"hobbies":["閱讀","編程"]}// 帶縮進的 JSON 字符串
const prettyJson = JSON.stringify(person, null, 2);
console.log(prettyJson);
// 輸出格式化的 JSON:
// {
// "name": "張三",
// "age": 30,
// "hobbies": [
// "閱讀",
// "編程"
// ]
// }
9. 對象操作的最佳實踐
9.1 使用對象字面量創建對象
對象字面量是創建對象最簡潔、最易讀的方式。
// 推薦
const person = {name: "張三",age: 30
};// 不推薦(除非有特殊原因)
const person = new Object();
person.name = "張三";
person.age = 30;
9.2 使用 ES6 的類語法
對于需要創建多個相似對象的情況,使用 ES6 的類語法比傳統的構造函數模式更清晰。
// 推薦
class Person {constructor(name, age) {this.name = name;this.age = age;}sayHello() {console.log(`Hello, I'm ${this.name}`);}
}// 不推薦(除非需要兼容舊瀏覽器)
function Person(name, age) {this.name = name;this.age = age;
}Person.prototype.sayHello = function() {console.log(`Hello, I'm ${this.name}`);
};
9.3 避免修改內置對象的原型
修改內置對象(如 Object
、Array
等)的原型可能會導致不可預期的問題,應盡量避免。
// 不推薦
Array.prototype.sum = function() {return this.reduce((acc, curr) => acc + curr, 0);
};
9.4 使用對象展開運算符或 Object.assign() 合并對象
const defaults = {timeout: 3000,retries: 3
};const options = {timeout: 5000,url: "https://api.example.com"
};// 推薦
const config = { ...defaults, ...options };// 或者
const config = Object.assign({}, defaults, options);
9.5 優先使用 const 聲明對象
除非需要重新賦值整個對象,否則應使用 const
聲明對象,這有助于防止意外的對象替換。
// 推薦
const person = {name: "張三",age: 30
};// 仍然可以修改對象的屬性
person.age = 31;// 不推薦(除非需要重新賦值整個對象)
let person = {name: "張三",age: 30
};
9.6 使用解構賦值訪問對象屬性
解構賦值可以使代碼更簡潔、更易讀。
const user = {name: "張三",email: "zhangsan@example.com",role: "admin"
};// 推薦
const { name, email, role } = user;
console.log(name, email, role);// 不推薦
const name = user.name;
const email = user.email;
const role = user.role;
console.log(name, email, role);
9.7 注意 this 的綁定問題
在 JavaScript 中,this
的值取決于函數的調用方式,而不是定義方式。在處理事件處理程序、回調函數等情況時,需要特別注意 this
的綁定。
const person = {name: "張三",greet: function() {console.log(`Hello, I'm ${this.name}`);},delayedGreet: function() {// 在 setTimeout 中,this 不會指向 person 對象setTimeout(function() {console.log(`Hello, I'm ${this.name}`); // this 可能是全局對象或 undefined}, 1000);},delayedGreetFixed: function() {// 方法1: 使用 bindsetTimeout(function() {console.log(`Hello, I'm ${this.name}`);}.bind(this), 1000);// 方法2: 使用箭頭函數(繼承外層作用域的 this)setTimeout(() => {console.log(`Hello, I'm ${this.name}`);}, 2000);}
};
9.8 安全地訪問嵌套對象屬性
當訪問嵌套對象的屬性時,應防止因中間屬性不存在而導致的錯誤。
const user = {profile: {name: "張三",address: {city: "北京"}}
};// 不安全(如果 user.profile 或 user.profile.address 不存在,會拋出錯誤)
console.log(user.profile.address.city);// 安全的方式1: 逐步檢查
let city = "未知";
if (user && user.profile && user.profile.address) {city = user.profile.address.city;
}
console.log(city);// 安全的方式2: 使用可選鏈操作符(ES11 特性)
console.log(user?.profile?.address?.city || "未知");// 安全的方式3: 使用 try-catch
try {console.log(user.profile.address.city);
} catch (error) {console.log("未知");
}
10. 總結
JavaScript 對象是該語言的核心概念之一,理解和掌握對象的操作對于編寫高效、可維護的 JavaScript 代碼至關重要。本指南涵蓋了 JavaScript 對象的基本概念、創建方法、屬性和方法操作、遍歷方式、高級特性、繼承機制以及常見的內置對象等內容。
通過靈活運用這些知識,您可以更好地組織和管理數據,實現復雜的功能,并編寫更加優雅和高效的 JavaScript 代碼。隨著 JavaScript 語言的不斷發展,對象相關的特性也在持續改進,建議保持學習最新的語言特性和最佳實踐。