持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情
这篇文章给入门的人看的。其他人免得浪费时间绕过。
翻译自github的一个专栏
Day 15
Classes
JavaScript是一门面向对象的语言,在JavScript中万物皆对象,对象有自己的属性和方法。我们通过对象来创建类。类像一个对象的构造方法,或者是创建统一对象的模板。我们通过创建对象来实例化类。类定义了对象的属性和行为,在另一方面对象就是代表了类。
一旦我们创建了类,只要我们想,可以随时通过创建对应类对象。从类创建对象称为类实例化
In the object section, we saw how to create an object literal. Object literal is a singleton. If we want to get a similar object , we have to write it. However, class allows to create many objects. This helps to reduce amount of code and repetition of code.
创建类
在JavaScript创建类,需要通过关键字class。class后面跟名称遵循驼峰命名(CamelCase)紧接着花括号包裹的代码块
class name {}让我们创建Person类
// syntax
class ClassName {
// code goes here
}
Example:
class Person {
// code goes here
}
我们创建了一个空的Person类。
类实例化
实例化类意味着通过class 创建对象,我们需要用到关键字new。在new后面跟着调用类的名称。
让我们创建dog对象通过我们Person类
class Person {
// code goes here
}
const person = new Person()
console.log(person)
Person {}
如您所见,我们创建了一个person对象。由于类没有任何属性,因此也是一个空对象
我们可以使用类构造函数给类定义不同属性,并且赋值。
Constructor构造函数
构造函数 Constructor是一个内置函数。我们可以通过构造函数创建对象的模板。构造函数以关键字constructor开头,然后后面跟括号,在括号里面,我们传参数作为类属性。我们通过this 关键字关联构造函数的参数和类属性。
下面Person对象的构造函数包含firstName和lastName属性。这些属性通过this关联到Person对象。this指代类本身。
class Person {
constructor(firstName, lastName) {
console.log(this) // Check the output from here
this.firstName = firstName
this.lastName = lastName
}
}
const person = new Person()
console.log(person)
Person {firstName: undefined, lastName:undefined}
对象的所有key都是undefined。每当我们实例化的时候,我们需要传递属性的值,在实例化类对象的时候让我们传递值
class Person {
constructor(firstName, lastName) {
this.firstName = firstName
this.lastName = lastName
}
}
const person1 = new Person('Asabeneh', 'Yetayeh')
console.log(person1)
Person {firstName: "Asabeneh", lastName: "Yetayeh"}
正如我们一开始所说的那样,一旦我们创建了一个类,就可以使用该类创建许多对象。现在,让我们使用Person类创建多个Person对象。
class Person {
constructor(firstName, lastName) {
console.log(this) // Check the output from here
this.firstName = firstName
this.lastName = lastName
}
}
const person1 = new Person('Asabeneh', 'Yetayeh')
const person2 = new Person('Lidiya', 'Tekle')
const person3 = new Person('Abraham', 'Yetayeh')
console.log(person1)
console.log(person2)
console.log(person3)
Person {firstName: "Asabeneh", lastName: "Yetayeh"}
Person {firstName: "Lidiya", lastName: "Tekle"}
Person {firstName: "Abraham", lastName: "Yetayeh"}
我们使用类Person创建了三个persons对象。正如您所看到的,我们的类没有太多属性,因此我们可以向类添加更多属性。
class Person {
constructor(firstName, lastName, age, country, city) {
console.log(this) // Check the output from here
this.firstName = firstName
this.lastName = lastName
this.age = age
this.country = country
this.city = city
}
}
const person1 = new Person('Asabeneh', 'Yetayeh', 250, 'Finland', 'Helsinki')
console.log(person1)
Person {firstName: "Asabeneh", lastName: "Yetayeh", age: 250, country: "Finland", city: "Helsinki"}
构造方法默认值
构造函数属性可以像其他常规函数一样具有默认值。
class Person {
constructor(
firstName = 'Asabeneh',
lastName = 'Yetayeh',
age = 250,
country = 'Finland',
city = 'Helsinki'
) {
this.firstName = firstName
this.lastName = lastName
this.age = age
this.country = country
this.city = city
}
}
const person1 = new Person() // it will take the default values
const person2 = new Person('Lidiya', 'Tekle', 28, 'Finland', 'Espoo')
console.log(person1)
console.log(person2)
Person {firstName: "Asabeneh", lastName: "Yetayeh", age: 250, country: "Finland", city: "Helsinki"}
Person {firstName: "Lidiya", lastName: "Tekle", age: 28, country: "Finland", city: "Espoo"}
类方法
在类中,我们可以创建类方法。方法是类中的JavaScript函数。下面我们创建一些类方法。
class Person {
constructor(firstName, lastName, age, country, city) {
this.firstName = firstName
this.lastName = lastName
this.age = age
this.country = country
this.city = city
}
getFullName() {
const fullName = this.firstName + ' ' + this.lastName
return fullName
}
}
const person1 = new Person('Asabeneh', 'Yetayeh', 250, 'Finland', 'Helsinki')
const person2 = new Person('Lidiya', 'Tekle', 28, 'Finland', 'Espoo')
console.log(person1.getFullName())
console.log(person2.getFullName())
Asabeneh Yetayeh
test.js:19 Lidiya Tekle
带有初始值的属性
当我们为某些属性创建类时,一些属性可能会有一个初始值。例如,如果你在玩游戏,你的起始分数为零。所以,我们可能有一个起始分数或零分。换句话说,我们可能有一个初始技能,一段时间后将会获得一些其他技能。
class Person {
constructor(firstName, lastName, age, country, city) {
this.firstName = firstName
this.lastName = lastName
this.age = age
this.country = country
this.city = city
this.score = 0
this.skills = []
}
getFullName() {
const fullName = this.firstName + ' ' + this.lastName
return fullName
}
}
const person1 = new Person('Asabeneh', 'Yetayeh', 250, 'Finland', 'Helsinki')
const person2 = new Person('Lidiya', 'Tekle', 28, 'Finland', 'Espoo')
console.log(person1.score)
console.log(person2.score)
console.log(person1.skills)
console.log(person2.skills)
0
0
[]
[]
方法可以是普通方法、getter或setter。让我们看看,getter和setter。
getter
get方法允许我们访问对象中的值。我们使用关键字get后跟函数编写了一个get方法。我们使用getter来获取值,而不是直接从对象访问属性。参见下面的示例
class Person {
constructor(firstName, lastName, age, country, city) {
this.firstName = firstName
this.lastName = lastName
this.age = age
this.country = country
this.city = city
this.score = 0
this.skills = []
}
getFullName() {
const fullName = this.firstName + ' ' + this.lastName
return fullName
}
get getScore() {
return this.score
}
get getSkills() {
return this.skills
}
}
const person1 = new Person('Asabeneh', 'Yetayeh', 250, 'Finland', 'Helsinki')
const person2 = new Person('Lidiya', 'Tekle', 28, 'Finland', 'Espoo')
console.log(person1.getScore) // We do not need parenthesis to call a getter method
console.log(person2.getScore)
console.log(person1.getSkills)
console.log(person2.getSkills)
0
0
[]
[]
setter
setter方法允许我们修改某些属性的值。我们使用关键字set后跟一个函数来编写setter方法。请参见下面的示例。
class Person {
constructor(firstName, lastName, age, country, city) {
this.firstName = firstName
this.lastName = lastName
this.age = age
this.country = country
this.city = city
this.score = 0
this.skills = []
}
getFullName() {
const fullName = this.firstName + ' ' + this.lastName
return fullName
}
get getScore() {
return this.score
}
get getSkills() {
return this.skills
}
set setScore(score) {
this.score += score
}
set setSkill(skill) {
this.skills.push(skill)
}
}
const person1 = new Person('Asabeneh', 'Yetayeh', 250, 'Finland', 'Helsinki')
const person2 = new Person('Lidiya', 'Tekle', 28, 'Finland', 'Espoo')
person1.setScore = 1
person1.setSkill = 'HTML'
person1.setSkill = 'CSS'
person1.setSkill = 'JavaScript'
person2.setScore = 1
person2.setSkill = 'Planning'
person2.setSkill = 'Managing'
person2.setSkill = 'Organizing'
console.log(person1.score)
console.log(person2.score)
console.log(person1.skills)
console.log(person2.skills)
1
1
["HTML", "CSS", "JavaScript"]
["Planning", "Managing", "Organizing"]
不要对常规方法和getter之间的区别感到困惑。如果你知道怎么创建正常方法,你就很好了。让我们在Person类中添加名为getPersonInfo的普通方法。
class Person {
constructor(firstName, lastName, age, country, city) {
this.firstName = firstName
this.lastName = lastName
this.age = age
this.country = country
this.city = city
this.score = 0
this.skills = []
}
getFullName() {
const fullName = this.firstName + ' ' + this.lastName
return fullName
}
get getScore() {
return this.score
}
get getSkills() {
return this.skills
}
set setScore(score) {
this.score += score
}
set setSkill(skill) {
this.skills.push(skill)
}
getPersonInfo() {
let fullName = this.getFullName()
let skills =
this.skills.length > 0 &&
this.skills.slice(0, this.skills.length - 1).join(', ') +
` and ${this.skills[this.skills.length - 1]}`
let formattedSkills = skills ? `He knows ${skills}` : ''
let info = `${fullName} is ${this.age}. He lives ${this.city}, ${this.country}. ${formattedSkills}`
return info
}
}
const person1 = new Person('Asabeneh', 'Yetayeh', 250, 'Finland', 'Helsinki')
const person2 = new Person('Lidiya', 'Tekle', 28, 'Finland', 'Espoo')
const person3 = new Person('John', 'Doe', 50, 'Mars', 'Mars city')
person1.setScore = 1
person1.setSkill = 'HTML'
person1.setSkill = 'CSS'
person1.setSkill = 'JavaScript'
person2.setScore = 1
person2.setSkill = 'Planning'
person2.setSkill = 'Managing'
person2.setSkill = 'Organizing'
console.log(person1.getScore)
console.log(person2.getScore)
console.log(person1.getSkills)
console.log(person2.getSkills)
console.log(person3.getSkills)
console.log(person1.getPersonInfo())
console.log(person2.getPersonInfo())
console.log(person3.getPersonInfo())
1
1
["HTML", "CSS", "JavaScript"]
["Planning", "Managing", "Organizing"]
[]
Asabeneh Yetayeh is 250. He lives Helsinki, Finland. He knows HTML, CSS and JavaScript
Lidiya Tekle is 28. He lives Espoo, Finland. He knows Planning, Managing and Organizing
John Doe is 50. He lives Mars city, Mars.
静态方法
static关键字定义类的静态方法。静态方法不是通过类实例调用的。它们是在类本身上调用的。这些通常是工具函数,例如一个用于创建或克隆对象的静态函数。静态方法的一个示例是Date.now()。直接通过类调用now方法。
class Person {
constructor(firstName, lastName, age, country, city) {
this.firstName = firstName
this.lastName = lastName
this.age = age
this.country = country
this.city = city
this.score = 0
this.skills = []
}
getFullName() {
const fullName = this.firstName + ' ' + this.lastName
return fullName
}
get getScore() {
return this.score
}
get getSkills() {
return this.skills
}
set setScore(score) {
this.score += score
}
set setSkill(skill) {
this.skills.push(skill)
}
getPersonInfo() {
let fullName = this.getFullName()
let skills =
this.skills.length > 0 &&
this.skills.slice(0, this.skills.length - 1).join(', ') +
` and ${this.skills[this.skills.length - 1]}`
let formattedSkills = skills ? `He knows ${skills}` : ''
let info = `${fullName} is ${this.age}. He lives ${this.city}, ${this.country}. ${formattedSkills}`
return info
}
static favoriteSkill() {
const skills = ['HTML', 'CSS', 'JS', 'React', 'Python', 'Node']
const index = Math.floor(Math.random() * skills.length)
return skills[index]
}
static showDateTime() {
let now = new Date()
let year = now.getFullYear()
let month = now.getMonth() + 1
let date = now.getDate()
let hours = now.getHours()
let minutes = now.getMinutes()
if (hours < 10) {
hours = '0' + hours
}
if (minutes < 10) {
minutes = '0' + minutes
}
let dateMonthYear = date + '.' + month + '.' + year
let time = hours + ':' + minutes
let fullTime = dateMonthYear + ' ' + time
return fullTime
}
}
console.log(Person.favoriteSkill())
console.log(Person.showDateTime())
Node
15.1.2020 23:56
静态方法是可以用作工具方法。
继承
通过继承 使用继承,我们可以访问父类的所有属性和方法。减少很多重复代码。如果您还记得,我们有一个Person父类,我们将从中创建子类。我们的子类可以是student、teach等。
// syntax
class ChildClassName extends {
// code goes here
}
让我们从Person父类创建一个Student子类。
class Student extends Person {
saySomething() {
console.log('I am a child of the person class')
}
}
const s1 = new Student('Asabeneh', 'Yetayeh', 'Finland', 250, 'Helsinki')
console.log(s1)
console.log(s1.saySomething())
console.log(s1.getFullName())
console.log(s1.getPersonInfo())
Student {firstName: "Asabeneh", lastName: "Yetayeh", age: "Finland", country: 250, city: "Helsinki", …}
I am a child of the person class
Asabeneh Yetayeh
Student {firstName: "Asabeneh", lastName: "Yetayeh", age: "Finland", country: 250, city: "Helsinki", …}
Asabeneh Yetayeh is Finland. He lives Helsinki, 250.
方法覆盖
如您所见,我们可以在子类Student中访问所有父类Person中的方法,我们可以自定义父类的方法,可以在子类中增加更多的属性。如果想要更多属性,我们需要在子类中使用constructor方法,我们调用super()函数以访问父类的所有属性。Person类没有性别,现在让我们为Student子类增加gender属性。如果子类中有与父类相同名称的方法,则父方法将被重写。
class Student extends Person {
constructor(firstName, lastName, age, country, city, gender) {
super(firstName, lastName, age, country, city)
this.gender = gender
}
saySomething() {
console.log('I am a child of the person class')
}
getPersonInfo() {
let fullName = this.getFullName()
let skills =
this.skills.length > 0 &&
this.skills.slice(0, this.skills.length - 1).join(', ') +
` and ${this.skills[this.skills.length - 1]}`
let formattedSkills = skills ? `He knows ${skills}` : ''
let pronoun = this.gender == 'Male' ? 'He' : 'She'
let info = `${fullName} is ${this.age}. ${pronoun} lives in ${this.city}, ${this.country}. ${formattedSkills}`
return info
}
}
const s1 = new Student(
'Asabeneh',
'Yetayeh',
250,
'Finland',
'Helsinki',
'Male'
)
const s2 = new Student('Lidiya', 'Tekle', 28, 'Finland', 'Helsinki', 'Female')
s1.setScore = 1
s1.setSkill = 'HTML'
s1.setSkill = 'CSS'
s1.setSkill = 'JavaScript'
s2.setScore = 1
s2.setSkill = 'Planning'
s2.setSkill = 'Managing'
s2.setSkill = 'Organizing'
console.log(s1)
console.log(s1.saySomething())
console.log(s1.getFullName())
console.log(s1.getPersonInfo())
console.log(s2.saySomething())
console.log(s2.getFullName())
console.log(s2.getPersonInfo())
Student {firstName: "Asabeneh", lastName: "Yetayeh", age: 250, country: "Finland", city: "Helsinki", …}
Student {firstName: "Lidiya", lastName: "Tekle", age: 28, country: "Finland", city: "Helsinki", …}
I am a child of the person class
Asabeneh Yetayeh
Student {firstName: "Asabeneh", lastName: "Yetayeh", age: 250, country: "Finland", city: "Helsinki", …}
Asabeneh Yetayeh is 250. He lives in Helsinki, Finland. He knows HTML, CSS and JavaScript
I am a child of the person class
Lidiya Tekle
Student {firstName: "Lidiya", lastName: "Tekle", age: 28, country: "Finland", city: "Helsinki", …}
Lidiya Tekle is 28. She lives in Helsinki, Finland. He knows Planning, Managing and Organizing
现在,getPersonInfo方法已经被重写,它可以判断这个人是男性还是女性。
🌕 你很优秀。现在,你知道了类,你有能力把一切变成一个对象,你已经成功了一半,现在做一些锻炼大脑和肌肉的练习
练习
练习 Level 1
- 创建动物类。该类将具有名称、年龄、颜色、legs属性并创建不同的方法
- 创建 Dog 和 Cat 子类 继承自 Animal 类.
练习 Level 2
- 重写父类的方法
练习 Level 3
- 让我们尝试开发一个程序来计算样本中心趋势的度量(平均值、中位数、模式)和可变性的度量(范围、方差、标准差)。除了这些度量之外,还可以找到样本的最小值、最大值、计数、百分位数和频率分布。您可以创建一个名为Statistics的类,并创建所有统计和计算的函数作为Statistics类的方法。检查以下输出
ages = [31, 26, 34, 37, 27, 26, 32, 32, 26, 27, 27, 24, 32, 33, 27, 25, 26, 38, 37, 31, 34, 24, 33, 29, 26]
console.log('Count:', statistics.count()) // 25
console.log('Sum: ', statistics.sum()) // 744
console.log('Min: ', statistics.min()) // 24
console.log('Max: ', statistics.max()) // 38
console.log('Range: ', statistics.range() // 14
console.log('Mean: ', statistics.mean()) // 30
console.log('Median: ',statistics.median()) // 29
console.log('Mode: ', statistics.mode()) // {'mode': 26, 'count': 5}
console.log('Variance: ',statistics.var()) // 17.5
console.log('Standard Deviation: ', statistics.std()) // 4.2
console.log('Variance: ',statistics.var()) // 17.5
console.log('Frequency Distribution: ',statistics.freqDist()) // [(20.0, 26), (16.0, 27), (12.0, 32), (8.0, 37), (8.0, 34), (8.0, 33), (8.0, 31), (8.0, 24), (4.0, 38), (4.0, 29), (4.0, 25)]
// you output should look like this
console.log(statistics.describe())
Count: 25
Sum: 744
Min: 24
Max: 38
Range: 14
Mean: 30
Median: 29
Mode: (26, 5)
Variance: 17.5
Standard Deviation: 4.2
Frequency Distribution: [(20.0, 26), (16.0, 27), (12.0, 32), (8.0, 37), (8.0, 34), (8.0, 33), (8.0, 31), (8.0, 24), (4.0, 38), (4.0, 29), (4.0, 25)]
- 创建一个名为PersonAccount的类。它有firstname、lastname、incomes、expense属性,还有totalIncome、totalExpense、accountInfo、addIncome、addExpense和accountBalance方法。Incomes是incomes的set数组和描述expenses也是expenses数组及其描述