当前位置: 首页 > article >正文

[JavaScript] 面向对象编程

JavaScript 是一种多范式语言,既支持函数式编程,也支持面向对象编程。在 ES6 引入 class 语法后,面向对象编程在 JavaScript 中变得更加易于理解和使用。以下将详细讲解 JavaScript 中的类(class)、构造函数(constructor)、继承、封装、多态,以及 this 的相关问题。


1. 为什么需要类与面向对象编程?

面向对象编程(Object-Oriented Programming,OOP)是一种以“对象”为核心的编程思想。通过类与对象的概念,可以更好地模拟现实世界的实体,提升代码的可重用性、可维护性和扩展性。

在 JavaScript 早期,使用函数和原型链实现面向对象的思想,语法复杂且容易出错。引入 class 后,语法更加直观。


2. 类(class)与构造函数(constructor)

2.1 类的基本语法

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.

2.2 为什么需要构造函数?

constructor 是类的特殊方法,用于在创建对象时初始化属性。它的主要作用是:

  1. 设置对象的初始状态。
  2. 为每个实例创建唯一的属性。

2.3 静态方法(static methods)

静态方法是直接定义在类上的方法,而不是在实例上的方法。静态方法通常用于创建工具类或与实例无关的逻辑。

class MathUtils {
    static add(a, b) {
        return a + b;
    }
}

console.log(MathUtils.add(2, 3)); // 输出:5

3. 继承

继承允许我们定义一个类,继承另一个类的属性和方法,从而实现代码复用。

3.1 基本语法

使用 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.

3.2 为什么需要继承?

  1. 代码复用:子类可以直接使用父类的属性和方法,避免重复代码。
  2. 逻辑扩展:子类可以添加自己的方法或重写父类的方法,实现特定功能。

4. 封装

封装是指将对象的内部状态隐藏起来,通过方法暴露必要的操作。这样可以保护数据的安全性,避免外部直接修改。

4.1 在 JavaScript 中实现封装

  1. 私有属性(ES6 之前的实现):
    通过闭包模拟私有属性。
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
  1. 私有属性(ES6 新特性):
    使用 # 定义真正的私有属性。
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

5. 多态

多态是指不同的类在调用相同方法时,可以表现出不同的行为。这通常通过**方法重写(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.

6. this 指向问题

6.1 为什么会有 this?

this 是 JavaScript 中一个动态绑定的关键字,其指向取决于函数的调用方式。


6.2 this 的常见指向规则

  1. 默认指向(全局对象):
    在非严格模式下,普通函数调用中的 this 指向全局对象 window
function showThis() {
    console.log(this);
}
showThis(); // 输出:window(浏览器环境下)
  1. 方法调用
    在对象的方法中,this 指向调用方法的对象。
const obj = {
    name: "Kevin",
    showThis() {
        console.log(this);
    },
};
obj.showThis(); // 输出:obj 对象本身
  1. 构造函数中的 this
    在构造函数中,this 指向新创建的对象。
function Person(name) {
    this.name = name;
}
const person = new Person("Kevin");
console.log(person.name); // 输出:Kevin
  1. 箭头函数中的 this
    箭头函数不会创建自己的 this,而是从外部作用域继承 this
const obj = {
    name: "Kevin",
    showThis: () => {
        console.log(this);
    },
};
obj.showThis(); // 输出:window 或 undefined(严格模式下)

6.3 解决 this 指向问题

  1. **使用 **bind
const obj = { name: "Kevin" };
function showName() {
    console.log(this.name);
}
const boundShowName = showName.bind(obj);
boundShowName(); // 输出:Kevin
  1. 使用箭头函数
const obj = {
    name: "Kevin",
    showThis() {
        const arrow = () => console.log(this.name);
        arrow();
    },
};
obj.showThis(); // 输出:Kevin

总结

JavaScript 的面向对象编程非常灵活,类的引入让代码更加清晰和直观。在实际开发中,熟练掌握类与对象、继承、封装、多态,以及 this 的指向规则,可以让你写出更加高效和可维护的代码。如果有任何疑问或需要补充代码示例,欢迎随时交流!


http://www.kler.cn/a/518944.html

相关文章:

  • 【数据结构】深入解析:构建父子节点树形数据结构并返回前端
  • 深度学习项目--基于LSTM的糖尿病预测探究(pytorch实现)
  • gradle创建springboot单项目和多模块项目
  • 延迟之争:LLM服务的制胜关键
  • 高速光模块中的并行光学和WDM波分光学技术
  • 【MySQL — 数据库增删改查操作】深入解析MySQL的create insert 操作
  • mysql之group by语句
  • [RoarCTF 2019]Easy Calc1
  • 【例51.3】 平移数据
  • 头歌实训作业 算法设计与分析-动态规划(第1关:0/1背包问题)
  • 【Python】第四弹---深入理解Python控制流:从顺序到循环的全面解析
  • 论文速读|Beit: Bert pre training of image transformers.ICLR22
  • BGP分解实验·12——配置路由反射器
  • ML基础2-python中的可视化1:matplotlib
  • 汽车定速巡航
  • 2025数学建模美赛|E题成品论文
  • Mono里运行C#脚本35—加载C#语言基类的过程
  • 高阶C语言|数组名的深度解析(数组名结合sizeof与strlen的详解)
  • impact 影响分析学习笔记(一)
  • 【后端面试总结】mysql的join,left join,right join,full join分别是什么意思
  • maven 全局配置
  • 【Python使用】嘿马python高级进阶全体系教程第11篇:静态Web服务器-面向对象开发,1. 以面向对象的方式开发静态W
  • 79,【3】BUUCTF WEB [GXYCTF2019]BabysqliV3.0
  • mongoDB常见指令
  • Go中new和make的区别对比
  • 机器学习的通俗解释