继承

147 阅读1分钟

一、继承

继承可以使得子类具有父类的各种属性和方法,而不需 要再次编写相同的代码。在令子类别继承父类别的同时, 可以重新定义某些属性,并重写某些方法,即覆盖父类别 的原有属性和方法,使其获得与父类别不同的功能。

1.1、ES3写法

function Mammal(name) {  
this.name = name
  this.head = '头'
  this.neck = '颈'
  this.body = '躯干'
 } 

Mammal.prototype.birth = function() { 
 console.log(this.name + '生了个宝宝') 
} 
let animal = new Mammal('大汪') 
animal.birth()

1.2、ES6写法

class Mammal {  
     constructor(name) { 
          this.name = name 
     } 
 head = '头'  
 neck = '额' 
 body = '躯干' 
 birth() {  
  console.log(`${this.name}生了个宝宝`)
   } 
let animal = new Mammal('大汪') 
animal.birth()

二、关于js中function和class的内在关系及区别的理解

2.1、定义class

  class事实上是一种特殊的funcion,就像可以定义funcion表达式和funcion声明一样,class语法也有2种形式:class表达式和class声明。

2.2、class声明

  定义一个class,可以使用class关键字加上类名。需要注意的是,funcion声明和class声明有一个重要的却别:funcion声明是hosting(状态提升)的,而class不是,class需要先声明再使用。

class Rectangle {
constructor(height, width) {
  this.height = height;
 this.width = width;
}
}

三、class中body和method的定义

  class的body部分包含在花括号{ }中,这里是定义class成员的地方,比如constructor和method。

3.1、constructor

  constructor方法是一个特殊的方法,用来创建并初始化一个对象。在一个class中只能有一个命名为constructor的特殊方法,如果包含多个将会报错。   constructor中可以通过super关键字,调用父类的constructor方法。

3.2、prototype methods(原型方法)

class Rectangle {
   constructor(height, width) {
   this.height = height;
   this.width = width;
  }
  // Getter
  get area() {
    return this.calcArea();
 }
  // Method
   calcArea() {
   return this.height * this.width;
   }
 }

const square = new Rectangle(10, 10);
 
console.log(square.area); // 100

四、获取父类属性

4.1、.call

function Human(name) {  
//等价于 Mammal(name),Mammal里面的this是当前的this  
Mammal.call(this, name)  
 this.clothes = '衣服'
 }    
Human.prototype.speak = function() {  
console.log(this.name + '会说话')
 } 
let p = new Human('小明') 
console.log(p.head) 
console.log(p.clothes) 
p.speak()

4.2、call、apply、bind

 fn.call(obj, a, b, ...) 
ü 等价于 fn(a, b, ...) ,执行时fn函数里面的this是传递的 obj对象

fn.apply(obj, [a, b, ...])
ü 等价于 fn(a, b, ...),执行时fn里面的this是传递的obj对 象 

fn.bind(obj)(a, b, ...) 
ü 等价于 fn(a, b, ...),执行时fn里面的this是传递的obj对 象

五、获取父类方法

5.1、ES3 写法

function Human(name) {
  Mammal.call(this, name)  
   this.clothes = '衣服' 
} 

Human.prototype = Object.create(Mammal.prototype) Human.prototype.constructor = Human 

Human.prototype.speak = function() {  
console.log(this.name + '会说话')
 } 

let p = new Human('小明')
 p.birth() 
p.speak()

5.2、ES6 写法 - 多了exends 和 super

class People {
  constructor(name) {
    this.name = name
  }
  setName(name) {
    this.name = name
  }
  sayName() {
    console.log('我的名字是' + this.name)
  }
}

class Doctor extends People{
  constructor(name, profession) {
    super(name)
    this.profession = profession
  }
  sayProfession() {
    console.log('我的职业是' + this.profession)
  }
}

六、hasOwnPerperty

判断对象自身属性中是否具有指定的属性(自由属性:绑定在自身上的属性,不是在原型链上的)

let p = new Human('小明') 
p.hasOwnPerperty('name')  // true 
p.hasOwnPerperty('speak') // false 
p.hasOwnPerperty('birth') // false

七、拓展知识

7.1、Object.assign

  • 将所有可枚举属性的值从一个或多个源对象复制到目标 对象
  • 它将返回目标对象。
const target = { a: 1, b: 2 } 
const source = { b: 4, c: 5 } 
const returnedTarget = Object.assign(target, source) 

console.log(target)      //  { a: 1, b: 4, c: 5 } 

console.log(target === returnedTarget) // true

原理:object.assign 就是对target 进行处理 属性名相同就进行覆盖,没有就新增,最后聚合成一个新的对象,本身就是对target进行操作

如果想新生成一个新的对象,可以加个{ },
例如
const obj1={a:1,b:2}
const obj2={a:4,d:3}
const obj3 = Object.assign({},obj1,obj2)
// obj3  {a: 4, b: 2, d: 3}
// obj1  {a: 1, b: 2}

7.2、Mixin

定义 : 通过不使用继承的方式让一个类中的方法被其他类复用

  1. mixin在javascript里可以看作是一种从别的对象"借用"功能的方法。每一个新定义的对象都有一个 prototype属性,其他的对象就可以从这里"借用"功能。这里的功能可以是一个属性,也可以是一个方法。
  2. mixins这种借用在 javascript里非常的适用。在重用代码的时候可以使用mixins来实现继承,也可以达到类似多继承的效果。

const mixin = (Base, mixins) => Object.assign(Base.prototype, mixins)

const Fly = {    // 对象
  canFly() {                              // 省略了 canFly:function( ){
      console.log('I can fly')  
} 
}
class Mammal {   
      birthChild() { 
            console.log('I birth a baby')
 } 
} 
mixin(Mammal, Fly) 
let m = new Mammal()
m.birthChild()
m.canFly

7.3、getter、setter

将对象属性绑定到查询/设置该属性时将被调用的函数

const people = {  
  firstName: 'Micheal',  
  lastName: 'Jackson',  

 get fullName( ) {  
     return `${this.firstName} ${this.lastName}`
  },  
 set fullName(name) {   
    let nameArr = name.split(/\s+/)  
    this.firstName = nameArr[0]    
    this.lastName = nameArr[1]  
} 
} 
console.log(people.fullName) 
people.firstName = 'John' 
console.log(people.fullName) 
people.fullName = 'Tom Cruse' 
console.log(people.lastName)
  get fullName() {    // funllName 当做是属性
            return `${this.firstName} ${this.lastName}`
  }
加了get的好处就是,调用的时候就不需要括号了 直接People.fullName


fullName:function()  {    
            return `${this.firstName} ${this.lastName}`
  }