简述原型链是什么,有什么用处?若想访问一个对象的原型,应该使用什么方法?

1.背景介绍

原型链是一种机制,指的是JavaScript每个对象包括原型对象都有一个内置的[[proto]]属性指向创建它的函数对象的原型对象,即prototype属性。

2.知识剖析

我们知道 JS 有对象,比如

var obj = { name: 'obj' }

我们可以对 obj 进行一些操作,包括

「读」属性

「新增」属性

「更新」属性

「删除」属性

下面我们主要来看一下「读」和「新增」属性。

为什么有 VALUEOF / TOSTRING 属性呢?

在我们没有对 obj 进行任何其他操作之前,发现 obj 已经有几个属性(方法)了

那么问题来了:valueOf / toString / constructor 是怎么来?我们并没有给 obj.valueOf 赋值呀。

要搞清楚 VALUEOF / TOSTRING / CONSTRUCTOR 是怎么来的,就要用到 CONSOLE.DIR 了。

我们发现 console.dir(obj) 打出来的结果是:

1. obj 本身有一个属性 name(这是我们给它加的)

2. obj 还有一个属性叫做 __proto__(它是一个对象)

3. obj.__proto__ 有很多属性,包括 valueOf、toString、constructor 等

4. obj.__proto__ 其实也有一个叫做 __proto__ 的属性(console.log 没有显示),值为 null

现在回到我们的问题:obj 为什么会拥有 valueOf / toString / constructor 这几个属性?

答案:

这跟 __proto__ 有关。

当我们「读取」 obj.toString 时,JS 引擎会做下面的事情:

1. 看看 obj 对象本身有没有 toString 属性。没有就走到下一步。

2. 看看 obj.__proto__ 对象有没有 toString 属性,发现 obj.__proto__ 有 toString 属性,于是找到了

所以 obj.toString 实际上就是第 2 步中找到的 obj.__proto__.toString。

可以想象,

3. 如果 obj.__proto__ 没有,那么浏览器会继续查看 obj.__proto__.__proto__

4. 如果 obj.__proto__.__proto__ 也没有,那么浏览器会继续查看 obj.__proto__.__proto__.proto__

5. 直到找到 toString 或者 __proto__ 为 null。

3.常见问题

访问对象原型的方法有哪些?

4.解决方法

获取实例对象obj的原型对象,有三种方法

1. obj.__proto__

2. obj.constructor.prototype

3. Object.getPrototypeOf(obj)

上面三种方法之中,前两种都不是很可靠。最新的ES6标准规定,__proto__属性只有浏览器才需要部署,其他环境可以不部署。而obj.constructor.prototype在手动改变原型对象时,可能会失效。

5.编码实战

6.扩展思考

原型链是如何产生的呢?

引自知乎【写代码的苏打饼】专栏的JavaScript 世界万物诞生记

7.参考文献

参考一:阮一峰:Javascript继承机制的设计思想

参考二:zhangjiahao8961:JavaScript原型及原型链详解

参考三:JavaScript 世界万物诞生记

8.更多讨论

Q1:什么是原型?
A1:我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象.这个对象称为原型对象,简称原型

Q2:用什么方法可以访问原型链自身的属性名?
A2:可以使用object.getownpropertynames()的方法访问原型链自身属性名

Q3:构造函数实例的方法和原型模式相比,缺点在哪里?
A3:构造函数的在每次实例化之后都会在实例上重新创建方法,即,构造函数的不同实例之间的同一个方法是不相等的,而原型模式只是复制了方法的指针。

技能树-IT修真院

IT修真院是一个免费的线上IT技术学习平台 。

每个职业以15个左右的task为初学者提供更快速高效的学习方式 ;

所有task均是从真实项目中提炼出来的技能点,

强调实战演练+自学优先+师兄辅导的学习方式,

严格的日报体系,欢乐的交流讨论学习气氛,更有无数师兄师姐帮你解疑!

猜你喜欢

转载自blog.csdn.net/weixin_42192534/article/details/81255883