关于前端:2句话1道题1张图带你捋清楚原型和原型链

5次阅读

共计 2900 个字符,预计需要花费 8 分钟才能阅读完成。

@[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);//=> false
console.log(f1.getY === f2.getY); //=> true
console.log(f1.__proto__.getY === Fn.prototype.getY); //=> true
console.log(f1.__proto__.getX === f2.getX); //=> false
console.log(f1.getX === Fn.prototype.getX); //=> false
console.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 隐式原型),其指向所属类的原型

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

正文完
 0