共计 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
和 f2
是 new 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 隐式原型),其指向所属类的原型
先把这个练熟了,前面再加的内容才更容易接受~