JS 中的 OOPS - 终极版

2025-06-04

JS 中的 OOPS - 终极版

🔥连接:https://www.subham.online

🔥仓库:https://github.com/Subham-Maity/OOPS-in-JS-Ultimate

🔥GitHub:https://github.com/Subham-Maity

🔥推特:https://twitter.com/TheSubhamMaity

🔥领英:https://www.linkedin.com/in/subham-xam

🔥Insta:https://www.instagram.com/subham_xam


✅ 正在寻找 JAVA 中 OOP 概念的最佳笔记?这里有一个:

> “JAVA 中的 OOPS - Ultimate” - 请查看此

▶️ 简介

⭐什么是 OOP?

面向对象编程是一种通过创建对象来解决问题的方法。

⭐ OOP 的 4 个支柱

OOP中的术语

  1. 抽象——隐藏内部细节(仅显示必要信息!)
  2. 封装——将各种组件放在一起(在胶囊中)的行为
  3. 继承——从现有事物中衍生出新事物的行为
  4. 多态性——一个实体,多种形式

js

▶️ 原型和原型

JavaScript的对象有一个特殊的属性prototype称为null

当我们尝试从对象中读取属性时,如果缺少该属性,JavaScript 会自动从原型中获取它。这称为原型继承

⭐ 设置原型

我们可以通过设置 来设置原型__proto__。如果我们从对象中读取一个属性,而该属性不在对象中,但在原型中,JavaScript 将从原型中获取该属性。如果对象中有一个方法,则会从对象中调用该方法。如果对象中没有该方法,但原型中有,则会从原型中调用该方法。

⭐示例:

//It will work properly
let p = {
    run : () => {
        console.log("run")
    }
}

p.run()//Output: - run

//Let's define another property
let a = {
    name : " subham"
}

a.run() //TypeError: a.run is not a function

//Now with proto
let b = {
    name : " subham"
}
b.__proto__ = p
b.run() //Output: - run
Enter fullscreen mode Exit fullscreen mode

简单来说,你可以继承某个对象的原型,让另一个对象继承它。这叫做原型继承。

//It will work properly
let p = {
    run : () => {
        console.log("p run")
    }
}

p.run()//Output: - p run

//Now with proto
let b = {
    run : () => {
        console.log("b run")
    }
}
b.__proto__ = p
b.run() //Output: - b run

Enter fullscreen mode Exit fullscreen mode

如果某个属性或方法已存在于对象中,JavaScript 将使用该属性或方法。如果该属性或方法不存在于对象中,但存在于原型中,JavaScript 将从原型中获取它。在本例中,由于该run方法已存在于b对象中,因此它将打印“b run”。

▶️ 类和对象

  • 在面向对象编程中,类是特定类型对象中的方法和变量的模板定义
  • 在面向对象编程中,对象是已在内存中分配的类(或结构)的特定实例。

⭐示例:

//class
class GoogleForm {
    submit() {
       console.log(this.name + " " + this.roll + " Your form submitted")
    }
    cancel() {
        console.log(this.name + " " + this.roll +" Your form cancelled")
    }
    fill(given_name , roll) {
        this.name = given_name
        this.roll = roll
    }
}


//object
const student1Form = new GoogleForm()

student1Form.fill("Rahul" , 24)

const student2Form = new GoogleForm()

student2Form.fill("Raj" , 25)

student2Form.cancel()


student1Form.submit()

student2Form.submit()
Enter fullscreen mode Exit fullscreen mode

▶️ 构造函数

在 JavaScript 中,构造函数是一个特殊的函数,它创建和初始化对象,设置它们的初始状态和属性。

假设他们忘记填写表格并单击提交按钮,它将抛出未定义!

class Form {

    submit() {
        console.log(this.name + ": Your form is submitted for train number: " + this.trainno)
    }

    cancel() {
        console.log(this.name + ": This form is cancelled for train number: " + this.trainno)
        this.trainno = 0
    }
    fill(givenname, trainno) {
        this.name = givenname
        this.trainno = trainno
    }

}

let myForm1 = new Form()

let myForm2 = new Form()
//
// myForm1.fill("Gaurav", 1234)
//
// myForm2.fill("Rahul", 5678)

myForm1.submit()

myForm2.submit()

myForm2.cancel()

// Output: undefined: Your form is submitted for train number: undefined
// Output: undefined: Your form is submitted for train number: undefined
// Output: undefined: This form is cancelled for train number: undefined

Enter fullscreen mode Exit fullscreen mode

现在创建构造函数,

class Form {

    constructor() {
        this.name = "Gaurav"
        this.trainno = 0
    }

    submit() {
        console.log(this.name + ": Your form is submitted for train number: " + this.trainno)
    }

    cancel() {
        console.log(this.name + ": This form is cancelled for train number: " + this.trainno)
        this.trainno = 0
    }
    fill(givenname, trainno) {
        this.name = givenname
        this.trainno = trainno
    }

}

let myForm1 = new Form()

let myForm2 = new Form()

// myForm1.fill("Gaurav", 1234)
//
// myForm2.fill("Rahul", 5678)

myForm1.submit()

myForm2.submit()

myForm2.cancel()

// Output: Gaurav: Your form is submitted for train number: 0
// Output: Gaurav: Your form is submitted for train number: 0
// Output: Gaurav: This form is cancelled for train number: 0
Enter fullscreen mode Exit fullscreen mode

⭐ 构造函数的类型

  1. 非参数化构造函数:没有参数的构造函数。
    class Example {
        constructor() {
            this.property = "default value";
        }
    }
Enter fullscreen mode Exit fullscreen mode
  1. 参数化构造函数:带有参数的构造函数。
    class Example {
        constructor(value) {
            this.property = value;
        }
    }
Enter fullscreen mode Exit fullscreen mode
  1. 复制构造函数:JavaScript 没有像 C++ 或 Java 那样内置的复制构造函数。但是,你可以创建一个方法来复制对象。
    class Example {
        constructor(value) {
            this.property = value;
        }

        copy() {
            return new Example(this.property);
        }
    }

    const original = new Example("original value");
    const copy = original.copy();
Enter fullscreen mode Exit fullscreen mode

与 C++ 等语言不同,JavaScript 没有析构函数。相反,JavaScript 依赖于高效的垃圾收集器来自动释放内存。

▶️ 继承

一个类从另一个类派生属性和特征的能力称为继承。

⭐为什么?

如果你不知道什么是继承

class Animal {
    constructor(name, color , age) {
        this.name = name
        this.color = color
        this.age = age
    }
    run() {
        console.log(this.name + ' is running')
    }

    shout() {

        console.log(this.name + ' is shouting')
    }

    sleep() {
        console.log(this.name + ' is sleeping')
    }
}

//If you are nub developer you will do
class Monkey {
    constructor(name, color) {
        this.name = name
        this.color = color
    }
    run() {
        console.log(this.name + ' is running')
    }

    shout() {

        console.log(this.name + ' is shouting')
    }

    sleep() {
        console.log(this.name + ' is sleeping')
    }

    eatBanana() {
        console.log(this.name + ' is eating banana')
    }
}

const animal_1 = new Monkey('Simba monkey', 'Brown', 2)

const animal_2 = new Animal('Donkey', 'White', 3)

animal_1.eatBanana()

animal_2.shout()
Enter fullscreen mode Exit fullscreen mode

如果你知道

//Parent Class - Base Class
class Animal {
    constructor(name, color , age) {
        this.name = name
        this.color = color
        this.age = age
    }
    run() {
        console.log(this.name + ' is running')
    }

    shout() {

        console.log(this.name + ' is shouting')
    }

    sleep() {
        console.log(this.name + ' is sleeping')
    }
}

//Child Class - Derived Class
class Monkey extends Animal{
    eatBanana() {
        console.log(this.name + ' is eating banana')
    }
    //you can also add new methods
    hide() {
        console.log(this.name + ' is hiding')
    }
}

const animal_1 = new Monkey('Simba monkey', 'Brown', 2)

const animal_2 = new Animal('Donkey', 'White', 3)

animal_1.eatBanana()
animal_1.run()
animal_1.hide()

animal_2.shout()
Enter fullscreen mode Exit fullscreen mode

⭐ 继承类型

  1. 单继承当一个类继承另一个类时,这称为单级继承。
class Shape {
  area() {
    console.log("Displays Area of Shape");
  }
}

class Triangle extends Shape {
  area(h, b) {
    console.log((1/2) * b * h);
  }
}

const triangle = new Triangle();
triangle.area(10, 5); // Output: 25
Enter fullscreen mode Exit fullscreen mode
  1. 分层继承被定义为从基类派生多个类的过程。
class Shape {
  area() {
    console.log("Displays Area of Shape");
  }
}

class Triangle extends Shape {
  area(h, b) {
    console.log((1/2) * b * h);
  }
}

class Circle extends Shape {
  area(r) {
    console.log(3.14 * r * r);
  }
}

const triangle = new Triangle();
triangle.area(10, 5); // Output: 25

const circle = new Circle();
circle.area(7); // Output: 153.86
Enter fullscreen mode Exit fullscreen mode
  1. 多级继承是从另一个派生类派生一个类的过程。
class Shape {
  area() {
    console.log("Displays Area of Shape");
  }
}

class Triangle extends Shape {
  area(h, b) {
    console.log((1/2) * b * h);
  }
}

class EquilateralTriangle extends Triangle {
  constructor(side) {
    super();
    this.side = side;
  }

  area() {
    console.log((Math.sqrt(3) / 4) * this.side * this.side);
  }
}

const equilateralTriangle = new EquilateralTriangle(5);
equilateralTriangle.area(); // Output: 10.825317547305486
Enter fullscreen mode Exit fullscreen mode
  1. 混合继承是简单继承、多重继承和层次继承的组合。JavaScript 并不直接支持多重继承,但我们可以使用 mixin 实现类似的行为。
class Shape {
  area() {
    console.log("Displays Area of Shape");
  }
}

class Triangle extends Shape {
  area(h, b) {
    console.log((1/2) * b * h);
  }
}

class Circle extends Shape {
  area(r) {
    console.log(3.14 * r * r);
  }
}

const mixin = (Base) => class extends Base {
  perimeter() {
    console.log("Calculates Perimeter");
  }
};

class EquilateralTriangle extends mixin(Triangle) {
  constructor(side) {
    super();
    this.side = side;
  }

  area() {
    console.log((Math.sqrt(3) / 4) * this.side * this.side);
  }
}

const equilateralTriangle = new EquilateralTriangle(5);
equilateralTriangle.area(); // Output: 10.825317547305486
equilateralTriangle.perimeter(); // Output: Calculates Perimeter
Enter fullscreen mode Exit fullscreen mode

▶️ 方法覆盖

如果超类和子类中定义了相同的方法,那么子类的方法将覆盖超类的方法

  • 一般的
class human {
    constructor(name , age , body_type) {
        this.name = name
        this.age = age
        this.body_type = body_type
    }

    getName() {
        console.log("The name of the human is : ", this.name)
    }

    getAge() {

        console.log("The age of the human is :", this.age)
    }

    getBodyType() {
        console.log("The body type of the human is :", this.body_type)
    }
}

class student extends human {}

const student_1 = new student("Subham" , 24 , "Thin")

student_1.getAge() //The age of the human is : 24
Enter fullscreen mode Exit fullscreen mode

⭐ 超级关键字 - 类型

super 关键字用于调用父类的构造函数来访问其属性和方法。

重写构造函数

class Human {
    constructor(name, age, bodyType) {
        this.name = name;
        this.age = age;
        this.bodyType = bodyType;
    }

    getName() {
        console.log("The name of the human is:", this.name);
    }

    getAge() {
        console.log("The age of the human is:", this.age);
    }

    getBodyType() {
        console.log("The body type of the human is:", this.bodyType);
    }
}

class Student extends Human {
    constructor() {
        super("Rahul", 80, "Fat");
    }
}

const student1 = new Student();

student1.getName(); // The name of the human is: Rahul
Enter fullscreen mode Exit fullscreen mode

重写方法

class Human {
    constructor(name, age, bodyType) {
        this.name = name;
        this.age = age;
        this.bodyType = bodyType;
    }

    getName() {
        console.log("The name of the human is:", this.name);
    }

    getAge() {
        console.log("The age of the human is:", this.age);
    }

    getBodyType() {
        console.log("The body type of the human is:", this.bodyType);
    }
}

class Student extends Human {
    constructor() {
        super("Rahul", 80, "Fat");
    }

    // Overriding using super keyword in child class
    getAge() {
        super.getAge();
        console.log("The age of the student is:", 20);
    }
}

const student1 = new Student();

student1.getAge(); // The age of the human is: 80
                   // The age of the student is: 20

Enter fullscreen mode Exit fullscreen mode

⭐ 方法覆盖的要点

  1. 相同的方法名称:子类中的方法必须与父类中的方法具有相同的名称。

  2. 相同参数:子类中的方法必须具有与父类方法相同的参数列表。

  3. IS-A 关系:方法覆盖仅发生在具有 IS-A 关系(继承)的两个类中。

  4. 访问修饰符:覆盖方法可以具有限制较少的访问修饰符,但不能具有限制较多的访问修饰符。

  5. Super 关键字:您可以使用该super关键字从父类调用重写的方法。

⭐ 附加说明

注1

class human {
    constructor() {
        console.log("Human class constructor")
    }
    eat() {
        console.log("Human can eat")
    }
}
class student extends human {
}
const student_1 = new student()
student_1.eat()

//Human class constructor
// Human can eat
Enter fullscreen mode Exit fullscreen mode

如果你没有在子类中明确定义构造函数,JavaScript 将自动为你创建一个,并使用 super() 调用父类的构造函数。
像这样

class human {
    constructor() {
        console.log("Human class constructor")
    }
    eat() {
        console.log("Human can eat")
    }
}
class student extends human {
    constructor(...arg) {
        super(...arg);
    }
}
const student_1 = new student()
student_1.eat()
Enter fullscreen mode Exit fullscreen mode

注 2

class human {
    constructor() {
        console.log("Human class constructor")
    }
    eat() {
        console.log("Human can eat")
    }
}
class student extends human {
    constructor() {
        console.log("This is student class constructor")
    }
}
const student_1 = new student()
student_1.eat()

// console.log("This is student class constructor")
//ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor

Enter fullscreen mode Exit fullscreen mode

您必须像这样使用 super 关键字

class human {
    constructor() {
        console.log("Human class constructor")
    }
    eat() {
        console.log("Human can eat")
    }
}
class student extends human {
    constructor() {
        super()
        console.log("This is student class constructor")
    }
}
const student_1 = new student()
student_1.eat()
Enter fullscreen mode Exit fullscreen mode

注 3

class human {
    constructor(name) {
        console.log("Human class constructor" , name)
        this.name = name
    }
    eat() {
        console.log("Human can eat")
    }
}
class student extends human {
    constructor(name) {
        this.name = name //not allow
        super()
        console.log("Student class constructor" , name)

    }
}
const student_1 = new student("subham")
student_1.eat()

// this.name = name
// ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
Enter fullscreen mode Exit fullscreen mode

在 super 关键字之后你可以使用这个

class human {
    constructor(name) {
        console.log("Human class constructor" , name)
        this.name = name
    }
    eat() {
        console.log("Human can eat")
    }
}
class student extends human {
    constructor(name) {
        super()
        this.name = name
        console.log("Student class constructor" , name)

    }
}
const student_1 = new student("subham")
student_1.eat()

// Human class constructor undefined
// Student class constructor subham
// Human can eat
Enter fullscreen mode Exit fullscreen mode

▶️ 方法重载

类中有两个或多个具有相同名称和不同参数的方法(或函数)

⭐ 我们可以在 JavaScript 中重载函数吗?

JavaScript 本身并不支持像其他一些语言(例如 Java)中那样的方法重载。这意味着你不能在同一个类中定义多个同名但参数不同的方法。不过,你可以使用一些技巧来实现类似的功能,例如检查单个方法中参数的数量和类型。

你不能在 JS 中做到这一点

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

    add(a, b, c) {
        return a + b + c;
    }
}

const calc = new Calculator();
console.log(calc.add(1, 2)); // This will throw an error because the first add method is overwritten
Enter fullscreen mode Exit fullscreen mode

如果你愿意,你可以通过这样做来实现

class Calculator {
    add(...args) {
        if (args.length === 2) {
            return args[0] + args[1];
        } else if (args.length === 3) {
            return args[0] + args[1] + args[2];
        } else {
            throw new Error("Invalid number of arguments");
        }
    }
}

const calc = new Calculator();

console.log(calc.add(1, 2)); // Output: 3
console.log(calc.add(1, 2, 3)); // Output: 6
Enter fullscreen mode Exit fullscreen mode

▶️访问修饰符

访问修饰符是用于设置类成员可访问性的关键字

⭐ 访问修饰符的类型

  1. 公共:声明为公共的成员可从任何其他类访问。
  2. 受保护的:声明为受保护的成员可在同一类中以及由派生类实例访问。
  3. 私有:声明为私有的成员只能在同一个类内访问。

⭐ 无障碍设施表

修饰符 父类 Child 类 课外
民众 ✔️ ✔️ ✔️
受保护 ✔️ ✔️
私人的 ✔️

⭐示例

1. 公共成员

公共成员可以从任何地方访问。

class Parent {
    publicProperty = "I'm public";

    publicMethod() {
        return "This is a public method";
    }
}

class Child extends Parent {
    useParentPublic() {
        console.log(this.publicProperty);
        console.log(this.publicMethod());
    }
}

const parent = new Parent();
const child = new Child();

console.log(parent.publicProperty);  // Output: I'm public
console.log(parent.publicMethod());  // Output: This is a public method
child.useParentPublic();
// Output: 
// I'm public
// This is a public method
Enter fullscreen mode Exit fullscreen mode

在此示例中,publicPropertypublicMethod可通过以下方式访问:

  • 在父类中
  • 在 Child 类中
  • 任何课程之外

2. 受保护成员(模拟)

在 JavaScript 中,我们按照惯例使用下划线前缀来表示受保护的成员。从技术上讲,它们仍然是公共的,但开发者同意不在类或其子类的外部直接访问它们。

class Parent {
    _protectedProperty = "I'm protected";

    _protectedMethod() {
        return "This is a protected method";
    }
}

class Child extends Parent {
    useParentProtected() {
        console.log(this._protectedProperty);
        console.log(this._protectedMethod());
    }
}

const parent = new Parent();
const child = new Child();

child.useParentProtected();
// Output:
// I'm protected
// This is a protected method

// These work, but violate the convention:
console.log(parent._protectedProperty);
console.log(parent._protectedMethod());
Enter fullscreen mode Exit fullscreen mode

在这种情况下:

  • _protectedProperty并且_protectedMethod可以在 Parent 中访问
  • 它们也可以在 Child(继承)中访问
  • 从技术上讲,它们可以在外部访问,但这违反了惯例

3. 私有成员

私有成员是真正私有的,并且只能在定义它们的类中访问。

class Parent {
    #privateProperty = "I'm private";

    #privateMethod() {
        return "This is a private method";
    }

    usePrivate() {
        console.log(this.#privateProperty);
        console.log(this.#privateMethod());
    }
}

class Child extends Parent {
    tryToUseParentPrivate() {
        // These would cause errors if uncommented:
        // console.log(this.#privateProperty);
        // console.log(this.#privateMethod());
    }
}

const parent = new Parent();
const child = new Child();

parent.usePrivate();
// Output:
// I'm private
// This is a private method

// These would cause errors:
// console.log(parent.#privateProperty);
// console.log(parent.#privateMethod());
// child.tryToUseParentPrivate();
Enter fullscreen mode Exit fullscreen mode

在这种情况下:

  • #privateProperty并且#privateMethod只能在 Parent 中访问
  • 尽管 Child 扩展了 Parent,但它们在 Child 中无法访问
  • 它们在课堂之外根本无法访问

关键要点

  1. 公共成员(默认)可在任何地方访问。
  2. 受保护的成员(约定_)可以在类和子类中访问,但不应在外部访问(尽管从技术上讲可以)。
  3. 私有成员(带有#)只能在定义类内访问,而不能在子类或外部访问。
  4. 当使用受保护的成员时,它们在可访问性方面的行为与公共成员一样,但开发人员同意将它们视为受保护的成员。
  5. 真正的隐私和封装只有使用语法的私有成员才能实现#

▶️ 静态

static 关键字为类定义静态方法或字段

静态方法是属于类本身的方法,而不是属于该类的任何特定实例的方法。

class Animal {
    constructor(name) {
        this.name = Animal.capitalize(name);
    }

    static capitalize(name) {
        return name.charAt(0).toUpperCase() + name.slice(1);
    }

    walk() {
        console.log(`Animal ${this.name} is walking`);
    }
}

const animal = new Animal("lion");
animal.walk(); // Output: Animal Lion is walking

console.log(Animal.capitalize("elephant")); // Output: Elephant
Enter fullscreen mode Exit fullscreen mode

要点:

  1. 使用关键字将该方法capitalize声明为静态的static
  2. 它在类(Animal.capitalize)上被调用,而不是在实例上。
  3. 它可以在构造函数内部或使用类名的其他方法中使用。

⭐ 继承和静态方法

静态方法被子类继承:

class Human extends Animal {
    static greet() {
        console.log("Hello!");
    }
}

const human = new Human("john");
human.walk(); // Output: Animal John is walking

console.log(Human.capitalize("sarah")); // Output: Sarah
Human.greet(); // Output: Hello!
Enter fullscreen mode Exit fullscreen mode

笔记:

  1. 该类Human继承了静态方法capitalizeAnimal
  2. Human也可以定义自己的静态方法,例如greet

⭐ 从非静态方法调用静态方法

您可以从非静态方法调用静态方法,但需要使用类名:

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

    multiply(a, b) {
        // Using a static method in a non-static method
        return Calculator.add(a, 0) * b;
    }
}

const calc = new Calculator();
console.log(calc.multiply(3, 4)); // Output: 12
console.log(Calculator.add(5, 6)); // Output: 11
Enter fullscreen mode Exit fullscreen mode

⭐ 静态方法 vs. 实例方法

下面通过比较来说明差异:

class MyClass {
    static staticMethod() {
        return "I'm a static method";
    }

    instanceMethod() {
        return "I'm an instance method";
    }
}

console.log(MyClass.staticMethod()); // Output: I'm a static method

const obj = new MyClass();
console.log(obj.instanceMethod()); // Output: I'm an instance method

// This would throw an error:
// console.log(MyClass.instanceMethod());

// This would also throw an error:
// console.log(obj.staticMethod());
Enter fullscreen mode Exit fullscreen mode

⭐ 静态方法的用例

  1. 实用函数:不需要对象状态的方法。
  2. 工厂方法:创建具有特殊属性的实例。
  3. 缓存或固定配置:存储所有实例的共享数据。

工厂方法的示例:

class User {
    constructor(name, role) {
        this.name = name;
        this.role = role;
    }

    static createAdmin(name) {
        return new User(name, "admin");
    }
}

const admin = User.createAdmin("Alice");
console.log(admin.role); // Output: admin
Enter fullscreen mode Exit fullscreen mode

⭐ 关键要点

  1. 静态方法是在类上定义的,而不是实例上定义的。
  2. 使用类名来调用它们:ClassName.methodName()
  3. 它们可以被子类继承。
  4. 它们不能直接访问实例属性或方法。
  5. 它们对于实用功能、工厂方法和管理类级数据很有用。
  6. 您不能在实例上调用静态方法,也不能在类上调用实例方法。

▶️ Getter 和 Setter

Getters 和 setters 是分别允许你获取和设置对象值的函数

//getter setter
class human {
    constructor(name, age) {
        this._name = name;
    }
    get getName() {
        return this._name;
    }
    set setName(name) {
        this._name = name;
    }
}

const person = new human("", 0);
person.setName = "Raj";
person.setAge = 25;

console.log(person.getName);
console.log(person.getAge);

//Raj
//25
Enter fullscreen mode Exit fullscreen mode

▶️instanceOf 运算符

检查对象是否是类、子类或接口的实例

//getter setter
class human {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    get getName() {
        return this.name;
    }
    set setName(name) {
        this.name = name;
    }
    get getAge() {
        return this.age;
    }
    set setAge(age) {
        this.age = age;
    }
}

const person = new human("", 0);
person.setName = "Raj";
person.setAge = 25;

console.log(person.getName);
console.log(person.getAge);

const person1 = "Subham"

console.log( person instanceof human)//true
console.log( person1 instanceof human)//false
Enter fullscreen mode Exit fullscreen mode

对于子类,它也返回 true

//getter setter
class human {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    get getName() {
        return this.name;
    }
    set setName(name) {
        this.name = name;
    }
    get getAge() {
        return this.age;
    }
    set setAge(age) {
        this.age = age;
    }
}

class Coder extends human {
    constructor(name, age, language) {
        super(name, age);
        this.language = language;
    }
}

const person = new human("", 0);
const subham = new Coder("subham", 22, "java");
person.setName = "Raj";
person.setAge = 25;


console.log( person instanceof human)
console.log( subham instanceof human)
Enter fullscreen mode Exit fullscreen mode

▶️ 封装

封装是一种限制直接访问对象某些组件的方法

class BankAccount {
    #balance; // Private field

    constructor(initialBalance) {
        this.#balance = initialBalance;
    }

    deposit(amount) {
        if (amount > 0) {
            this.#balance += amount;
        }
    }

    getBalance() {
        return this.#balance;
    }
}

const account = new BankAccount(1000);
account.deposit(500);
console.log(account.getBalance()); // 1500
// console.log(account.#balance); // Syntax error: private field
Enter fullscreen mode Exit fullscreen mode
//Encapsulation
const user = {
    firstName: "John",
    lastName: "Doe",
    age: 25,
    getAgeYear: function() {
        return new Date().getFullYear() - this.age;
    }
}
console.log(user.getAgeYear());
Enter fullscreen mode Exit fullscreen mode

▶️ 多态性

多态性的意思是“多种形式”,当我们有许多通过继承相互关联的类时就会出现多态性。

// Parent class
class Animal {
  makeSound() {
    console.log("The animal makes a sound");
  }
}

// Child classes
class Dog extends Animal {
  makeSound() {
    console.log("The dog barks");
  }
}

class Cat extends Animal {
  makeSound() {
    console.log("The cat meows");
  }
}

// Function to demonstrate polymorphism
function animalSound(animal) {
  animal.makeSound();
}

// Usage
const animal = new Animal();
const dog = new Dog();
const cat = new Cat();

animalSound(animal); // Output: The animal makes a sound
animalSound(dog); // Output: The dog barks
animalSound(cat); // Output: The cat meows
Enter fullscreen mode Exit fullscreen mode

▶️抽象

抽象是隐藏复杂的实现细节并仅显示对象必要特征的概念。

// Abstraction: Hiding complex implementation details and showing only the necessary features of an object.

// Abstract class
class Vehicle {
    constructor(brand) {
        this.brand = brand;
    }

    // Abstract method
    start() {
        throw new Error("Method 'start()' must be implemented.");
    }

    getBrand() {
        return this.brand;
    }
}

// Concrete class
class Car extends Vehicle {
    start() {
        return `${this.brand} car is starting...`;
    }
}

// Usage
const myCar = new Car("Toyota");
console.log(myCar.getBrand()); // Output: Toyota
console.log(myCar.start());    // Output: Toyota car is starting...
Enter fullscreen mode Exit fullscreen mode
文章来源:https://dev.to/codexam/oops-in-js-ultimate-4j34
PREV
全栈开发人员词汇表(第二部分,更高级)第二部分:更高级
NEXT
你准备好迎接 React 18 了吗?