JS原型、原型链和继承

60 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

原型的规则

  1. 每个对象都有一个内置的隐式原型__proto__属性
  2. 每个函数都有一个显式原型prototype属性
  3. 通过new操作符创建出来的对象的隐式原型会指向构造函数的显式原型

function Person(){}

var p1 = new Person()

p1.__proto__ == Person.prototype//true

4.constructor 4.1 在创建Person函数的时候,函数Person的原型对象的constructor属性指向Person函数本身 4.2 如果给函数Person的原型对象赋一个新的对象,那么这个对象的constructor指向的是Object 4.3 通过Object.defineProperty()函数将原型对象的constuctor重新指向Person

image.png

原型链的定义

我们从一个对象上获取属性,如果在对象本身没有找到,就会到原型上面找,原型是一个对象,该对象又有自己的原型属性,对应一个对象;原型上面没有,就会到原型的原型上面找,直到obj,就形成了原型链

对象

对象的创建

构造函数方法\构造函数+原型方法

代码:

image.png

内存图:

image.png

构造函数方法弊端:重复创建函数属性

面试的时候被问到:函数放在函数体内和放在函数的原型上有什么区别? 普通的属性放在构造函数里 方法放在构造函数的显式原型,这样批量创建对象的时候才不会重复创建函数,占用内存

对象的继承

继承的作用:将类中相同的代码抽取,放到父类,子类就可以继承自父类

使用原型链继承(面试被问到了)

image.png

image.png

先创建一个父类的实例对象,再将该对象赋值给父类的原型,就可以实现继承

弊端:

  1. 直接打印stu对象看不到继承的属性
  2. 如果属性是引用类型(数组),比如本例中friends属性,就会出现问题
  3. 不能给Person传递参数

借用构造函数继承

image.png

弊端:

  1. p对象多出一些属性
  2. Person函数至少被调用2次

原型式继承

  1. 法1:setPrototypeOf 将传入的对象作为新创建的对象的原型
  2. 法2:新建函数
  3. 法3:Object.create()

image.png

寄生组合继承

核心代码

image.png

类的继承(class)

class只是function的语法糖 class的实例对象的原型也指向class的原型

class要接收参数 要通过构造函数constructor 当new操作符操作一个类的时候会自动调用constructor

放在class Person里的方法就相当于将方法放在函数Person的原型上

类的访问器方法 在get、set属性的时候做拦截操作

类的静态方法 可以直接通过类来调用的方法 Person.randomPerson()

对象的其他方法

  1. hasOwnProperty方法 判断属性在对象本身
  2. in 操作符 只要有这个元素就返回in
  3. A instanceOf B用来检测 B的原型有没有出现在A的原型链上