@[toc]

0 / 两句话

JS中面向对象的底层解决机制

第一句话

=> 每一个(除了三种特例,以外的)函数数据类型,都天生自带一个属性:<u>prototype原型属性</u>,其属性值是:<u>一个对象</u>(Function.prototype除外)

=> 这个prototye原型对象中天生自带一个属性:<u>constructor</u>,其属性值是:<u>以后构造函数自身</u>

第二句话

=> 每一个对象数据类型值,都天生自带一个属性:\proto 原型链属性(或者叫:隐式原型),其属性值指向:<u>所属类的原型对象prototype</u> 能够找到所属类原型上的公共办法

△ 请大声朗诵10遍~

函数数据类型,没有原型属性的特例:

① 箭头函数

let obj = {say(){}}; 这种写法的obj.say()

③ Function.prototype

没有原型属性,不能应用 new 关键字

△ 图1.1_三个没有原型的函数数据类型,不能应用new关键字

函数数据类型

① 一般函数、箭头函数、生成器函数

② 构造函数(自定义类)

③ 内置类(内置构造函数)

④ ……

prototype 原型对象,针对 <u>类</u> 有用,对于一般函数来说没啥用

对象数据类型

① 一般对象、数组对象、正则对象、日期对象……

② prototype 原型对象

③ 实例对象

④ 函数也是对象 前面再细说~

⑤ ……

所有对象都是Object内置类的一个实例

1 / 一道题 and 一张图

function Fn() {    this.x = 100;    this.y = 200;    this.getX = function () {        console.log(this.x);    }}Fn.prototype.getX = function () {    console.log(this.x);};Fn.prototype.getY = function () {    console.log(this.y);};let f1 = new Fn;let f2 = new Fn;console.log(f1.getX === f2.getX);console.log(f1.getY === f2.getY);console.log(f1.__proto__.getY === Fn.prototype.getY);console.log(f1.__proto__.getX === f2.getX);console.log(f1.getX === Fn.prototype.getX);console.log(f1.constructor);console.log(Fn.prototype.__proto__.constructor);f1.getX();f1.__proto__.getX();f2.getY();Fn.prototype.getY();

△ 通过这道题来了解下面的2句话

来来来,依据下面的 <u>2句话</u> 来一一验证这些问题~

△ 图1_一张图

f1 f2new Fn; 创立进去的实例对象

那么,Fn.prototype 原型对象是谁new进去的?

咱不晓得是谁的实例对象时候,那就找Object去吧~

Object 是一个内置类、类、类、类,是个构造函数

△ 图2_Object 是个内置类

Fn.prototype 原型对象上的 getX 和 getY:

① 绝对于 实例 f1 和 f2 来说是公共属性和办法
f1.hasOwnProperty('getY') => false

② 但绝对于Fn.prototype 对象本人来说,就是公有属性

Fn.prototype.hasOwnProperty('getY') => true

属性是公有还是私有=>相对来说的,看参照物是谁

成员拜访:不论是遍历还是间接拜访

=> 点表示法 f1.x

=> 括号表示法 f1['x']

f1.x

① 首先找本人公有的属性,公有中存在,那么操作的就是公有的

② 公有中不存在,则默认基于\proto 找所属类的原型prototype上的

③ 如果还没有,则基于prototype上的\__proto__持续向上查找……

④ 始终找到 Object.prototype 为止

把这套查找机制,称为:原型链查找机制

f1.\__proto__.getX

跳过公有属性查找,间接找到所属类的原型上 的公共属性和办法

留神:在IE浏览器中不兼容\__proto__,浏览器爱护起来了,不让咱用啊~

然而,咱能够用 Object.getPrototypeOf(f1).getX

f1.getX()

① 实例先找到对应的办法基于原型链查找机制

② 再把办法执行

③ 如果遇到this,则剖析this是谁【函数执行看“点”后面是谁】

console.log(f1.getX === f2.getX);//=> falseconsole.log(f1.getY === f2.getY); //=> trueconsole.log(f1.__proto__.getY === Fn.prototype.getY); //=> trueconsole.log(f1.__proto__.getX === f2.getX); //=> falseconsole.log(f1.getX === Fn.prototype.getX); //=> falseconsole.log(f1.constructor); //=>function Fn(){...} 自定义类console.log(Fn.prototype.__proto__.constructor); //=> function Object(){...} 内置类

△ 看图谈话

f1.getX();

=> 调用getX函数,有点:this->f1

=> f1实例对象上有本人的:公有办法getX

=> console.log(this.x);

=> f1.x ->100

f1.__proto__.getX();

=> 调用getX函数,后面有点:this->f1.\__proto__->Fn.prototype

=> 公共的getX办法

=> console.log(this.x);

=> Fn.prototype.x ->undefined

f2.getY();

=> 调用getY函数,有点:this->f2

=> 在f2实例上没有找到getY办法,那么就沿着原型链f2.__proto__找到所属类的原型Fn.prototype身上,找到了getY办法

=> 公共的getY办法

=> console.log(this.y);

=> f2.y ->200

Fn.prototype.getY();

=> 原型上的getY办法

=> this->Fn.prototype

=> console.log(this.y);

=> Fn.prototype.y => undefined

- end -

2句话,1道题,1张图:捋分明【原型和原型链】~

第一句话

=> 每一个函数数据类型,天生自带一个prototype原型属性,其属性值是一个对象 留神:有特例

=> 这个prototype原型对象上,天生自带一个属性constructor,其属性值是类/构造函数自身

第二句话

=> 一个对象数据类型,天生自带一个 \proto 原型链属性(or 隐式原型),其指向所属类的原型

先把这个练熟了,前面再加的内容才更容易接受~