JavaScript面向对象-既熟悉又陌生的它
2024-01-26 11:24:56
关于对象,之前学过的java就是一门纯面向对象的语言,在更早之前JavaScript只能说是基于对象的语言,随着ES6的出现,JavaScript的面向对象的思想也变得更加明确。
理解JavaScript中的面向对象
JavaScript是一种基于原型的语言,这意味着对象不是通过类创建的,而是通过原型创建的。原型是对象的模板,它定义了对象可以拥有的属性和方法。
在JavaScript中,每个对象都有一个原型,原型对象也是一个对象,它也有一个原型,依此类推,直到到达Object.prototype。Object.prototype是所有JavaScript对象的根原型。
JavaScript中的类
ES6中引入了class,使JavaScript更像一门面向对象的语言。class关键字允许你创建类,类是对象的模板,它定义了对象的属性和方法。
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
}
const person = new Person('John Doe', 30);
person.greet(); // Hello, my name is John Doe and I am 30 years old.
继承
在JavaScript中,继承是通过原型链实现的。每个对象都有一个原型,原型对象也是一个对象,它也有一个原型,依此类推,直到到达Object.prototype。
当一个对象访问一个不存在的属性或方法时,JavaScript会沿着原型链向上查找,直到找到该属性或方法。
例如,以下代码演示了如何创建一个Person对象并继承自Object.prototype:
const person = {
name: 'John Doe',
age: 30
};
person.greet(); // TypeError: person.greet is not a function
因为Person对象没有greet方法,JavaScript会沿着原型链向上查找,直到找到Object.prototype。Object.prototype没有greet方法,因此抛出TypeError异常。
为了解决这个问题,我们可以将greet方法添加到Person对象的原型上:
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};
person.greet(); // Hello, my name is John Doe and I am 30 years old.
现在,当Person对象访问greet方法时,JavaScript会沿着原型链向上查找,找到Person.prototype上的greet方法,并执行它。
封装
封装是指将对象的属性和方法隐藏起来,只允许通过特定的方法来访问它们。这有助于保护对象的数据免遭意外更改,并使对象更容易维护。
在JavaScript中,封装可以通过使用闭包来实现。闭包是指能够访问其创建时的变量的函数。
例如,以下代码演示了如何使用闭包来封装Person对象的数据:
const Person = (function() {
const privateData = {};
function Person(name, age) {
privateData[this] = {
name: name,
age: age
};
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${privateData[this].name} and I am ${privateData[this].age} years old.`);
};
return Person;
})();
const person = new Person('John Doe', 30);
person.greet(); // Hello, my name is John Doe and I am 30 years old.
console.log(person.name); // undefined
console.log(person.age); // undefined
因为Person对象的数据被封装在闭包中,因此无法直接访问它们。只能通过Person对象的greet方法来访问这些数据。
多态
多态是指能够以不同的方式响应相同的消息。这有助于使代码更灵活和可重用。
在JavaScript中,多态可以通过使用继承和接口来实现。
例如,以下代码演示了如何使用继承来实现多态:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
}
class Student extends Person {
constructor(name, age, school) {
super(name, age);
this.school = school;
}
study() {
console.log(`I am studying at ${this.school}.`);
}
}
class Teacher extends Person {
constructor(name, age, subject) {
super(name, age);
this.subject = subject;
}
teach() {
console.log(`I am teaching ${this.subject}.`);
}
}
const person = new Person('John Doe', 30);
person.greet(); // Hello, my name is John Doe and I am 30 years old.
const student = new Student('Jane Doe', 20, 'Harvard University');
student.greet(); // Hello, my name is Jane Doe and I am 20 years old.
student.study(); // I am studying at Harvard University.
const teacher = new Teacher('Michael Jones', 40, 'Mathematics');
teacher.greet(); // Hello, my name is Michael Jones and I am 40 years old.
teacher.teach(); // I am teaching Mathematics.
因为Student类和Teacher类都继承自Person类,因此它们都可以响应greet消息。但是,它们以不同的方式响应greet消息。Student类以“I am studying at {this.school}.”的方式响应greet消息,而Teacher类以“I am teaching {this.subject}.”的方式响应greet消息。
这使得我们可以使用相同的代码来处理不同类型的对象,从而使代码更灵活和可重用。