在了解javaScript的原型链之前,我们得先来看一下原型是什么。

在javaScript中,所有的函数都会有着一个特别属性:prototype(显示原型属性);当我们运行如下代码时:

function Fn(){

}

在内存中则是如下这样工作的:

我们可以看到,当function对象创建时,其会有一个属性:prototype,该属性在定义函数的时候被自动赋值,值默认为:{},即:指向堆空间中的空的object对象,而该object空对象即是此function的原型对象。

在函数实例化对象时,所有的实例化对象也会有一个特别的属性:__proto__(隐式原型属性),继续刚才的例子,我们运行如下代码:

function Fn(){

}

var fn=new Fn();

此时内存中是如下状况:

此时有没有发现function对象的显示原型属性与其实例化得到的对象的隐式原型属性的值是相同的,即它们指向同一个对象——空object(function的原型对象)。

下面我们来说下显示原型属性与隐式原型属性的关系。

在function实例化对象时,在其实例化对象内部相当于自动运行了如下代码:

var fn=new Fn();  //fn内部:this.__ptoto__=Fn.prototype

我们可以通过如下代码来判断显示原型属性与隐式原型属性是否相等:

function Fn(){

}

var fn=new Fn();  //fn内部:this.__ptoto__=Fn.prototype

console.log(fn.__proto__===Fn.prototype);

运行上述代码会输出:true,这说明显示原型属性与隐式原型属性确实相等。

由此我们可以总结:函数实例化对象的隐式原型属性等于其构造函数的显示原型属性。


了解过原型之后,我们来看一下原型链。

先来看一张图:

那么这个空的object对象是不是一个实例化对象呢,如果是的话,它的构造函数又是谁呢?

在回答上述问题之前我们先来看一个新的属性:constructor;

这个属性与prototype作用类似,不过不同的是:prototype是function对象指向它对应的原型对象,而constructor则是原型对象指向其对应的function对象。

举个例子:

function Fn(){

}

var fn=new Fn();  //fn内部:this.__ptoto__=Fn.prototype

console.log(fn.__proto__.constructor);

若我们运行上述代码,则会得到如下结果:

通过这个例子我们可以知道:Fn的实例化对象fn可以通过fn.__proto__.constructor来得到自身的构造函数。

它的原理也很简单,由前面我们可以知道,fn.__proto__===Fn.prototype是成立的,所以可以通过fn.__ptoto__来得到Fn的原型对象,然后再使用constructor来得到与该原型相对应的function函数,即:Fn。

再回到前面的问题上,我们同样可以通过上述方法来获得object的构造函数。

即执行:

function Fn(){

}

var fn=new Fn();  //fn内部:this.__ptoto__=Fn.prototype

console.log(Fn.prototype.__proto__.constructor);

其输出结果如下:

我们可以看到,object空对象的构造函数是Object。

那么问题又来了,我们知道:函数实例化对象的隐式原型属性等于其构造函数的显示原型属性。

这个object空对象的构造函数既然是Object,那么object应该也通过__ptoto__来指向一个原型对象。

即:

那么Object函数原型对象的隐式原型又指向谁呢?

我们来看一下:

function Fn(){

}

var fn=new Fn();  //fn内部:this.__ptoto__=Fn.prototype

console.log("输出结果为:"+Fn.prototype.__proto__.__proto__);

由此可以知道:Object函数原型对象的隐式原型不再指向其他对象,即:

当我们运行如下代码时:

function Fn(){

}

var fn=new Fn();  //fn内部:this.__ptoto__=Fn.prototype

Object.prototype.name='mmzkyl';

console.log("输出结果为:"+fn.name);

会得到如下输出:

我们可以很明显看到,上述代码并没有在Fn内部定义任何东西,但是fn.name确实又输出了:mmzkyl。

这里来解释一下,当查找对象内部属性的属性/方法时,JavaScript引擎会自动沿着如下图所示来进行查找:

JavaScript会先在自身查找目标属性/方法,若是没有查找到则会沿着其隐式原型属性渠道原型对象中寻找,若是找到了则返回该值,若是还没有找到,则继续沿着隐式原型属性寻找,若是一直找到了Object函数原型对象还是没有找到,则会返回undefined。

这个寻找的过程类似与一条链,而这也称为原型链。

javaScript(原型链)的更多相关文章

  1. JavaScript学习总结(十七)——Javascript原型链的原理

    一.JavaScript原型链 ECMAScript中描述了原型链的概念,并将原型链作为实现继承的主要方法.其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法.在JavaScript中, ...

  2. javascript原型链中 this 的指向

    为了弄清楚Javascript原型链中的this指向问题,我写了个代码来测试: var d = { d: 40 }; var a = { x: 10, calculate: function (z) ...

  3. 明白JavaScript原型链和JavaScrip继承

    原型链是JavaScript的基础性内容之一.其本质是JavaScript内部的设计逻辑. 首先看一组代码: <script type="text/javascript"&g ...

  4. Javascript 原型链资料收集

    Javascript 原型链资料收集 先收集,后理解. 理解JavaScript的原型链和继承 https://blog.oyanglul.us/javascript/understand-proto ...

  5. 资料--JavaScript原型链

    JavaScript原型链 原文出处:https://www.cnblogs.com/chengzp/p/prototype.html 目录 创建对象有几种方法 原型.构造函数.实例.原型链 inst ...

  6. JavaScript原型链:prototype与__proto__

    title: 'JavaScript原型链:prototype与__proto__' toc: false date: 2018-09-04 11:16:54 主要看了这一篇,讲解的很清晰,最主要的一 ...

  7. JavaScript原型链及其污染

    JavaScript原型链及其污染 一.什么是原型链? 1.JavaScript中,我们如果要define一个类,需要以define"构造函数"的方式来define: functi ...

  8. 图解Javascript原型链

    本文尝试阐述Js中原型(prototype).原型链(prototype chain)等概念及其作用机制.上一篇文章(图解Javascript上下文与作用域)介绍了Js中变量作用域的相关概念,实际上关 ...

  9. 画一画javascript原型链

    在javascript中,几种数据类型String,Number,Boolean,Object,Function都是函数,可称之为函数对象. 可以说拥有prototype属性的都是函数. 所有对象都拥 ...

  10. JavaScript原型链和instanceof运算符的暧昧关系

    时间回到两个月前,简单地理了理原型链.prototype以及__proto__之间的乱七八糟的关系,同时也简单了解了下typeof和instanceof两个运算符,但是,anyway,试试以下两题: ...

随机推荐

  1. Docker镜像与仓库(四)

    Dockerfile方式创建镜像 https://hub.docker.com/_/centos/ #找一个centos6.6 的dockerfile链接 [root@linux-node1 ~]# ...

  2. embed git commit hash to assembly

    https://stackoverflow.com/a/41200059/3782855 https://github.com/304NotModified/Fody.Stamp

  3. 我的Android进阶之旅------> Android为TextView组件中显示的文本加入背景色

    通过上一篇文章 我的Android进阶之旅------> Android在TextView中显示图片方法 (地址:http://blog.csdn.net/ouyang_peng/article ...

  4. nodeJS中express框架设置全局跨域请求头

    //设置跨域请求头 router.all('*', function(req, res, next) { res.header("Access-Control-Allow-Origin&qu ...

  5. Nginx模块开发(3)————使用upstream访问第三方服务

    该模块可以完成如下的功能,当我们输入http://你的ip/lcwupstream时,会使用upstream方式访问淘宝搜索,打开淘宝搜索的主页面,代码如下: //start from the ver ...

  6. Markdown更改字体、颜色、大小,设置文字背景色,调整图片大小设置居中,插入表格等方法

    Markdown 通过简单标记语法,使普通文本内容具有一定格式.但它本身不支持修改字体.字号与颜色等功能的. 一.更改字体大小.颜色.更改字体 Markdown语法 <font face=&qu ...

  7. numpy数组的分割与合并

    合并 np.newaxis import numpy as np a=np.array([1,2,3])[:,np.newaxis]#变成列向量 b=np.array([4,5,6])[:,np.ne ...

  8. 【Hadoop离线基础总结】Hadoop的架构模型

    Hadoop的架构模型 1.x的版本架构模型介绍 架构图 HDFS分布式文件存储系统(典型的主从架构) NameNode:集群当中的主节点,主要用于维护集群当中的元数据信息,以及接受用户的请求,处理用 ...

  9. xpath加PHP对网站相关数据的截取

    首先了解一串代码 <?php  $url = 'http://www.baidu.com';$ch = curl_init();curl_setopt($ch, CURLOPT_FILE, fo ...

  10. scala 中 Any、AnyRef、Object、AnyVal 关系

    Any,是 scala 中的抽象类,不能实例化 AnyRef 继承于 Any,它是一个 trait AnyVal 继承于 Any,它是一个抽象类,目的是消除基本类型,scala中只有引用类型,仅此作用 ...