美文网首页
JS继承知识点总结

JS继承知识点总结

作者: wo不是黄蓉 | 来源:发表于2021-08-04 21:37 被阅读0次

学习继承之前自我感觉比较混乱的几个概念?

  • 什么是构造函数?
  • 什么是原型?什么是原型链?
  • 什么是原型对象?什么是实例对象?

第一个:什么是构造函数?

在es5中构造函数在js中其实就是一个普通的函数,但是我们约定用new关键字创建实例的函数叫做构造函数。
在es6中其实用class声明的对象也是一个函数,class 不过是个语法糖

举个例子:

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  sayHi() {
    console.log("hello world");
  }
}
console.log(Person. prototype);  //{constructor:f,sayHi:f,[[Prototype]]:Object}
console.log(Person .__proto__);//f(){}

let fn = function () {
  this.a = 1;
  this.b = 2;
};
console.log(fn.__proto__);//f(){}
console.log(fn.prototype);//{constructor:f,[[Prototype]]:Object}

第二个:什么是原型?

在js中原型也是一个对象,通过原型可以实现对象的属性继承。在js中存在一个[[Prototype]]属性,就是刚才构造函数的fn.prototype返回的内容中就可以看到该属性,js中这个属性对象的就是该对象的原型。但是[[Prototype]]是一个内部的属性不能够被访问,又但是在浏览器厂商实现了一个 __ proto__ 的非标准属性返回内容和[[Prototype]]一样,以此来获取对象的原型

什么是原型链?

即:构造函数的原型对象,其原型对象又有自己的原型对象对象,层层向上形成原型链,知道一个对象的原型对象为Null

举个例子:


原型链.png

第三个:什么是原型对象?

通俗来讲对象的.prototype属性就是获取该对象的,如第一段代码Person.prototype或者fn.prototype返回的是一个对象

什么是实例对象?

实例对象通过构造函数进行创建,再通俗来讲通过new 关键字创建的对象即可称之为实例对象。实例对象没有.prototype属性,因为实例对象它不是一个函数,只有函数才有protype属性

原型对象、原型、实例对象、构造函数之间有什么关系?


image.png

进入正题继承

实现继承有哪些方式?

es5中主要使用call/apply来实现继承,es6中使用extends关键字+super来实现
es5主要的几种实现方式,分为两大类:使用原型链继承、使用构造函数继承。

  • 原型链继承:关键使用prototype属性来实现的继承。
    • 缺点:原型中包含的引用值会在所有实例之间共享,只能在原型上修改属性和方法,因此派生出来的类不能传递自己的参数。
    • 举个例子:
function Parent() {
 this.name = 'Foo'
}
function Child() {}
// 继承 Parent
Child.prototype = new Parent();
let child1= new Child();
child1.name = 'Bar'
console.log(child1.name); // Bar
let child2= new Child();
console.log(child2.name); // Bar
  • 构造函数继承:关键是使用call或者apply来实现
    • 缺点:因为继承是写在子类里面的,函数不能进行复用;并且此时不能判别上一级的原型链,原型链断开了
    • 好处:可以解决原型链继承原型中包含的引用值会在所有实例之间共享问题,并且,call后面也可以传递自己的参数
    • 举个例子:
function Animal() {
  this.species = "动物";
  this.sleep = function () {
    return this.species + "正在睡觉";
  };
}

function Cat(name, color) {
  Animal.call(this, arguments);
  this.name = name;
  this.color = color;
}

let cat = new Cat("小咪", "block");
console.log(cat);
cat.sleep();
  • 组合继承(原型链+构造函数)
    • 思路:使用原型链继承原型上的方法和属性,通过构造函数继承实例属性
    • 举个例子
function Animal() {
  this.species = "动物";
  this.sleep = function () {
    return this.species + "正在睡觉";
  };
}

function Cat(name, color) {
  Animal.call(this, arguments);
  this.name = name;
  this.color = color;
}
let animal = new Animal();
Cat.prototype = animal;  //将构造函数的原型对象指向父类实例,实现对父类属性和方法的继承
Cat.__proto__ = Cat.constructor;  //将构造函数的原型指向子类构造函数本身,实现子类特有的方法
let cat = new Cat("小咪", "block");
console.log(cat);

  • 原型式继承(本质上是实现了一个浅复制,原型式继承-利用空对象进行继承:Object.create的实现方式)
    • 缺点:本质上是实现对传入对象的引用,因此是浅复制,修改值会同步进行修改,存在共享属性问题
function Person(name) {
  this.name = name;
  this.sum = function () {
    console.log("hello ,my name is" + this.name);
  };
}

function content(obj) {
  function F() {}
  F.prototype = obj;
  return new F();
}
var sup = new Person("你叫啥");
var sup1 = new Person("我叫啥");
console.log(content(sup).name)  //你叫啥
console.log(content(sup1).name)  //你叫啥
  • 寄生式继承(实现一个函数工厂,通过content浅拷贝对象,通过工厂函数定义自有属性和方法)
    • 缺点:同上
function Person(name) {
  this.name = name;
  this.sum = function () {
    console.log("hello ,my name is" + this.name);
  };
}

function content(obj) {
  function F() {}
  F.prototype = obj;
  return new F();
}
var person= new Person("江卫国");
var person1=  new Person("江卫民");
console.log(content(sup))

function subObject(obj) {
  var sub = content(obj);
  sub.name = "gar";
  return sub;
}
var sup2 = subObject(person);
var sup3 = subObject(person1);
console.log(sup2)//gar,自身存在name属性不必往上一级进行查找
console.log(sup3)//gar
  • 寄生式组合继承(寄生+构造函数)
    • 可以解决构造出来不同实例的属性共享问题
    • 缺点:效率问题,父类构造函数会被调用两次,一次是创建子类实例的时候,一次是在子类构造函数中调用的时候
function Person(name) {
  this.name = name;
  this.sum = function () {
    console.log("hello ,my name is" + this.name);
  };
}

function content(obj) {
  function F() {}
  F.prototype = obj;
  return new F();
}

var con = content(Person.prototype);
function Sub(name) {
  Person.call(this, name);  //第二次
}
Sub.prototype = con;  //将子类的构造函数的实例指向构造出来的对象//第一次
con.constructor = Sub;  //将构造出来的对象的构造函数指向子类,以此实现隔离不同实例之间的参数,由此我们也可以看出来只有实现了自己的构造函数才能进行自定义参数
var sub1 = new Sub("我是姜卫国"); 
var sub2 = new Sub("我是姜卫民");
console.log(sub1);//我是姜卫国
console.log(sub2);//我是姜卫民

参考:https://www.jianshu.com/p/b853d80b6c6a
《JavaScript高级程序设计(第4版)》

完结...

相关文章

  • JS继承知识点总结

    学习继承之前自我感觉比较混乱的几个概念? 什么是构造函数?什么是原型?什么是原型链?什么是原型对象?什么是实例对象...

  • JS中继承

    js中的继承无论是在面试还是在实际应用中都是一个高频的知识点,总结梳理下。 方法1.通过构造函数实现继承 通过构造...

  • JS继承--总结

    先说一个有关面向对象的小知识点有助于大家对后面理解 1.每个构造函数都有一个原型对象(prototype).//即...

  • js继承总结

    最近在准备面试,js继承真的好乱鸭鸭鸭鸭,整理一下~希望可以记得!(参考:https://blog.csdn.ne...

  • class-继承(es6)

    继承-JS 继承-class class-总结 Class 在语法上更加贴合面向对象的写法Class 实现继承更加...

  • JS继承

    羡慕java的继承,一个extend搞定开头总结一下JS继承的方式:原型链继承,借用构造函数继承,组合继承,原型式...

  • javaScript中继承的几种形式

    js中继承是一个相对复杂的问题,这里我自己做了一些总结,便于日后复习。 什么是继承? js中的继承可以从对象的角度...

  • JS继承的几种方式

    关于Js继承的几种方式,总结一下,以便查看。 第一种 prototype 引用型原型继承 语言支持:js原生支持的...

  • js:原型、继承总结

    前言 在面试中,我们常常被问到原型的问题还有js的继承实现。但是这个概念很广,理解起来比较费劲。 以下我将会从为什...

  • JS继承方式总结

    1、构造函数绑定方式 优点:简单易懂缺点:无法继承父类A的原型里的属性和方法 2、原型模式 优点:子类可以继承父类...

网友评论

      本文标题:JS继承知识点总结

      本文链接:https://www.haomeiwen.com/subject/fnalvltx.html