什么是原型链
原型链就是顺着__proto__
所在的一条链子,这样说可能不是很好理解,下面来看例子你就会理解。
需要了解
1.a.__proto__
和 a.prototype
都称做为a的原型。
2.Object.prototype
是原型链的顶端。
3.如果 a
是由b
实例化出来的,则有关系a.__proto__ === b.prototype
,所以a.__proto__
的地址和b.prototype
指向的地址是一样的,即他们使用的是同一个对象。
原型链解读
先以函数实例的原型链
为例子为大家讲解
function A(){}
const a=new A()
console.log(a.__proto__===A.prototype) // true,这里是根据上面 '需要了解'处可以推断
console.log(A.prototype.__proto__===Object.prototype)
// true,这里可以通过打印 A ,然后展开看到 A 就能看到该关系
知道以上关系后,可以得出原型链如下:
再以数组的原型链
为例
const arr=[]
console.log(arr.__proto__===Array.prototype) //true,根据上面 '需要了解'处可以推断
console.log(Array.prototype.__proto__===Object.prototype)
// true,打印 Array,然后展开Array就能看到该关系
知道以上关系后,可以得出原型链如下:
其它的原型链如:函数、对象、正则、日期的原型链和上面的基本一致。
原型链的作用
首先你需要只知道的是,处在原型上的对象,是可以顺着自己所在原型链向上找,然后可以使用上面的方法或者属性。主要作用就是减少内存消耗,提高代码的复用率。看看下面示例你就会明白
function A(){}
A.prototype.f1=()=>{console.log('f1')}
A.prototype.f2=()=>{console.log('f2')}
A.prototype.f3=()=>{console.log('f3')}const a1=new A()
const a2=new A()
const a3=new A()a1.f1() // f1
a2.f1() // f1
a3.f1() // f1
把一些公共的方法添加到原型上,这样我们实例化的每个对象就都可以使用这些这些原型上的方法了。如果我们不把方法添加到原型上,而现在需求是需要每个实例都能使用上面的这些方法,那我们只能将这些方法都添加到实例上例:a1.f1=f1
。如果我们把这些方法添加到原型上,实例使用时,只需要往原型上找就行,而且所有实例使用的同一个原型。对比一看,是不是省了很多内存开销。
合理使用原型
手动在原型上添加某个属性
Object.prototype.a=2
这是第三方库a.js含有如下代码
Object.prototype.a=1
此时引入a.js
const obj={}
console.log(obj.a) // 1
此时不是我们期望的结果,所以不要滥用原型,不要在系统的原型上随意添加修改方法
原型的读写相关方法
const user={name:"nb",age:18}//获取user对象的 __proto__
Object.getPrototypeOf(user)
// 把user对象的原型修改为{},修改对象的__proto__,只能修改为对象
Object.setPrototypeOf(user,{})
原型为什么不能修改为非对象
const obj={}
obj.__proto__=1
console.log(obj.__proto__) //打印后依然是一个对象
/*
<get __proto__()>: function __proto__()
<set __proto__()>: function __proto__()
*/
在打印的对象中可以找到 __proto__
属性被劫持了,这就是原因。
结尾
看完这篇文章后,你会发现原型链用来是这么的简单。感谢你们的观看,希望这篇文章能给你带来帮助。如果有小伙伴有问题或者疑惑,欢迎提出和分享。