原型链和继承
在 JavaScript 中,每个对象都有一个原型(prototype),这个原型指向另一个对象。这个链式的原型关系被称为原型链。当访问一个对象的属性时,如果该对象没有该属性,它会沿着原型链向上查找,直到找到该属性或到达原型链的末端。
// 创建一个构造函数 Person
function Person(name, age) {
this.name = name;
this.age = age;
}
// 添加一个方法到 Person.prototype
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name} and I am${this.age} years old.`);
};
// 创建一个 Person 实例
const person1 = new Person("Alice", 30);
// 调用 greet 方法
person1.greet(); // Hello, my name is Alice and I am 30 years old.
继承可以通过原型链实现,也可以通过原型式继承(如 Object.create())、组合继承(使用原型链和构造函数)等方式实现。
作用域链和闭包
作用域链是 JavaScript 引擎在执行代码时创建的一个链式结构,用于在函数内部访问变量。这个链从当前函数的作用域开始,然后是外部函数的作用域,最后是全局作用域。
闭包是一个函数及其作用域内的变量组成的组合,即使外部函数执行完毕,闭包中的变量也不会被销毁。
function outerFunction() {
var outerVariable = "I am outer";
function innerFunction() {
console.log(outerVariable); // 访问外部函数的变量
}
return innerFunction;
}
const inner = outerFunction();
inner(); // I am outer
异步编程
回调函数是一种在异步操作完成后执行的函数。
function fetchData(callback) {
setTimeout(() => {
callback("Data fetched successfully!");
}, 2000);
}
fetchData((data) => {
console.log(data);
});
Promise 是一种对象,用于异步操作的结果。
const fetchData = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data fetched successfully!");
}, 2000);
});
fetchData()
.then((data) => {
console.log(data);
})
.catch((error) => {
console.error(error);
});
async/await 是 ES2017 引入的语法糖,用于处理 Promise。
async function fetchData() {
try {
const data = await new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data fetched successfully!");
}, 2000);
});
console.log(data);
} catch (error) {
console.error(error);
}
}
fetchData();
ES6+ 新特性
- let 和 const:
let
声明的变量具有块级作用域,const
声明的变量是常量,一旦声明不能更改。
if (true) {
let message = "Hello";
console.log(message); // Hello
}
const pi = 3.14159;
pi = 3; // 错误,不能更改 pi 的值
- 模板字符串:使用反引号````表示,可以在字符串中嵌入变量。
const name = "Alice";
const age = 30;
const greeting = `Hello, my name is ${name} and I am${age} years old.`;
console.log(greeting); // Hello, my name is Alice and I am 30 years old.
- 箭头函数:
()=>{}
,用于简化函数声明。
const greet = (name) => `Hello, ${name}!`;
console.log(greet("John")); // Hello, John!
- 解构赋值:允许从数组或对象中提取值并赋给变量。
const person = { name: "Alice", age: 30 }; const { name, age } = person; console.log(name); // Alice console.log(age); // 30
- 模块化:通过
import
和export
语句来导入和导出模块。 -
// module1.js export const add = (a, b) => a + b; // module2.js import { add } from './module1'; const result = add(5, 3); console.log(result); // 8
- 其他新特性:如
Promise
、Set
、Map
、Proxy
、Reflect
、Symbol
等。 -
Promise
Promise 是一个对象,用于异步操作的结果。它有三种状态:
pending
(进行中)、fulfilled
(已完成)和rejected
(已失败)。const fetchData = () => new Promise((resolve, reject) => { setTimeout(() => { resolve("Data fetched successfully!"); }, 2000); }); fetchData() .then((data) => { console.log(data); }) .catch((error) => { console.error(error); });
Set 和 Map
- Set:类似于数组,但成员的值都是唯一的,没有重复的值。
-
const numbers = new Set([1, 2, 3, 4, 5]); console.log(numbers); // Set(5) {1, 2, 3, 4, 5}
- Map:类似于对象,但它的键可以是任何值,且键是唯一的。
-
const map = new Map([ ["name", "Alice"], ["age", 30], ]); console.log(map); // Map(2) {name: "Alice", age: 30}
Proxy
Proxy 是一种对象,它可以拦截对象上的操作,如属性访问、属性设置、函数调用等。
const person = { name: "Alice", age: 30 }; const proxy = new Proxy(person, { get: (target, key) => { if (key === "age") { return target[key] * 2; // 返回年龄的两倍 } return target[key]; }, }); console.log(proxy.name); // Alice console.log(proxy.age); // 60
Reflect
Reflect 是 JavaScript 语言的一个内置对象,它提供了一些与 JavaScript 对象操作相关的方法。
const person = { name: "Alice", age: 30 }; const keys = Reflect.ownKeys(person); console.log(keys); // ["name", "age"]
Symbol
Symbol 是 ES6 引入的一种新的原始数据类型,表示独一无二的值。
const symbol = Symbol("unique"); console.log(typeof symbol); // "symbol" console.log(symbol === symbol); // false
这些新特性使得 JavaScript 更加强大和灵活,有助于编写更简洁、更易于维护的代码。随着 JavaScript 语言的不断进化,开发者需要不断学习和适应新的特性和变化。