浅析js中的原型和原型链及其使用场景

您所在的位置:网站首页 哪些小说是有原型的 浅析js中的原型和原型链及其使用场景

浅析js中的原型和原型链及其使用场景

2024-07-14 18:25:51| 来源: 网络整理| 查看: 265

一、前言

最近浏览网站学习的时候,看到了这个话题,感觉面试里也经常会被问到;所以查阅了不少文章,想总结一下,方便以后翻看。理解的会比较浅显,希望能多多交流,以后理解更深层的也会持续在这里更新。

CDN文档 javaScript中的继承与原型链

二、原型的使用场景

场景1:在vue项目中,我们通常会将对象公共属性放在vue原型上;或者使用插件,将其挂载到vue原型上;这都是利用原型来实现的。

下面案例是将公共属性添加到vue原型上,使用插件的话同理。

// main.js import Vue from "vue"; //发现少了一个 imgBaseUrl 属性,可以使用原型对象进行扩展 Vue.prototype.imgBaseUrl = config.imgBaseUrl; // 其他页面使用 export default { data() { const _this = this; return { imgBaseUrl: _this.imgBaseUrl, }; } };

场景2:js中判断数据类型Object.prototype.toString.call()方法, instanceof方法。 instanceof 是用来 判断数据是否是某个对象的实例,返回一个布尔值。

详细内容可以查看我之前的文章:js中判断数据类型的几种实用方法

三、原型和原型对象

在JS中,我们所说的原型通常是针对于函数而言的,当然构造函数也是一个函数。

函数也是一个对象,是对象那么它就有属性,在JS中,我们所创建的每一个函数自带一个属性prototype,我们就把prototype称为原型,也有人把它称之为“显示原型”,反正就一个意思。

这个prototype它指向了一个对象,可以把prototype想象成一个指针,或者更简单的理解为prototype的属性值(键值对)。prototype指向的这个对象我们就称之为原型对象,通常大家就直接将prototype理解为原型对象。

请注意,以下的代码是独立的(出于严谨,假定页面没有其他的 JavaScript 代码)。为了最佳的学习体验,强烈建议打开浏览器的控制台(在 Chrome 和火狐浏览器中,按 Ctrl+Shift+I 即可),进入“console”选项卡,然后把如下的 JavaScript 代码复制粘贴到窗口中,最后通过按下回车键运行代码。

function Person() { } console.log(Person.prototype)

打印结果: 在这里插入图片描述

可以看到prototype它确实指向了一个对象,原型对象prototype里面有一个constructor属性,它指向了Person构造函数。

总结

1)每个函数都有一个prototype属性,被称作原型。 2)prototype原型指向一个对象,所以也被称原型对象。

四、prototype和__proto__不能混淆

很多人把 prototype和__proto__混为一潭,其实这是两个维度的东西。 prototype的维度是函数,而__proto__的维度是对象。 __proto__是每个对象都有的属性,我们通常把它称为"隐式原型",把prototype称为"显式原型"。

另外,函数也是一个对象,所以它既有prototype属性又有__proto__属性。

控制台验证一下:我们可以看到函数有prototype和__proto__两个属性,而对象只有__proto__属性。

Function: 在这里插入图片描述 object对象: 在这里插入图片描述

接下来我们再来看看__proto__属性,控制台打印看看。

在这里插入图片描述

发现了一个新的属性:[[Prototype]],官方对于这个属性其实有解释,这里通俗的解释一下:

[[prototype]]其实就是隐式原型__proto__,因为各大浏览器厂家不同,所以取了别名罢了,大家只需记住这个和__proto__一样即可。

总结

1)prototype和__proto__不太一样,一个是函数拥有的显式原型,一个是对象拥有的隐式原型。 2) __proto__通常被称作隐式原型,每个对象都拥有该属性。 3)[[prototype]] 其实就是__proto__。

五、原型链

接着我们可以给 Person 函数的原型对象添加新属性,如下:

function Person(){} Person.prototype.name= "铁锤妹妹"; // 往函数的原型上添加变量和方法 Person.prototype.age = '18' Person.prototype.getAge= function() console.log('我18岁了') } var obj = new Person() console.log( obj.name ) //"铁锤妹妹" console.log( obj.age ) //"18"

上面的代码,我们声明了一个构造函数Person,其实就是一个函数。我们知道函数的prototype是一个对象,我们就可以往这个对象上添加东西,所以我们就直接往函数的原型上添加了变量和方法。

接着我们使用new关键词创建一个Person构造函数的 实例对象 ,分别打印name和age,会发现obj这个实例是可以调用构造函数Person原型属性和方法的。这个就叫做 继承。

其实这就和我们的原型链有关了,我们把obj打印出来看看: console.log(obj)

在这里插入图片描述

我们会发现obj对象上并没有name和age属性,但是在他的隐式原型[[Prototype]]上有name和age,而且我们会发现obj的[[prototype]]中的constructor指向的是它的构造函数Person。

然后我们再修改一下我们的代码,我们在obj对象上添加一个name属性,看看会输出什么。

function Person(){} Person.prototype.name= "铁锤妹妹"; // 往函数的原型上添加变量和方法 Person.prototype.age = '18' Person.prototype.getAge= function() console.log('我18岁了') } var obj = new Person() obj.name = '铁柱哥' console.log( obj.name ) //"铁柱哥" console.log( obj.age ) //"18"

在这里插入图片描述

如上打印所示, obj.__proto__ = Person.prototype。但这是做什么的呢?当访问obj中的一个属性,浏览器首先会查看obj中是否存在这个属性。

如果 obj 不包含属性信息,那么浏览器会在 obj 的 __proto__ 中进行查找 (同 Person.prototype). 如属性在 obj 的 __proto__ 中查找到,则使用 obj 中 __proto__ 的属性。

否则,如果 obj 中 __proto__ 不具有该属性,则检查 obj 的 __proto__ 的 __proto__ 是否具有该属性。默认情况下,任何函数的原型属性 __proto__ 都是 window.Object.prototype. 因此,通过 obj 的 __proto__ 的 __proto__ ( 同 Peron.prototype 的 __proto__ (同 Object.prototype)) 来查找要搜索的属性。

如果属性不存在 obj 的 __proto__ 的 __proto__ 中,那么就会在obj的 __proto__ 的 __proto__ 的 __proto__ 中查找。然而,这里存在个问题:obj 的 __proto__ 的 __proto__ 的 __proto__ 其实不存在。因此,只有这样,在 __proto__ 的整个原型链被查看之后,这里没有更多的 __proto__ ,浏览器断言该属性不存在,并给出属性值为 undefined 的结论。

上面的查找过程是不是很像链式查找!而这就是我们所说的 原型链,而且我们发现查找的过程主要是通过 __proto__ 原型来进行的,所以 __proto__ 就是我们原型链中的 连接点。

原型链流程图: 原型链流程图

总结:

1)当访问某个对象的属性时,会先在这个对象本身属性上查找,如果没有找到,就去它的原型(_proto_)去找,即它的构造函数的prototype查找,如果没有找到,就到原型的原型去找(构造函数的prototype._proto_)。如果直到最顶层的 Object.prototype 还是找不到,是null,则返回undefined。这样一层一层的查找就会形成一个链式结构,这就是原型链。 2)如果对象自身和它的原型,都定义了一个同名属性,那么优先读取对象自身的属性,这叫做“覆盖”。 3)所有引用类型的 _proto_都指向它的构造函数的prototype。

想要理解原型链,我们还得理解__proto__指向哪儿,也就是说它指向那个构造函数,比如上面的obj对象的__proto__指向的就是Person构造函数,所以我们继续往Person上查找。

六、 性能

在原型链上查找属性比较耗时,对性能有副作用,这在性能要求苛刻的情况下很重要。另外,试图访问不存在的属性时会遍历整个原型链。 遍历对象的属性时,原型链上的每个可枚举属性都会被枚举出来。要检查对象是否具有自己定义的属性,而不是其原型链上的某个属性,则必须使用所有对象从 Object.prototype 继承的 hasOwnProperty 方法。

function Person(name) { this.name = name; } let p1 = new Person("John"); console.log(p1.hasOwnProperty("name")); // true console.log(p1.hasOwnProperty("toString")); // false // 而toString属性是从Object.prototype原型链上继承来的属性。 七、拓展 对象的 hasOwnPrototype() 来检查对象自身中是否含有该属性。使用 in 检查对象中是否含有某个属性时,如果对象中没有但是原型链中有,会继续检查原型链,也会返回true。 八、 手写代码实现 instanceof (考察对原型链的理解) 步骤1:先取得当前类的原型,当前实例对象的原型链步骤2:一直循环(执行原型链的查找机制) 获取当前实例对象原型链的原型链(proto = proto. _proto_,沿着原型链一直往上找) 如果 当前实例的原型链 _proto_ 上找到了当前类的原型 prototype,则返回true。 如果 一直找到 object.prototype._proto_ == null,object的基类 null 上面都没找,就返回false // 实例._proto_ === 构造函数.prototype function _instanceof (instance, constructor) { // 由于 instanceof 要检测的是某对象,需要有一个前置判断条件 // 基本数据类型直接返回 false if (typeof instance !== 'object' || instance == null) return false let proto = Object.getPrototypeOf(instance) // 等价于 instance._proto_; 如果该对象没有原型,则返回 null。 // 当proto == null时,说明已经找到了Object的基类null 退出循环 while (proto !== null) { // 实例的原型等于当前构造函数的原型 if (proto === constructor.prototype) return true // 沿着原型链_proto_一层层向上找 proto = Object.getPrototypeOf(proto) // 等价于 proto._proto_ } return false } console.log('test', _instanceof(null, Array)) // false console.log('test', _instanceof({}, Array)) // false console.log('test', _instanceof([1,2,3,4], Array)) // true console.log('test', _instanceof('', Array)) // false

可参考: 一文搞懂原型和原型链! 浅谈原型和原型链以及其应用案例 【web前端面试必问2】js原型和原型链的理解(透彻)



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭