Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >强大的原型和原型链

强大的原型和原型链

作者头像
okaychen
发布于 2018-01-05 04:15:58
发布于 2018-01-05 04:15:58
7790
举报
文章被收录于专栏:前端那些事前端那些事

前两次总结了JavaScript中的基本数据类型(值类型<引用类型>,引用类型<复杂值>)以及他们在内存中的存储,对内存空间有了一个简单的了解,以及第二次总结了this深入浅出的用法,我们知道了this的用法取决于函数四种调用的方式。

这一次我们来对JavaScript中原型以及原型链做一个深入浅出的理解。

JavaScript深入浅出系列

1)复杂值vs原始值&&内存空间 - JavaScript深入浅出(一)

2)this的用法 – JavaScript深入浅出(二)

3)原型那些事 - JavaScript深入浅出(三)

待续......关于原型的话题都会变得严肃。

实际上,原型只是一个被称为"原型"的空对象属性,它是由JavaScript在后台创建(当然我们知道了它的原理,可以手动完成这项工作);

当你创建一个函数时,这个函数都会有一个prototype属性(不管你是不把它当做一个构造函数使用)。

βヾ(,,・∇・,,川←那么我们具体来看一下吧!!!

原型链概要

prototype属性是JavaScript为每个Function实例创建的一个对象。

具体的说:"它将通过new关键字创建的<对象实例>链接回创建它们的<构造函数>" 。就这样,我们可以共享或继承通用的方法和属性。当我们在属性查找时,就会不自觉的开启了我们的原型链之旅

让我们通过一个简单的例子开启我们的原型链查询之旅:我们使用Array构造函数创建一个数组,然后调用join方法

我想上面的例子对于js入门者是非常简单的,那么但是我们再来仔细了解一下,你发现join方法并没有定义为myArray对象实例的属性,但是我们创建的数组却可以访问join()方法,就好像我们本来就可以访问似的。

join()是在哪个地方定义的呢?

事实上,我们经常使用的join(),slice(),push()...等这些内建的方法,都被定义为了Array()构造函数的prototype属性的属性。由于在我们创建的myArray数组中没有找到join(),因此JavaScript会在原型链中查找join()方法

其实这样做我们很容易就联想到了效率和重用,通过把该属性添加到原型中去,我们所有的数组都有充分利用了相同的join()函数,而不需要为每一个数组实例都创建函数的新实例。

原型在所有的function()实例上都是标准的

我们知道创建函数两种方法

1、调用Function构造函数法:

2、使用字面量法:

其实,即使不直接使用Function构造函数,而是使用字面量表示法,所有的函数也都是由Function()构造函数创建的

我们用字面量方法创建了一个函数,发现它的prototype和Function()构造函数一样,都指向了object(),这也就证实了我们上所说的.

 默认的prototype属性是object()对象

上面我已经谈到,实际上,原型只是一个被称为'原型'的空对象属性,它在JavaScript的后台已经创建,并且通过Function()构造函数来使用。

我们可以手动完成这项在后面完成的工作,以便了解它的机制。

上面的代码非常简单,实际上也非常好用,它实质上复制了JavaScript在后面已经完成的工作。

将构造函数创建的实例链接至构造函数的prototype属性

将构造函数所创建的实例链接至构造函数的prototype属性,让我们开始这条神秘的_proto_链接

上面我们所原型只是一个对象,但是它是特殊的,因为原型链将每个实例都链接至其构造函数的prototype属性。

创建的对象实例创建对象的构造函数的prototype属性

当然,我们除了使用_proto_链接,还可以使用构造函数属性:

事实上,_proto_  ===  constructor.prototype

 这样我们就不难理解,下面可以达到同样的效果:

上面的例子中我写到直接使用链也是可以的,下面会介绍它的查询顺序。虽然我相信对于入门者都是使用的链查询,但是我们有必然要知道它背后的那些机制。

其实有只看不见的手,在帮助着我们的代码完成任务

原型链的最后是Object.prototype

那么就让我们来看一下它的原型链查询吧。

由于prototype属性是一个对象,因此原型链或查询的最后一站是Object.prototype。

我想上面的代码,对于我们来说是丝毫不费力气的,但就借这个简单的例子,最后一个简单的undefined结果,却经历了一段不为我们所见的原型链查询;

我们创建了一个myArray空数组,然后我们试图访问未定义的myArray属性时,并不会直接返回undefined,而是要经历一段原型链查询。

①在myArray对象中查找foo属性;

如果没有找到

②则在Array.prototype中查找该属性;

但它在哪里也没有定义,

③最后查找的地方就是Object.prototype

三个对象中都没有定义,最后才给我们了一个undefined的回馈。所以请好好对待你的undefined吧,因为它的出现一波三折,还真不容易啊。。哈哈

用新对象替换prototype属性会删除默认的构造函数属性

我们可以用一个新值来替换prototype属性的默认值,但是需要特别注意的是:这么做会删除在"预制"原型对象中找到的默认的constructor属性,除非我们手动指定一个 ;

所以当你想要替换JavaScript设置的默认的prototype属性(与一些js oop模式类似),应该重新连接引用该构造函数的构造函数属性

下面我们简单的改一下上面的代码,以便构造函数属性能够再次为适当的构造函数提供引用

继承原型属性的实例总是能够获得最新值

其实prototype是动态的继承原型的属性的实例总是能够获得最新值,

这一点比较简单,不管是使用原型对象还是自己的对象覆盖它,继承原型属性的实例总是能够获得新值。

但是我们需要注意下面的一点:

  丨

  丨

  丨

用新对象替换prototype属性不会更新以前的实例

 当你想用一个新对象完全替换prototype属性时,觉得所有的实例都会被更新,那么就即将要走向一条寻错的道路,可能会得到意想不到的结果。

创建一个实例时,该实例将在实例化时绑定至"刚完成"的原型,提供一个新对象作为prototype属性不会更新已创建的实例和原型之间的连接

这里的重点是,一旦开始创建实例,就不应用一个新对象那个来替换对象的原型,这样将会导致实例有一个指向不同原型的链接

 自定义构造函数实现原型继承

 当我们在自定义构造函数时,同样可以实现原型继承:

上面我们写的例子,很好的利用原型链,来创建一个构造函数。如果我们不提供参数的话,构造函数则可以继承legs和arms属性。如果传入参数,就遮盖继承的属性

 创建继承链

我们自定义的构造函数实现了原型继承,设计原型继承的目的是要在传统的面向对象编程语言中找到模仿继承模式的继承链。继承只是一个对象可以访问另一个对象的属性。

接下来我们来创建一个简单的继承链:

事实上,上述代码我做的仅仅是利用一个已有的原生对象。

Person()和prototype属性的默认的object()值没有什么不同,这也正是一个prototype属性包含默认空object()值所发生的事情,查找用于创建对象的构造函数的原型(即object.prototype),以便查找所继承的属性。

::我们为什么要关注prototype属性呢?

(希望下面可以给<JavaScript入门者>一个了解prototype的理由)

你可能不喜欢原型继承,而是更多的喜欢采用另一种模式的对象继承。但是:

①原生构造函数(如Ocject(),Array(),Function()...)都使用了prototype属性,以便让你的实例可以继承属性和方法。

②如果想要更好的理解JavaScript,我们需要了解JavaScript本身是如何使用prototype对象的

③当你自定义一个构造函数时,可以像JavaScript原生对象那样使用继承,就必须要知道他是如何工作的

④通过使用原型继承,我们可以创建有效的对象实例。因为并非所有的数组对象都需要他们自己的join()方法<我想这就需要我们做些工作了>,但所有的实例都可以利用相同的join()方法,这就提高了效率和重用性。

 写在后面

到这里我们的函数原型属性的深入浅出系列已经介绍完毕了,这篇博文希望可以帮助初学者--记住原型链层次结构的工作原理、对于易混淆的原型继承属性有一个分类,解决初学者心中的原型困惑

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-09-21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
JavaScript核心概念-原型、原型链
每个函数都有一个prototype属性,那这个属性到底是指向哪里呢?是这个函数的原型吗?
程序员不务正业
2021/05/06
6470
前端入门15-JavaScript进阶之原型链声明正文-原型链
作为一个前端小白,入门跟着这几个来源学习,感谢作者的分享,在其基础上,通过自己的理解,梳理出的知识点,或许有遗漏,或许有些理解是错误的,如有发现,欢迎指点下。
请叫我大苏
2018/12/24
4080
前端入门15-JavaScript进阶之原型链声明正文-原型链
彻底搞懂JS原型与原型链
说到JavaScript的原型和原型链,相关文章已有不少,但是大都晦涩难懂。本文将换一个角度出发,先理解原型和原型链是什么,有什么作用,再去分析那些令人头疼的关系。
hellocoder2029
2022/10/17
3.6K1
原型与原型链
网上有太多关于原型的资料,不是一上来就各种概念,让人看到摸不着头脑,就是贴各种代码,少个通俗的解释,所以才有了这一篇文章。
前端程序之路
2021/03/28
6290
原型与原型链
Javascript之其实我觉得原型链没有难的那么夸张!
  原型链、闭包、事件循环等,可以说是js中比较复杂的知识了,复杂的不是因为它的概念,而是因为它们本身都涉及到很多的知识体系。所以很难串联起来,有一个完整的思路、脉络。我最近想把js中有意思的知识点都总结整理一下,虽然逃不开一些一模一样的内容,但是自己造一下轮子,按照自己的思路,也别有一番味道。
全栈程序员站长
2022/07/21
6810
Javascript之其实我觉得原型链没有难的那么夸张!
总结一下js的原型和原型链
最近学习了js的面向对象编程,原型和原型链这块是个难点,理解的不是很透彻,这里搜集了一些这方面的资料,以备复习所用 一. 原型与构造函数   Js所有的函数都有一个prototype属性,这个属性引用了一个对象,即原型对象,也简称原型。这个函数包括构造函数和普通函数,我们讲的更多是构造函数的原型,但是也不能否定普通函数也有原型。譬如普通函数: function F(){   ; } alert(F.prototype instanceof Object) //true 构造函数,也即构造对象。首先了解下通过
吴裕超
2018/02/28
1.1K0
前端入门13-JavaScript进阶之原型声明正文-原型
作为一个前端小白,入门跟着这几个来源学习,感谢作者的分享,在其基础上,通过自己的理解,梳理出的知识点,或许有遗漏,或许有些理解是错误的,如有发现,欢迎指点下。
请叫我大苏
2018/12/24
6690
再谈javascriptjs原型与原型链及继承相关问题
普通的内置对象与基本包装类型的主要区别就是对象的生命期,使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中,而自动创建的基本包装类型的对象,则只是存在于一行代码的执行瞬间,然后立即被立即销毁。这意味着我们不能再运行时为基本包装类型值添加属性和方法。
IMWeb前端团队
2019/12/04
5530
《现代Javascript高级教程》JavaScript中的原型与继承
JavaScript是一门支持面向对象编程的语言,它的函数是第一公民,同时也拥有类的概念。不同于传统的基于类的继承,JavaScript的类和继承是基于原型链模型的。在ES2015/ES6中引入了class关键字,但其本质仍然是基于原型链的语法糖。
linwu
2023/07/27
2840
《现代Javascript高级教程》JavaScript中的原型与继承
关于javascript的原型和原型链,看我就够了(一)
关于js的原型和原型链,有人觉得这是很头疼的一块知识点,其实不然,它很基础,不信,往下看 要了解原型和原型链,我们得先从对象说起
陌上寒
2019/04/02
3710
关于javascript的原型和原型链,看我就够了(一)
JS基础知识总结(三):原型、原型链
上一篇JS基础知识总结(二)主要了介绍深拷贝、浅拷贝的基础知识,本文将介绍JS原型、原型链的有关内容。
前端林子
2019/01/05
2.4K1
JS基础知识总结(三):原型、原型链
JS面试必问-JS原型及原型链
在js中万物皆对象,对象可以说是重中之重了。每一个对象都拥有自己的属性。但是在这个世界中有很多东西都是相似的,可以归为一类,他们有共同的方法和属性。不可能让每一个对象都定义一个属性吧。那样太消耗内存了。所以,在js中怎么才能让多个对象共享一个或多个方法呢?原型的出现就是为了解决这个问题。
用户10106350
2022/10/26
1.7K0
JS面试必问-JS原型及原型链
构造对象,原型和原型链笔记
面向对象:面向对象、原型 对原型、原型链、 Function、Object 的理解 什么是 JS 原型链? 转载以上文章
bamboo
2019/01/29
4960
构造对象,原型和原型链笔记
来自原形与原型链的拷问
在JS中,我们经常会遇到原型。字面上的意思会让我们认为,是某个对象的原型,可用来继承。但是其实这样的理解是片面的,下面通过本文来了解「原型与原型链」的细节,再顺便谈谈继承的几种方式。
JowayYoung
2020/04/01
5150
来自原形与原型链的拷问
JavaScript进阶-原型链与继承
在JavaScript中,原型链和继承是理解对象间关系和实现代码复用的核心概念。这两个机制共同构成了JavaScript面向对象编程的基础。本文将深入浅出地探讨原型链与继承的工作原理、常见问题、易错点及其避免策略,并通过具体代码示例加以说明。
Jimaks
2024/06/19
2130
JavaScript进阶-原型链与继承
JS基础-关于原型、原型链的一切
JS的原型、原型链一直是比较难理解的内容,不少初学者甚至有一定经验的老鸟都不一定能完全说清楚,更多的"很可能"是一知半解,而这部分内容又是JS的核心内容,想要技术进阶的话肯定不能对这个概念一知半解,碰到问题靠“猜”,却不理解它的规则!
OBKoro1
2019/08/26
1.4K0
[JS必知必会]原型链这么看好像并不难
上面一段代码,声明第一个函数foo的时候,它就会带一个foo.prototype的属性,这个属性是一个对象属性,用new foo();构造器的方式构造一个新的对象obj。这时候这个obj的原型会指向foo的prototype属性。 对于这个foo函数的原型也会指向Object.prototype,这个Object.prototype也是有原型的,它的原型指向null。
coder_koala
2019/07/30
4790
[JS必知必会]原型链这么看好像并不难
深入JavaScript原型链污染
相比其他语言(如Java、python等传统OOP语言),JavaScript的机制和类完全不同。
raye
2024/02/04
2391
JavaScript继承和原型链
JS在加载构造函数时,会在内存中生成一个对象,这个对象称为函数的原型对象(prototype)。
前端航航
2022/11/11
4740
一站搞定原型链:深入理解JavaScript的继承机制
JavaScript 的原型链(prototype chain)是理解 JavaScript 对象和继承机制的关键。它是通过对象的原型(prototype)属性实现的,用于实现对象属性和方法的共享和继承。以下是对 JavaScript 原型链的详细介绍,这一篇文章将会通过理论与demo相结合的方式,力争一文概括原型、对象、原型链以及基于原型链实现JavaScript的继承机制的所有方面,帮助您一站式搞定原型链。
watermelo37
2025/01/22
1020
一站搞定原型链:深入理解JavaScript的继承机制
推荐阅读
相关推荐
JavaScript核心概念-原型、原型链
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档