oops-in-javascript-with-easy-to-understand-examples-2ppn

原始地址:https://dev.to/nehal_mahida/oops-in-javascript-with-easy-to-understand-examples-2ppn

[
](https://dev.to#introduction)
Introduction
在本文中,我们将学习并使用javascript中的面向对象编程(OOP)概念。
如果您来自像C++或Java这样的面向对象编程语言,您可能希望在javascript中使用基于类的语法。
如果您不了解OOP,不用担心,我将用易于理解的示例来解释所有的概念。
[
](https://dev.to#nice-to-have)
好的要求
在ES6发布之前,我们使用构造函数来使用OOP概念。但现在,借助ES6类的帮助,我们可以获得更类似于C++或Java的语法来使用OOP概念。
(ES6类在幕后使用相同的构造函数)
很酷🙂
但是什么是面向对象编程?🤔
这里是OOP的一个流行定义
面向对象编程(OOP)是一种基于对象概念的编程范例。
意味着什么?🙄
这意味着我们在OOP语言中实现的一切都是通过对象来实现的,这里的对象定义了现实世界的实体,例如Student或Car(稍后详细介绍)。
好!但为什么我们需要OOP?
好问题!
开发OOP的主要目标是组织代码的结构。使用OOP,您可以编写更模块化和可维护的代码。您可以将代码与现实世界的实体关联起来。
通过使用OOP,可以确保一个代码的只允许成员对其他人可访问。这使得您的代码在未经身份验证的访问(在代码中)方面完全安全。
明白了吗?
现在,让我们逐步看一下面向对象编程的主要概念。
[
](https://dev.to#object)
对象
如上所述,对象就像现实生活中的实体一样。它们具有属性和方法。
以汽车作为一个对象。汽车有许多特征,如颜色、公司名称、型号名称和价格等。在汽车上,我们可以执行启动、制动和停止等操作。这里汽车的特性是属性,而操作是方法。
如果您使用javascript一段时间了,您可能已经在代码中多次使用了对象,但可能没有以面向对象的方式。
让我在这里创建一个用户对象。
const user = {
name: 'Nehal Mahida',
userName: 'nehal_mahida',
password: 'password:)',
login: function(userName, password) {
if (userName === this.userName && password === this.password) {
console.log('Login Successfully');
} else {
console.log('Authentication Failed!!');
}
},
};
user.login('nehal', 'nehal');
user.login('nehal_mahida', 'password:)');
// Authentication Failed!!
// Login Successfully
上面的代码可以很好地解释。我创建了一个具有一些属性和操作的用户对象。
没有新东西,对吧?
让我们了解更多的OOP概念。
[
](https://dev.to#class)
类
类是现实生活实体的蓝图。它描述了对象的外观,它具有什么特征以及我们可以对其执行哪些操作。
类只是一个模板。无法对其执行任何操作。将类视为您的网站UX设计(线框图)。您创建它是为了了解最终您的网站UI将如何看起来。用户无法像在实际网站上那样与您的线框图交互。
我们通过类实例化对象。我们可以创建类的许多实例。
让我们举个例子。
class User {
#password;
constructor(name, userName, password) {
this.name = name;
this.userName = userName;
this.#password = password;
}
login(userName, password) {
if (userName === this.userName && password === this.#password) {
console.log('Login Successfully');
} else {
console.log('Authentication Failed!!');
}
}
setPassword(newPassword) {
this.#password = newPassword;
}
};
const nehal = new User('Nehal Mahida', 'nehal_mahida', 'password:)');
const js = new User('JavaScript', 'js', 'python:)');
nehal.login('nehal_mahida', 'password:)'); // Login Successfully
js.login('js', 'python:)'); // Login Successfully
console.log(nehal.name); // Nehal Mahida
console.log(nehal.password); // undefined
console.log(nehal.#password); // Syntax Error
nehal.setPassword('new_password:)');
nehal.login('nehal_mahida', 'password:)'); // Authentication Failed!!
nehal.login('nehal_mahida', 'new_password:)'); // Login Successfully
在上面的示例中,我创建了名为
User 的类,它具有一些属性和方法。然后,我使用
new User() 创建该类的实例,并传递所需属性的值。
您看到了一个未调用的
constructor 方法吗??
实际上,方法已被调用 🙄
当我们使用
new 关键字从类创建一个对象时,javascript 内部调用 constructor 方法,该方法初始化类的公共和私有属性。对象在这里可以访问类的所有公共属性和方法。
公共和
私有属性是什么??
默认情况下,类中声明的所有属性都是公共的,意味着可以从类的外部调用和修改它们。您可以在构造函数内外声明公共属性。这里,
name 和
userName 是公共属性。
私有属性呢?
再看一下代码。您是否注意到密码是在构造函数方法之外声明的,并以
# 开头?
Hash(#
)表示此属性对该类是私有的,只有在类内部声明的方法才能访问它。私有属性必须在使用之前声明。
当我尝试打印密码时,得到了
undefined,因为我没有名为“password”的成员,然后我尝试使用“#password”,这给了我一个语法错误,因为“#password”是私有的。
要打印/修改私有属性,我们需要
**getter/setter** 方法。这里我创建了一个设置新密码的方法。
以下概念是面向对象编程的四大支柱。
[
](https://dev.to#encapsulation)
封装
**封装**是指将数据和方法绑定到一个单元中,以保护其免受外部访问的影响。就像药片内包含了药物一样。
在类的上下文中,一些属性不会直接从类的外部访问。您需要调用负责这些属性的方法。
听起来熟悉吗?
是的,你猜对了。这就像为我们在类中声明的私有属性创建get/set方法一样。
在上面的示例中,我们已经使用了封装。我们将(逻辑地)将私有属性
password 与公共方法
setPassword() 绑定在一起。您还有一个getter方法,它返回私有属性的当前值。
[
](https://dev.to#abstraction)
抽象
人们经常将**封装**误认为**抽象**。抽象是封装的下一步。抽象是指只显示必要信息并隐藏内部实现。
让我们以汽车为例。在车上,我们可以执行一些操作,如启动、制动和停止。当您调用其中一个操作时,它会给您一些结果。这些操作有某些子操作对您隐藏起来,但您不需要关心这些子操作。
这就是汽车公司使用功能抽象为客户提供流畅体验的方式。
让我们再来看一个抽象的例子。假设您在前端项目中使用了某些第三方react组件。该组件为您的定制提供了许多props和方法。该组件并非是魔术,它内部使用相同的HTML标签、CSS和javascript。但现在您不需要担心这些事情。您只需要设置props并根据自己的要求调用方法。这就是抽象。
让我们编码吧🤩
class User {
name;
email;
#password;
constructor() {}
#validateEmail(email) {
// check email is valid or not.
return true;
}
#validatePassword(password) {
// check password is satisfying the minimum requirements or not.
return true;
}
signUp(name, email, password) {
let isValidated = false;
isValidated = this.#validateEmail(email);
isValidated &&= this.#validatePassword(password);
if (isValidated) {
this.name = name;
this.email = email;
this.#password = password;
// add user in your db.
console.log('User registered successfuly');
} else {
console.log('Please enter correct Details!!');
}
}
login(email, password) {
if (email === this.email && password === this.#password) {
console.log('Login Successfully');
} else {
console.log('Authentication Failed!!');
}
}
#isRegisteredUser(email) {
// check user is registered or not.
return true;
}
resetPassword(email, newPassword) {
if (this.#isRegisteredUser(email)) {
this.#password = newPassword;
console.log('Operation performed successfully');
}
else {
console.log('No account found!');
}
}
};
const nehal = new User();
nehal.signUp('Nehal Mahida', 'nm@gmail.com', 'password:)'); // User registered successfuly
nehal.#validateEmail('nm@gmail.com'); // Syntax Error.
nehal.login('nm@gmail.com', 'password:)'); // Login Successfully
nehal.resetPassword('nm@gmail.com', ''); // Operation performed successfully
在上面的示例中,我们引入了一些
**私有**方法。这些方法在执行一些工作,并且它们不会暴露给类的外部。
这些方法由公开可用的方法调用。
作为一个开发人员,我只需要提供从UI接收到的详细信息并调用相应的方法。
在
**Java**等面向对象编程语言中,我们有**抽象类**和**接口**的概念。这在javascript中是不可能的。
否则,我们可以创建一个抽象类,并且其他类可以使用该类来实现类似的功能。
因此,我们可以说我们使用封装来实现抽象。 😊
[
](https://dev.to#inheritance)
继承
当一个类继承了另一个类的属性和方法时,它被称为OOP中的继承。继承属性的类称为**子类**或**子类**,继承属性的类称为**父类**或**父类**。
我们为什么需要继承?
继承是OOP中非常重要的概念。继承的主要优点是**重用性**。当子类从父类继承时,我们不需要重复编写相同的代码。当我们需要更改属性时,只需在父类中更改它,所有子类将自动继承更改。继承还有助于代码的**可读性**。
让我们编码...
class User {
#password;
constructor(email, password) {
this.email = email;
this.#password = password;
}
login(email, password) {
if (email === this.email && password === this.#password) {
console.log('Login Successfully');
} else {
console.log('Authentication Failed!!');
}
}
resetPassword(newPassword) {
this.#password = newPassword;
}
logout() {
console.log('Logout Successfully');
}
}
class Author extends User {
#numOfPost;
constructor(email, password) {
super(email, password);
this.#numOfPost = 0;
}
createPost(content) {
// add content to your DB. :)
this.#numOfPost++;
}
getNumOfPost() {
return this.#numOfPost;
}
}
class Admin extends User {
constructor(email, password) {
super(email, password);
}
removeUser(userId) {
// remove this userId from your DB.
console.log('User Removed successfully.');
}
}
const nehal = new Author('nm@gmail.com', 'password:)');
nehal.login('nm@gmail.com', 'password:)');
nehal.createPost('I hope you are enjoying this article. Don\'t forget to leave your feedback. :)');
nehal.createPost('I am tired, Do you wanna buy me a coffee? :)');
console.log(nehal.getNumOfPost()); // 2
const json = new Admin('jason@gmail.com', '[Object] [object]');
json.login('jason@gmail.com', '[Object] [object]');
json.resetPassword('{id: 1}');
json.login('jason@gmail.com', '{id: 1}');
json.removeUser(12);
在上面的示例中,通过使用
extends 和
super 关键字,**Author** 和
**Admin** 类继承了**User** 类的属性。
**extends** 关键字用于在两个类之间建立父子关系。在第一个示例中,**Author** 成为子类,**User** 成为父类。
子类可以访问父类的所有公有和受保护成员。此外,它可以拥有自己的属性和方法。这就是我们通过继承实现**重用性**的方式。
**super** 关键字是一个特殊的关键字。在子类的构造函数中调用**super**会调用父类的构造函数。这就是我们在**Author** 和**Admin** 类中初始化属性的方式。
子类还可以重写父类的方法。这引入了**多态**的概念。
[
](https://dev.to#polymorphism)
多态
多态意味着“多种形式”。就像我们一样,作为软件工程师,我们可以在前端、后端、DevOps甚至测试方面工作。😅
多态有两种类型。
- 编译时多态性
- 运行时多态性
**函数重载**是一种编译时多态性。在这里,我们创建了多个具有相同名称但不同参数或类型的函数。
在javascript中不支持函数重载,因为如果您创建具有相同名称的函数,javascript将使用前面的函数重写最后定义的函数。
**方法重写**是一种运行时多态性。记得我告诉过您可以在子类中重写父类的方法吗?这就是方法重写。
让我们举个例子。
class User {
constructor(email, password) {
this.email = email;
this.password = password;
}
login(email, password) {
if (email === this.email && password === this.password) {
console.log('Login Successfully');
} else {
console.log('Authentication Failed!!');
}
}
}
class Author extends User {
#numOfPost;
constructor(email, password) {
super(email, password);
this.#numOfPost = 0;
}
createPost(content) {
// add content to your DB. :)
this.#numOfPost++;
}
getNumOfPost() {
return this.#numOfPost;
}
}
class Admin extends User {
constructor(email, password) {
super(email, password);
}
login(email, password) {
// add extra layer of security as this is an admin account.
const isValidAdmin = true; // we can have some 2FA type security check here.
if (email === this.email && password === this.password && isValidAdmin) {
console.log('Admin Login Successfully');
} else {
console.log('Authentication Failed!!');
}
}
removeUser(userId) {
// remove this userId from your DB.
console.log('User Removed successfully.');
}
}
const nehal = new Author('nm@gmail.com', 'password:)');
nehal.login('nm@gmail.com', 'password:)'); // Login Successfully
const json = new Admin('jason@gmail.com', '[Object] [object]');
json.login('jason@gmail.com', '[Object] [object]'); // Admin Login Successfully
在上面的示例中,**Author** 和
**Admin** 都继承自
**User** 类。这两个类都有
**User** 类的
login 方法。现在我需要对管理员账户进行额外级别的验证,所以我在**Admin** 类中创建了一个
login 方法,它会重写父类的
login 方法。
当**Admin** 类的对象调用
login 方法时,它将调用该类的
login 方法的函数调用。
这就是我们使用方法重写实现多态的方式。
到此为止。我们已经涵盖了使用javascript进行OOP的所有概念。🤩
**注意**:上述所有信息均基于我的知识和研究。如果您发现有任何错误,请在评论中纠正我。愉快学习🙂
如果您喜欢这篇文章,请点赞、分享并为其加上书签🔖!
如果您在Twitter上,请关注,我会分享一些关于学习Web开发的很棒资源。🙏🏻
感谢您的反馈🤗
🏃♂️ 让我们联系 👇
🕊
👨💻
[Github](https://github.com/NehalMahida)
[
](https://dev.to#support)
🙌 支持
如果您喜欢我的文章,请考虑用一杯咖啡支持我。☕
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值