首页 > 技术文章 > 对原型及原型链的理解?什么是原型,什么是原型链?

liandudu 2021-01-26 11:49 原文

看过很多相关文中,有通俗易懂的,也有晦涩难懂的,但是只要不是自己整理的始终都不会消耗成自己的知识储备。建议都用自己的理解去整理,那样思路是自己的,日后就算忘记了,看一眼也马上可以记起来。

1、什么是原型对象prototype?

原型是一个对象,并且只有函数有prototype

prototype对象中有一个constructor属性,指向了这个函数本身。

function test () {}
var fn = new test() // test.prototype就是fn的原型对象,可以理解通过new 将 fn 和 test.prototype建立连接(原型继承)
console.log(test.prototype.constructor === test) // true

2、什么是__proto__(隐式原型)?

_proto_实际上是某个实例对象的隐藏属性, 任何对象都有__proto__,指向它所对应的构造函数的原型对象

 


 

我到这个地方就有点乱了,什么关系指来指去,为什么定义的字符串/number/true、false变量都有__proto__。一脸懵逼啊!!!到这里就要岔开话题了,先了解下另外一个知识点,

js的三大包装对象Number()、String()、Boolean()

 

我们知道常用的 基本类型(原始类型):有 number、string、boolean、undefined、null

其中, number、string、boolean这三个类型比较特殊。在调用其某个方法时,JavaScript 引擎会自动将原始类型的值转为包装对象实例,也就是原始类型的“包装对象”。可以调用各种包装对象的属性和方法,在使用后立刻销毁实例。自动转换生成的包装对象是只读的,无法修改。

let str = 'hello word'
console.log(str.length) 
// 访问length属性,但str本身不是对象,不能调用length属性。
// javascript引擎自动将其转为String包装对象,在这个对象上调用length属性。调用结束后,这个临时对象就会被销毁。
// number、boolean类型等同

 

复杂类型: array、function、object

复杂类型是由js内置对应的构造器实例而来,Array、Function、Object

 


 

回归主题,__proto__指向它所对应的构造函数的原型对象

所以这里,第一步就很清晰了

let str = 'hello word'
console.log(str.__proto__ === String.prototype) // true
let num = 1 console.log(num.__proto__ === Number.prototype) // true
let flag = true console.log(flag.__proto__ === Boolean.prototype) // true
function test () {} console.log(test.__proto__ === Function.prototype) // true
let arr = [] console.log(arr.__proto__ === Array.prototype) // true
let obj = {} console.log(obj.__proto__ === Object.prototype) // true

 

所有的构造器都是Function函数(构造器)的实例,所以以上所有构造器(String、Number、Boolean、Function、Array、Object)的__proto__,均指向Function.prototype

这里是不是感觉更加清晰了一点呢~ 出个题目

// 看看以下__proto__指向什么呢?

console.log(Number.prototype.__proto__)

let str = 'hello world'
console.log(str.__proto__.__proto__)

 

解题

console.log(Number.prototype.__proto__)
// Number.prototype 是个原型对象,故名思意,对象对象,对象是由Object函数构造而来。所以 Number.prototype.__proto__ === Object.prototype

let str = 'hello world'
console.log(str.__proto__.__proto__)
// 第一步:str.__proto__ 指向其构造函数的原型对象,固str.__proto__ ===  String.prototype
// 第二部:String.prototype.__proto__,是不是就是上一题,原型对象,对象由Object函数构造而来,所以 str.__proto__.__proto__ === Object.prototype

 

 特比注意的是,所有 构造函数.prototype.__proto__  都会指向Object.prototype 。唯独Object.prototype.__proto__ === null记不住的话就记住一句话,对象生万物,万物皆对象。

 

3、什么是原型链?

以上对原型对象和__proto__有了一定的了解,那什么是原型链?

当访问一个对象的某个属性时,会先在这个对象本身的属性上找,如果没有找到,会去这个属性的__proto__属性上找,即这个构造函数的prototype,如果还没找到,就会继续在__proto__上查找,直到最后一层,找不到即为undefined。这样一层一层往上找,彷佛是一条链子串起来,所以叫做原型链。

 

可以去找一些相关题目做个练习加深对原型和原型链的理解~

推荐阅读