历史原因
由于JS是基于对象的编程语言,大白话意思就是JS里面所有东西都是对象,包括:函数、数组等
与面向对象的编程语言不同的是,JS里面没有类的概念,哪怕ES6新增的类,也只是一种语法糖
什么是原型
JS 中最特别的就是 函数 了,函数有 3 种形式:
- 普通函数 (用于调用)
- 构造函数 (用于创建对象,函数体中
this指向创建的对象) - 对象 (原型对象就是挂载在对象中
prototype属性上)
无论是函数声明还是函数表达式,JS引擎都会自动给函数对象添加一个属性(prototype),这个属性指向的就是我们所讲的原型(原型对象,因为原型就是一个对象类型的)
只有函数才有原型,而且该函数是作为构造函数使用时,原型才有意义,所以我们原型又称为 —— 构造函数原型对象
原型有什么作用
- 降低内存使用量,把同一类对象的共同东西(方法、属性)放到原型对象上
- 用于实现继承特性,除了原型,还要靠后面介绍的原型链
原型链又是什么
如果仅仅只有原型,而没有原型链,那原型是没有意思的,因为函数(构造)创建的对象是无法访问到原型
在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属性,如果没找到,就继续沿原型链继续查找,比前者少找自身一级