JS继承知识点总结

2021-08-04  本文已影响0人  wo不是黄蓉

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

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

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

在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主要的几种实现方式,分为两大类:使用原型链继承、使用构造函数继承。

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
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);

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)  //你叫啥
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版)》

完结...

上一篇 下一篇

猜你喜欢

热点阅读