目录
class类的构造方法
每个类都可以有一个自己的构造函数(方法),这个方法的名称是固定的constructor
每个类只能有一个构造函数,如果包含多个构造函数,那么会抛出异常
// 类的声明
class Person {
// 类的构造方法 注:一个类只能有一个构造函数, 如果没有定义那就自动用默认的
// 通过new关键字操作类的时候,会调用constructor函数,并执行如下操作
// 1、在内存中创建一个对象 moni = {}
// 2、 将类的原型prototype赋值给创建出来的对象 moni.__proto__ = Person.prototype
// 3、将对象赋值给函数的this:new绑定 this = moni
// 4、执行函数中的代码
// 5、自动返回创建出来的对象
constructor() {
}
}
let p1 = new Person()
let P2 = new Person('kobe', 30)
class中的方法定义
let names = ['abc', 'cba']
class Person {
constructor(name, age) {
this.name = name
this.age = age
this.address = '长沙'
}
// 第一种 定义普通的实例方法
eating() {
console.log(this.name + 'eating')
}
running() {
console.log(this.age +running)
}
// 第二种 定义类的访问器方法
get address() {
console.log('拦截访问操作')
return this._address
}
set address(newAddress) {
console.log('拦截设置操作')
this._address = newAddress
}
// 第三种 类的静态方法(类方法) 可以通过类名直接访问
// 譬如 Person.randomPerson()直接调用
static randomPerson() {
// 譬如这里实现生成一个随机的值,从names里面取
// Math.floor()是向下取整,所以不包含100。向上取整的话就不包含0
let nameIndex = Math.floor(Math.random() * names.length)
let name = names[nameIndex]
// 生成一个0-100的随机数
let age= Math.floor(Math.random() * 100)
return new Person(name, age)
}
}
let p1 = new Person('kobe', 18)
let p2 = new Person('why', 25)
console.log(p1) // 输出 Person {name: 'kobe', age: 18}
console.log(p2) // 输出 Person {name: 'why', age: 25}
// 调用类的静态方法 随机生成一个值
let p3 = Person.randomPerson()
// 生成多个值
for (let i = 0; i < 50; i++) {
console.log(Person.randomPerson())
}
class中实现继承的过程
静态方法: 只能使用类名调用,直接在类上面,不在原型上面(不需要通过实例调用的时候,就可以通过静态方法)。
构造方法:定义在constructor里的方法,只有在new创建对象的时候才会调用
// 子类继承自父类的构造函数
// 父类
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
running() {
console.log(this.name + 'running')
}
eating() {
console.log(this.name + 'eating')
}
// 譬如perosonMthod
personMethod() {
console.log('处理逻辑1')
console.log('处理逻辑2')
console.log('处理逻辑3')
}
// 静态方法
static staticMethod() {
console.log('personStaticMethod')
}
}
// Student称之为子类(或者是派生类)
class Student extends Person {
// JS引擎在解析子类的时候就有要求,如果我们有实现继承
// 那么子类的构造方法中,在使用this之前,必须要调用一个super(),或者在return之前调用
// 通过super调用父类的构造函数
constructor(name, age, sno) {
super(name,age) // 通过super() 调用父类的方法 就不需要写 this.name = name
this.sno= sno
}
// 譬如想要在perosonMthod这个方法基础上 增加逻辑处理 可以使用super()
// 子类对父类方法的重写,并且复用父类的方法逻辑
personMethod() {
super.personMethod() // 先执行父类的方法
console.log('处理逻辑4')
console.log('处理逻辑5')
console.log('处理逻辑6')
}
// 如果对父类方法不满意 也可重写父类静态方法
static staticMethod() {
// 可以通过super 先调用父类的方法
super.staticMethod()
// 然后再继续编写自己需要的逻辑
console.log('StudentStaticMethod')
}
}
let stu = new Student('why', 18, 111)
console.log(stu) // 输出 Student {name: 'why', age: 18, sno: 111}
// 继承过来的方法在父类的原型对象上
stu.eating() // 输出 why eating
stu.running() // 输出 why running
stu.personMethod()
// 输出 处理逻辑1 处理逻辑2 处理逻辑3 处理逻辑4 处理逻辑5 处理逻辑6
// 可以直接调用父类的静态方法
Student.staticMethod() // 输出 personStaticMethod
// 重写父类的方法之后
Student.staticMethod() // 输出 personStaticMethod StudentStaticMethod
创建类继承自内置
// 定义一个class,默认情况下有个类,继承的就是Object
// 譬如 class Foo {} 就等于 class Foo extends Object {}
class Foo {
}
// 譬如 如果要继承数组的处理方式,可以继承自数组
class HYArray extends Array {
firstItem() {
return this[0]
}
lastItem() {
return this[this.length-1]
}
}
let arr = new Array(1,2,3)
JS中实现混入效果(mixins)的一些方式
JavaScript的类只支持单继承,也就是只能有一个父类。
应用场景:在开发中我们需要在一个类中添加更多相似的功能时,可以使用混入(mixin)
class Person {}
// 定义一个mixins方法
function mixinRunner(BaseClass) {
class NewClass extends BaseClass {
running() {
console.log('running')
}
}
return NewClass
}
// 在JS中类只能有一个父类: 也叫单继承
class Student extends Person {}
let NewStudent = mixinRunner(Student)
let ns = new NewStudent()
ns.running() // 输出 running
// 也可以拓展到 再加一个混入的function
function mixinEater(BaseClass) {
// 返回一个匿名函数
return class extends BaseClass {
eating() {
console.log('eating')
}
}
}
// 再次进行扩展
let NewStudent = mixinEater(mixinRunner(Student))
let ns = new NewStudent()
ns.running() // 输出 running
ns.eating() // 输出 eating
传统面向对象多态
传统的面向对象多态有三个前提:
1、必须有继承
2、必须有重写(子类重写父类的方法)
3、必须有父类引用指向子类对象
// Shape形状,定义一个父类class
class Shape {}
class Rectangle extends Shape {
// 重写父类的方法 返回100
getArea() {
return 100
}
}
class Cirle extends Shape {
// 重写父类的方法 返回200
getArea() {
return 200
}
}
let r = new Reatangle()
let c = new Circle()
// 多态: 当对不同的数据类型执行同一个操作时,如果表现出来的行为(形态)不一样
// 那么就是多态的体现
// 在js中,function就是行为的体现
function calcArea(shape) {
console.log(shape.getArea())
}
calcArea(r) // 输出100
calcArea(c) // 输出200
// 如果没有对r和c进行重写父类方法,那这就不是一个多态的对象。
JS面向对象多态
// 多态:当对不同的数据类型执行同一个操作时,如果表现出来的行为(形态)不一样,那么就是多态的体现
function calcArea(foo) {
console.log(foo.getArea())
}
let obj1 = {
name: 'why',
getArea() {
return 1000
}
}
class Person {
getArea() {
return 100
}
}
let p = new Person()
calcArea(obj1) // 输出 1000
calcArea(p) // 输出 100
// 下面这种也是多态的体现
function sum(m, n) {
return m + n
}
sum(20, 30) // 输出 50
sum('abc', 'cba') // 输出 ‘abccba’