JavaScript 是一种多范式语言,既支持函数式编程,也支持面向对象编程。在 ES6 引入 class
语法后,面向对象编程在 JavaScript 中变得更加易于理解和使用。以下将详细讲解 JavaScript 中的类(class
)、构造函数(constructor
)、继承、封装、多态,以及 this
的相关问题。
面向对象编程(Object-Oriented Programming,OOP)是一种以“对象”为核心的编程思想。通过类与对象的概念,可以更好地模拟现实世界的实体,提升代码的可重用性、可维护性和扩展性。
在 JavaScript 早期,使用函数和原型链实现面向对象的思想,语法复杂且容易出错。引入 class
后,语法更加直观。
class
是用来定义对象蓝图的关键字,其中包含对象的属性和方法。
class Person {
// 构造函数:定义对象的初始化逻辑
constructor(name, age) {
this.name = name; // this 代表当前实例
this.age = age;
}
// 定义实例方法
sayHello() {
console.log(`Hello, my name is ${this.name}.`);
}
}
// 创建类的实例
const person1 = new Person("Kevin", 25);
console.log(person1.name); // 输出:Kevin
person1.sayHello(); // 输出:Hello, my name is Kevin.
constructor
是类的特殊方法,用于在创建对象时初始化属性。它的主要作用是:
静态方法是直接定义在类上的方法,而不是在实例上的方法。静态方法通常用于创建工具类或与实例无关的逻辑。
class MathUtils {
static add(a, b) {
return a + b;
}
}
console.log(MathUtils.add(2, 3)); // 输出:5
继承允许我们定义一个类,继承另一个类的属性和方法,从而实现代码复用。
使用 extends
实现继承,并通过 super()
调用父类的构造函数。
class Animal {
constructor(name) {
this.name = name;
}
makeSound() {
console.log(`${this.name} is making a sound.`);
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // 调用父类的构造函数
this.breed = breed;
}
makeSound() {
console.log(`${this.name}, a ${this.breed}, barks.`);
}
}
const dog = new Dog("Buddy", "Golden Retriever");
dog.makeSound();
// 输出:Buddy, a Golden Retriever, barks.
封装是指将对象的内部状态隐藏起来,通过方法暴露必要的操作。这样可以保护数据的安全性,避免外部直接修改。
function Person(name) {
let _name = name; // 私有变量
this.getName = function () {
return _name;
};
this.setName = function (newName) {
_name = newName;
};
}
const person = new Person("Kevin");
console.log(person.getName()); // 输出:Kevin
person.setName("Feng");
console.log(person.getName()); // 输出:Feng
#
定义真正的私有属性。class Person {
#name;
constructor(name) {
this.#name = name;
}
getName() {
return this.#name;
}
setName(newName) {
this.#name = newName;
}
}
const person = new Person("Kevin");
console.log(person.getName()); // 输出:Kevin
person.setName("Feng");
console.log(person.getName()); // 输出:Feng
多态是指不同的类在调用相同方法时,可以表现出不同的行为。这通常通过**方法重写(Method Overriding)**实现。
class Animal {
makeSound() {
console.log("Animal is making a sound.");
}
}
class Dog extends Animal {
makeSound() {
console.log("Dog is barking.");
}
}
class Cat extends Animal {
makeSound() {
console.log("Cat is meowing.");
}
}
const animals = [new Dog(), new Cat()];
animals.forEach(animal => animal.makeSound());
// 输出:
// Dog is barking.
// Cat is meowing.
this
是 JavaScript 中一个动态绑定的关键字,其指向取决于函数的调用方式。
this
指向全局对象 window
。function showThis() {
console.log(this);
}
showThis(); // 输出:window(浏览器环境下)
this
指向调用方法的对象。const obj = {
name: "Kevin",
showThis() {
console.log(this);
},
};
obj.showThis(); // 输出:obj 对象本身
this
指向新创建的对象。function Person(name) {
this.name = name;
}
const person = new Person("Kevin");
console.log(person.name); // 输出:Kevin
this
,而是从外部作用域继承 this
。const obj = {
name: "Kevin",
showThis: () => {
console.log(this);
},
};
obj.showThis(); // 输出:window 或 undefined(严格模式下)
bind
:const obj = { name: "Kevin" };
function showName() {
console.log(this.name);
}
const boundShowName = showName.bind(obj);
boundShowName(); // 输出:Kevin
const obj = {
name: "Kevin",
showThis() {
const arrow = () => console.log(this.name);
arrow();
},
};
obj.showThis(); // 输出:Kevin
JavaScript 的面向对象编程非常灵活,类的引入让代码更加清晰和直观。在实际开发中,熟练掌握类与对象、继承、封装、多态,以及 this
的指向规则,可以让你写出更加高效和可维护的代码。如果有任何疑问或需要补充代码示例,欢迎随时交流!