继承的概念和常用方法

113 阅读4分钟

概念

一:继承的概念:

  • 1、在原有的类的基础上快速增加新的功能

  • 2、不影响到原来的类,也不改变原来类的代码,方便对于功能的扩展

  • 3、继承是一种创建新类的方式,新建的类可以继承一个或多个类。

  • 4、新建的类称为派生类(子)类,之前存在的类称为基(父)类
    记忆方法:基就是地基是盖房子的第一步,所以是之前的就存在的,派生就是派生出新的被,肯定是后出现的,所以叫派生,在原来的类上派生出新的类,那么有原来的类才有后来派生的,有父亲才能有儿子,儿子是父亲生下来的,所以也可以叫父类和子类

涉及到的api

1Object.setPrototypeOf(hd, parent);//创建  Object.getPrototypeOf(hd)//获取
1、创建极简对象
let xj = Object.create(null, {  name: { value: "向军" }} );

2、
let hd = {};
let parent = { name: "parent" };
Object.setPrototypeOf(hd, parent);
console.log(hd);
console.log(Object.getPrototypeOf(hd));

Object.create()不会继承大Boss Object上的原型,它会把你传入的第一个参数对象作为原型来继承,第二个参数是关于它自己的自有属性的描述。

而new 操作符以及对象字面量创建方式都会继承大老板 Object的原型上的属性方法。

call也不会继承function的原型上的属性方法,只是实例化function构造函数

new一个函数会返回什么?

new操作符在执行过程中会改变this的指向,所以在了解new操作符之前,我们先解释一下this的用法。

function Cat (name, age) 
{
this.name = name;
this.age = age;//没写return 就是return this
}
console.1og (new cat('mi aomiao', 18)); 
// Cat [name: "miaomiao", age: 18]

输出的结果中包含了name与age的信息。事实上我们并未通过return返回任何值,为什么输出的信息中会包含name和age属性呢?其中起作用的就是this这个关键字了。

image.png

function Cat (name, age) {
var Cat = {Cat.name = name Cat.age = age;}
return Cat;
}
console.1og (new Cat('mi aomi ao'18), 18)
// Cat [name: "miaomiao", age: 18]

结果一样

但是这样子的对象没有绑定原型的,要写下面的代码

obj._ _proto_ _ = Cat.prototype;

实现继承的几种方法

1、原型链继承

原型链继承的主要思想是:重写子类的prototype属性,将其指向父类的实例。

Cat.prototype = new Animal();

2、构造器继承

将父类的实例的属性和函数绑定到子类的this上\

function Cat(name) {   
 // 核心,通过call()函数实现Animal的实例的属性和函数的继承
Animal.call(this);   this.name = name || 'tom';
}

3、(原型链+构造器 继承)extends

function Super(name, age) {//父类,超类
     this.name = name;
     this.age = age;
}
Object.assign(Super.prototype, {
     sleep() {
        console.log(`${this.name} is sleeping!`);
     }
})

//子类
function Sub(name, age, gender) {
     Super.call(this, name, age);
    //以调用父类构造函数的形式,得到执行结果,将this绑定为当前的实例对象
    //普通调用时,this的指向window而不是当前实例对象,所以使用方法借用,绑定this的指向
     this.gender = gender;
     Sub.prototype = Object.create(Super.prototype);
     //以父类的prototype为原型,创建一个空对象,替换子类的prototype

   //由于空对象身上没有constructor引用,赋值
    Sub.prototype.constructor = Sub;
    
   //自己的方法
Object.assign(Sub.prototype, {
     eat() {
         console.log(`${this.name} is eating!`);
     }
});
let sub1 = new Sub("zs", 18, "male");
// sub1.constructor===>fn Sub//sub1通过自己身上的__proto__指向创建它的类的原型对象 
//Sub.prototype,prototype身上有它所在的构造函数的引用constructor
//sub1.__proto__.constructor====>fn Sub

}

为什么子类构造器中要先执行super

image.png

使用 Mixin 实现多继承,

image.png

Object.assign(Admin.prototype, Request, Credit);

function extend(sub, sup) {
  sub.prototype = Object.create(sup.prototype);
  sub.prototype.constructor = sub;
}
function User(name, age) {
  this.name = name;
  this.age = age;
}
User.prototype.show = function() {
  console.log(this.name, this.age);
};
const Credit = {
  total() {
    console.log("统计积分");
  }
};
const Request = {
  ajax() {
    console.log("请求后台");
  }
};

function Admin(...args) {
  User.apply(this, args);
}//“相当于复制的方式”拿到user的属性给创造出来的Admin实例

extend(Admin, User);
Object.assign(Admin.prototype, Request, Credit);
let hd = new Admin("向军", 19);
hd.show();
hd.total(); //统计积分
hd.ajax(); //请求后台

应用

1、给普通对象添加Object原型上的方法

内置对象.prototype.方法.call(要处理的对象, item => {
    return item.hasAttribute("class");//原来例子是过滤节点,含有class属性的
  })

2、为 Object 原型对象添加方法,

将影响所有函数

<body>
  <button onclick="this.hide()">后盾人</button>
</body>
<script>
  Object.prototype.hide = function() {
    this.style.display = "none";
  };
</script>

原型链关系图

image.png

1、对象有__proto__ 函数有prototype

2、对象由函数产生

3、对象的__proto__ 指向 函数的prototype

image.png

所有原型对象都是Object构造函数生成的,指父。

原型对象--》父Objiect.proty 构造函数都--》Func提on。prototype【额

构造函数的“构造能力”怎么来的?Function.prototype传承下来的额

强语言的类的基本特征:抽象、封装、继承、多态 js基于原型的对象机制,也可以达到类的基本特征:抽象、封装、继承、多态

遇到的问题

同样是new,构造函数产生的,构造函数里面的方法不见了,类里面的方法放到了原型里面"__ proto __")。(但为什么类不能 在 控制台打印出来)
因为忘记加this.了!!