类与原型
class Person {
constructor(x,y) {
this.x = x
this.y = y
}
add() {
return this.x + this.y
}
}
let person = new Person(1,2)
console.log(person.add()) // 3
通过类Person
的构造函数实例化了一个对象person
,person
继承了类的add
办法
ES6之前是没有类的概念,所以要实现下面的操作,须要function
出马
function Person(x, y) { // 首字母大写示意它是个类函数
this.x = x
this.y = y
this.add = function() {
return this.x + this.y
}
}
let person = new Person(1,2)
console.log(person.add()) // 3
这样尽管实现了,然而显著有毛病,下面ES6类的构造函数仅初始化了x,y
,默认继承了add
办法,而function
形式的须要初始化所有,所以须要优化
function Person(x, y) {
this.x = x
this.y = y
}
Person.prototype.add = function() {
return this.x + this.y
}
let person = new Person(1,2)
console.log(person.add()) // 3
很显著,通过Person.prototype
实现了class
中this
的作用,这就叫实例原型(实例对象自身就是从类实例化而来,可不就是实例原型)
既然与ES6 class
挂上了钩,这时还短少一个constructor
,巧了,实例原型恰好有一个属性constructor
指向构造函数自身
而且为了造成一个闭环,实例对象也有一个属性__proto__
指向实例原型
因为所有对象都继承于
Object
,所以会有上面的一部分
继承
ES6 继承
class Father{
constructor(name,age) {
this.name = name
this.age = age
}
// 此处的形式其实是挂载在prototype属性上的,反推下面的ES5 语法
sayName() {
console.log(this.name + this.age)
}
}
class Child extends Father{
constructor(name, age, job) {
super(name,age) // 必须调用super办法,并且肯定要在应用this之前调用,相当于Father.prototype.constructor.call()
this.job = job
}
sayJob() {
console.log(this.job)
}
// 笼罩父类的办法
sayName() {
console.log('hello world') // 调用父类的属性,输入:hello world
}
}
let kid = new Child('nike','20','teacher')
kid.sayJob() // teacher
kid.sayName() // hello world
其中的要害是super
,super
作为一个办法在调用父类的构造函数,同时也能够作为一个对象,指向父类的prototype
对象,而下面的调用父类属性会呈现undefined
,因为name
并没有挂载在父类的prototype
上,从新革新一下
class Father{
constructor(name,age) {
Father.prototype.name = name
this.age = age
}
}
因为sayName
办法是挂载在prototype
属性上的,所以能够间接super.sayName()
调用,而且调用办法执行的上下文this
是指向子类的
class Father{
constructor(name,age) {
this.name = name
this.age = age
this.job = 'Hello world'
}
sayJob() {
console.log(this.job)
}
}
class Child extends Father{
constructor(name, age, job) {
super(name,age) // 必须调用super办法,并且肯定要在应用this之前调用
this.job = job
}
sayJob() {
super.sayJob() // teacher
}
}
let kid = new Child('nike','20','teacher')
kid.sayJob() // teacher
原型链继承
从下面的剖析可知,xxx.prototype
作为实例原型,它领有跟实例对象一样的属性和办法,所以只须要把父类的实例对象赋值给子类的prototype
属性,那么不就继承了
function Father(name) {
this.name = name
}
function Child(age) {
this.age = age
}
Child.prototype = new Father('nike') // 将父类的实例对象赋值给Child的prototype
let kid = new Child(20) // 实例子类对象
console.log(kid.name) // nike
console.log(kid.age) // 20
构造函数继承
因为ES5的类
是个函数,所以借助函数的个性能够实现另外一种继承
function Father(name) {
this.name = name
}
function Child(age) {
Father.call(this, 'nike')
this.age = age
}
let kid = new Child(20)
console.log(kid.name) // nike
这两个就够了,其余形式都是画龙点睛
判断一个对象是否另一个对象的原型
person instanceof Person // true
person instanceof Object // true
Person.prototype.isPrototypeOf(person) // true
Object.prototype.isPrototypeOf(person) // true
发表回复