JS原型链解析
思维导图
前言
- 网上扣的图,哈哈。不太了解原型链的同学乍一看可能有点蒙,不过,没关系,读完此篇文章,我们再回头来看~
- 之前有转过原型链的文章,当时自己也是一知半解。所以自己又重新梳理了一遍!
函数的prototype属性
###先看代码
- 每个函数都有一个prototype属性,它默认指向一个空的Object对象。
- 原型对象中constructor,它指向函数对象。
- 作用:函数的所有实例自动拥有原型中的属性(方法)。
- 注:方法也是属性哦,只不过它可以执行。
显式原型
每一个函数都有一个prototype,即显式原型
隐式原型
每一个实例对象都有一个__proto__,可称为隐式原型
Console.log(Fn.prototype===fn.__proto__) //true
- 对象的隐式原型的值等于其构造函数的显式原型的值
- 上面加粗的这句话很核心哦,理解原型链的基本~
- 理解:共同存储的对象的引用,指向同一块地址值
显式原型的生成
function Fn(){
}
//内部语句是这样的
this.prototype = {}
- 注意:Fn.prototype === {} //false
- 这里 {} 是为了代表Object空对象
隐式原型的生成
var fn = new Fn();
//内部语句是这样的:
this.__proto__ = Fn.prototype
Java程序员的理解
函数对象
- 函数对象即class 类
实例对象
- new class 类产生对象
Object
即Object对象
JavaScript原型链在内存中的展现形式
- 既然讲到了内存,就离不开地址值啦。【要理解原型链,上图要求自己画出~】
- 上图栈中存在三个地址引用,分别是:Object函数对象,fn实例对象,Fn函数对象【实例对象和函数对象要区分哦】
- 我们发现:fn的__propto__和Fn的prototype指向的是同一块地址值,所以二者相等。
- Object函数对象prototype和Object空对象的__proto__指向的是同一块地址值。
- Object原型对象的__proto__指向null【原型链的尽头】
- 总结:所谓的原型链的全称为隐式原型链,即__proto__所指向的地址链。
- JavaScript也是遵循“一生二,二生三,三成万物的思想~“
思维导图上的规律
- 函数的显示原型对象指向的是空的Object实例对象(但是Object不满足),这一点可以看地址分析的那张图,Object函数指向的是Object原型对象。
console.log(Fn.prototype instanceof Object) //true
console.log(Object.prototype instance Object) //false
console.log(Function.prototype instance Object) //true
- 所有函数都是Function的实例,包括Function。
这里就比较有意思了,想要理解这句话首先要明白Function是js的内置对象,所有函数都是通过new Function() 的来的,包括Function自己。所以就有了下面这句话: - 所有函数的__proto__都是一样的,这里也包括Object函数哦,这句话可以在上图找到答案。
console.log(Function.prototype === Function.prototype) //true
- Object的原型对象是原型链的尽头
console.log(Object.prototype.__prototype__) //null
属性问题
- 讲了这么多,原型链到底有啥用?
- 下面来看看原型链的作用【属性的存储】
get【属性查找】
*访问对象的属性时
*先在自身属性中查找,找到后返回如果没有找到,就按照__proto__构成的地址链查找,直到null,如果最终没有找到,返回undefined,(如果是方法,则报错:xxx is not a function)
*别名:隐式原型链
*作用:查找对象的属性(方法)
set【设置属性】
- 设置属性时,不会查找原型链,如果当前对象中没有此属性,则直接添加此属性并设置其值,如果有则改变其值。
验证
function Fn(){
}
Fn.prototype.a = 'xxx';
var fn1 = new Fn();
console.log(fn1.a,fn1) //xxx,fn1对象
var fn2 = new Fn();
fn2.a ='yyy';
console.log(fn1,fn2);
结尾
- 至此,是否对原型链有了新的理解呢?
- 如果有错的地方,还请指正,共勉~