文章目录

  • class类 与 构造函数
  • class类
  • 一、创建一个类
  • 二、继承
  • 1 全部继承自父类
  • 2 super关键字
  • 2.1 类中的继承关系
  • 2.2 super调用父类中的普通函数
  • 构造函数和原型
  • 1 创建一个构造函数
  • 2 实例成员和静态成员
  • 3 prototype原型对象
  • 4 对象原型__proto__
  • 5 原型链
  • 6 继承




class类

一、创建一个类

constructor函数在创建实例化对象的时候,就进行调用

class Car {
	// 构造器方法
	constructor(name, price) {
		// 构造器中的this--类的实例对象
		this.name = name
		this.price = price
	},
	// 一般方法
	// 这个方法放在了类的原型对象上,供实例使用
	// 通过Car的实例调用该方法时,this指向的就是Car的实例对象
	drive() {
		console.log(`我开${this.name}牌汽车`)
	}
}
// 创建Car的实例对象
const c1 = new Car('奔驰', '50w')
const c2 = new Car('宝马', '40w')
  • 通过赋值语句创建的方法,是放在实例自身上的,调用通过实例对象名.方法名
  • 直接声明的方法,是放在原型对象上的,调用通过实例对象名.方法名
  • 如果方法前面用static进行修饰,这个方法时放在类的本身上的,调用通过类名.方法名
class Car {
	drive() {
		console.log('这个方法放在了原型对象上')
	}
	fun = ()=> {
		console.log('这个方法放在了实例自身上')
	}
	static fun1 = ()=> {
		console.log('我前面用static进行修饰, 我是加在类本身的方法上的方法')
	}
	static fun2() {
		console.log('我前面用static进行修饰, 我是加在类本身的方法上的方法')
	}
}
const c1 = new Car()
c1.drive()
c1.fun()
Car.fun1()
Car.fun2()

class的template构造函数_javascript

二、继承

1 全部继承自父类

class Bus extends Car {}

const b1 = new Bus('解放', '10W')

console.log(b1)
// Bus { name: '解放', price: '10W' }
b1.drive()
// 我开解放牌汽车

2 super关键字

// 继续上面的例子
class Bus extends Car {
  constructor(name, price, load) {
    super(name, price)
    this.load = load
  }
}

const b1 = new Bus('解放', '10W', '20t')

console.log(b1)
// Bus { name: '解放', price: '10W', load: '20t' }

super关键字只能放在构造器函数最前面执行

2.1 类中的继承关系
// 继续上面的例子
b1.drive()
// 我开解放牌汽车

此时,b1的原型对象Bus上并没有drive方法,因此通过原型链向上找到Car原型对象,Car的原型上有drive,因此,此时b1是通过原型链调用的Car上的方法


class Bus extends Car {
  constructor(name, price, load) {
    super(name, price)
    this.load = load
  }
  drive() {
    console.log(`我开${this.name}牌汽车,我的载重是${this.load}`)
  }
}

const b1 = new Bus('解放', '10W', '20t')

b1.drive() 
// 我开解放牌汽车,我的载重是20t

此时,b1的原型对象Bus上有drive方法,因此,b1调用的就是他原型对象上的drive方法

2.2 super调用父类中的普通函数
class Car {
  constructor(name, price) {
    this.name = name
    this.price = price
  }
  drive() {
    return `我是${this.name}牌汽车,我的价格是${this.price}`
  }
}

class Bus extends Car {
  constructor(name, price, weight) {
    super(name, price)
    this.weight = weight
  }
  drive() {
    console.log(super.drive() + ',我的载重是' + this.weight)
  }
}

const b1 = new Bus('解放', '10w', '10t')

b1.drive()

在子类的普通函数中,可以通过super.父类函数名(),来调用父类中的普通函数

构造函数和原型

1 创建一个构造函数

function Car(name, price) {
  this.name = name
  this.price = price
  this.drive = ()=> {
    console.log(`我是${this.name}牌汽车,我的价格是${this.price}`)
  }
}

const c1 = new Car('奔驰', '50w')

console.log(c1)

c1.drive()

2 实例成员和静态成员

构造函数中的属性和方法,统称为成员。

  1. 实例成员就是在构造函数中,通过this添加的成员。实例成员只能通过实例对象进行方法,不能通过构造函数进行访问
  2. 静态资源是在构造函数本身添加的成员。静态资源只能通过构造函数访问,不能通过实例对象访问
function Car(name, price) {
  this.name = name
  this.price = price
  this.drive = ()=> {
    console.log(`我是${this.name}牌汽车,我的价格是${this.price}`)
  }
}
Car.country = '美国'
const c1 = new Car('奔驰', '50w')
// name price drive都是实例成员,只能通过实例对象进行访问,不能通过构造函数进行访问
console.log(c1.price)  // 50w
console.log(Car.price) // undefined

// length是在构造函数本身添加的成员,所以是静态成员
console.log(c1.country)  // undefined
console.log(Car.country) // 美国

3 prototype原型对象

在创建构造函数时,我们不要把不变的方法定义到构造函数内部,这样浪费内存,要定义到构造函数prototype原型对象上。

function Car(name, price) {
  this.name = name
  this.price = price
}
// 这里如果用箭头函数,会造成this为undifined
Car.prototype.drive = function() {
  console.log(`我是${this.name}牌汽车,我的价格是${this.price}`)
}
const c1 = new Car('奔驰', '50w')

c1.drive()
  1. 原型是一个对象,我们也称为prototype原型对象
  2. 我们把方法定义到prototype原型对象上后,所有的实例都可以使用这个方法,不会在内存开辟新的空间
  3. prototype原型对象上有个属性constructor,他指向构造函数本身。
  4. prototype原型对象中的this指向的是实例对象

4 对象原型__proto__

对象上有一个属性__proto__,他指向的是实例对象的构造函数的prototype原型对象

  • 实例对象的__proto__属性 等价于 构造函数的prototype属性
  • 调用时,首先看实例对象上是否有要调用的方法,如果没有,就去__proto__上查找对应方法,等于去构造函数的prototype原型对象上查找。

5 原型链

c1通过c1.__proto__指向Car.prototype ,car的原型对象prototype也是一个对象,他也有__proto__属性,Car.prototype.__proto__指向的是Object.prototype原型对象,Object.prototype.__proto__指向null

6 继承

function Father (fullName, age) {
      this.fullName = fullName
      this.age = age
    }

    Father.prototype.say = function() {
      console.log('我要说', this.fullName)
    }
    function Son (fullName, age, height) {
      // 通过call方法,调用构造函数Father,并将他的this修改为Son
      // 通过这种方法继承构造函数内部的属性和方法
      Father.call(this, fullName, age)
      this.height = height
    }
    // 通过这种方式继承挂载到原型对象上的属性和方法
    Son.prototype = new Father()
    // 再手动将constructor指向回Son
    Son.prototype.constructor = Son

    const s = new Son('小明', 18, '180')

    console.log(s)
    s.say()