前端开发日记 # 原型

143 阅读2分钟

历史原因

由于JS是基于对象的编程语言,大白话意思就是JS里面所有东西都是对象,包括:函数、数组等

与面向对象的编程语言不同的是,JS里面没有的概念,哪怕ES6新增的,也只是一种语法糖

什么是原型

JS 中最特别的就是 函数 了,函数有 3 种形式:

  1. 普通函数 (用于调用)
  2. 构造函数 (用于创建对象,函数体中this指向创建的对象)
  3. 对象 (原型对象就是挂载在对象中prototype属性上)

无论是函数声明还是函数表达式,JS引擎都会自动给函数对象添加一个属性(prototype),这个属性指向的就是我们所讲的原型(原型对象,因为原型就是一个对象类型的)

只有函数才有原型,而且该函数是作为构造函数使用时,原型才有意义,所以我们原型又称为 —— 构造函数原型对象

原型有什么作用

  1. 降低内存使用量,把同一类对象的共同东西(方法、属性)放到原型对象上
  2. 用于实现继承特性,除了原型,还要靠后面介绍的原型链

原型链又是什么

如果仅仅只有原型,而没有原型链,那原型是没有意思的,因为函数(构造)创建的对象是无法访问到原型

JS中,所有对象(普通对象、函数、数组等)JS引擎都会自动添加一个隐式属性:__proto__

该属性指向对象的构造函数原型对象

为何叫隐式属性?
在开发中,无须开发者显式调用的属性

正因为这个隐式属性的加入,但访问对象实例上某个属性或方法时,如果对象上不存在该属性或方法,系统就会根据__proto__属性,到原型对象上去查找,这样就形成了一条查找链,我们称其为“原型链

问题

1、如果覆盖原型,那之前创建的对象所指向的原型会发生变化吗?

function Person(){}

const p = new Person()

Person.prototype.age = 19;

Person.prototype = {
    age: 18
}

const pn = new Person()

console.log(pn.age);  // 18

console.log(p.age);   // 19

总结:之前创建的对象指向的原型不会发生变化,而覆盖之后创建的对象,指向的原型才发生变化

2、pn.orgName 与 pn.__proto__.orgName 区别

前者是从pn对象自身开始查找orgName属性,如果没有就到其构造函数原型对象去找

而后者是从其构造函数原型对象去找orgName属性,如果没找到,就继续沿原型链继续查找,比前者少找自身一级