1.原型和函数
众所周知,JS并没有类(class)的概念,虽然说ES6开始有了类的概念,但是,这并不是说JS有了像Java这些基于类的面向对象语言一样,有了全新的继承模型。ES6中的类,仅仅只是基于现有的原型继承的一种语法糖。
几点关键
- 函数都拥有
prototype
属性,指向它的原型对象。也可以说:每个构造函数都有一个prototype原型对象
- 原型对象拥有一个
constructor
属性,指向它的构造函数 - 函数可以通过new操作符创建对象,对象的
__proto__
指向该函数的原型对象 - 每个对象都拥有一个
__proto__
属性,并且指向它的prototype原型对象 - 函数也可以看作是一个对象,它的
__proto__
指向Funtion.prototype
看 Object 和 Function
// 结果都是 "function"
typeof Function
typeof Object
typeof Array
那么到现在我们知道,JS本身提供的这些都是函数,函数也是一个对象,那么他就会有:
prototype
属性__proto__
属性
原型对象中会有:
constructor
属性__proto__
属性
我们现在分析一下,Object 、Function 和他们的原型对象中的这两个属性
自己画的图
在浏览器中验证
> Function.__proto__ === Function.prototype
< true
> Function.prototype.constructor === Function
< true
> Function.prototype.__proto__ === Object.prototype
< true
> Object.__proto__ === Function.prototype
< true
> Object.prototype.constructor === Object
< true
> Object.prototype.__proto__ === null
< true
我们可以得出结论:
- 所有函数的
__proto__
都指向 Function.prototype - 原型对象的
__proto__
指向Object.prototype Object.prototype.__proto__
指向 null
当我们定义一个函数,“函数”这个对象的原型__proto__
指向Function.prototype
function func() {
}
func.__proto__ === Function.prototype // true
那么我们进一步看Object、Function和Array
function fun1() {
}
const obj = {
}
const arr = []
- fun1、obj、arr都可以看作是new出来的实例,他们分别指向Function.prototype,Object.prototype,Array.prototype。
- 其中Function.prototype,Array.prototype的__proto__指向Object.prototype。
2.谈谈 __proto__属性
对于函数:“函数”这个对象的原型__proto__指向Function.prototype
对于对象:每个对象都有一个__proto__属性,并且指向它的prototype原型对象
我们现在通过函数new一个对象
function Person() {
}
const p1 = new Person()
当前的结构如图:
prototype 和 __proto__有什么用呢?
实例对象的__proto__指向构造函数的prototype,从而实现继承。
prototype对象相当于特定类型所有实例对象都可以访问的公共容器
3.原型链
当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
例:寻找valueOf()方法
var arr = [1,2,3]
arr.valueOf() // [1, 2, 3]
原型链如下:
arr —> Array.prototype —> Object.prototype —> null
这就是传说中的原型链,层层向上查找,最后还没有就返回undefined
4.instanceof操作符
instanceof 原理
instanceof的判断逻辑是: 从当前引用的__proto__一层一层顺着原型链往上找,能否找到对应的prototype。找到了就返回true。
简易实现
const instanceOf = (A, B) => {
let p = A;
// 遍历链表
while (p) {
if (p === B.prototype) {
return true;
}
p = p.__proto__;
}
return false;
};
instanceOf(Function, Object); // true