ECMAScript规定了两个特殊的内置对象:Object和Function。他们的特殊性在于,他们本身既是对象又是函数,而他们同时也是对象和函数的构造器。这种自己生自己的逻辑显然违反人性,如果还停留在类的继承的思想上,那么更加无法理解。

  然而ECMAScript是基于原型链的,所以忘掉类的继承,从原型链入手:原型链是对象的集合,每个对象都有内部属性[[Prototype]](注1)指向另一个对象;当访问对象某一属性的时候,如果此属性不为此对象的自身属性(注2),则继续去[[Prototype]]指向的对象上查找此属性。[[Prototype]]形成的对象的链式集合即原型链。这里可以得出:原型链上的所有元素都是对象。

  ECMASciprt规定:原型链必须是有限长度(注3),而且终点必须是null。现在终点是唯一的,那么原型链上倒数第二个元素是不是唯一的呢?ECMAScript没有规定,但从实现上来看,是唯一的。因为原型链上所有的元素都是对象,所以倒数第二个元素应该是所有对象的基础对象。这个对象在实现中只给出一个引用,就是Object.prototype。这里可以得出:原型链上有两个元素是固定的,终点是null,倒数第二的元素是Object.prototype指向的对象(注4)。

  那么倒数第三个元素是不是固定的呢?不是。从倒数第二个元素是Object.prototype来看,通过{}字面量和new Object()创建的对象都在倒数第三这个位置,即POJO都在倒数第三。另外还有两个特例,一个是除内置函数之外的内置对象,如Math、JSON;一个是除Object之外的内置函数的prototype属性指向的对象,如Function.prototype。这里可以得出:原型链上倒数第三的元素一般是POJO+Math/JSON+(Function/Array/String/Boolean/Number/Date/RegExp/Error).prototype。

  倒数第三的位置出现了这么多的prototype,那么倒数第四的位置就好推测了,所有除Object之外的内置函数作为构造器调用(注5)时生成的实例对象都在倒数第四。其中需要注意的是,所有的内置函数本身是Function作为构造器调用生成的实例对象,所以都在这个位置。这里可以得出:原型链上倒数第四的元素一般是(Function/Array/String/Boolean/Number/Date/RegExp/Error)实例,其中包括(Object/Function/Array/String/Boolean/Number/Date/RegExp/Error),注意这个括号里面Object回来了。

  原型链基本结构如下图:

从图上看来:

  1. array等非POJO对象在原型链上和他们的构造器属于同一级别
  2. POJO在原型链上比他的构造器还靠后一个级别

参考文档:ES5

注:

  1. 内部属性是不开放给JS访问的属性,但现代浏览器已经可以通过__proto__属性访问和设置[[Prototype]]
  2. own property,即直接设置在此对象上的属性
  3. 执行以下代码感受下:
    var a = {};
    a.__proto__ = a;
  4. Object.prototype和基础对象的关系好比快捷方式和应用程序,本身没有任何关系,现在可以指向基础对象,以后也可以指向其他对象。当然原则上是不允许的,基础对象没有引用内存会被回收,所以ECMAScript规定Object下的prototype属性的writable和configuration特性都是false(特性的问题以后另起一篇)
  5. 假设func为一个函数,func()即作为函数调用(调用内部函数属性[[Call]]),new func()即作为构造器调用(调用内部函数属性[[Construct]])

从Object和Function说说JS的原型链的更多相关文章

  1. 前端基本知识(二):JS的原型链的理解

    之前一直对于前端的基本知识不是了解很详细,基本功不扎实,但是前端开发中的基本知识才是以后职业发展的根基,虽然自己总是以一种实践是检验真理的唯一标准,写代码实践项目才是唯一,但是经常遇到知道怎么去解决这 ...

  2. js javascript 原型链详解

    看了许多大神的博文,才少许明白了js 中原型链的概念,下面给大家浅谈一下,顺便也是为了巩固自己 首先看原型链之前先来了解一下new关键字的作用,在许多高级语言中,new是必不可少的关键字,其作用是为了 ...

  3. 怎么理解js的原型链继承?

    前言 了解java等面向对象语言的童鞋应该知道.面向对象的三大特性就是:封装,继承,多态. 今天,我们就来聊一聊继承.但是,注意,我们现在说的是js的继承. 在js的es6语法出来之前,我们想实现js ...

  4. 自己对js对原型链的理解

    js对象分为2种 函数对象和普通对象 函数对象 比如 function Show(){}var x=function Show2(){}var b=new Function("show3&q ...

  5. JS中原型链继承

    当我们通过构造函数A来实现一项功能的时候,而构造函数B中需要用到构造函数A中的属性或者方法,如果我们对B中的属性或者方法进行重写就会出现冗杂的代码,同时写出来也很是麻烦.而在js中每个函数都有个原型, ...

  6. js的原型链和constructor

    转载:http://www.108js.com/article/article1/10201.html?id=1092 请先瞻仰上边的这篇文章. 对象的原型链: box.__proto__.__pro ...

  7. js的原型链

    js中的原型链是一个很重要的概念,理解了原型链,对js程序的开发有很大的好处,废话不说,先上图: javascript是基于原型的语言,所以一个对象可以另一个对象继承.不过javascript实现的时 ...

  8. 关于js中原型链的理解

    我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,一个对象.无论什么时候,我们只要创建一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性对象 ...

  9. js面向对象-原型链

    var Person = function (name) { this.name = name; } Person.prototype.say = function () { console.log( ...

随机推荐

  1. multiset与set

    set的含义是集合,它是一个有序的容器,里面的元素都是排序好的,支持插入,删除,查找等操作,就   像一个集合一样.所有的操作的都是严格在logn时间之内完成,效率非常高. set和multiset的 ...

  2. C语言中全局变量存放在哪个位置?

    今年软考的时候,遇到了这个题目,表示不解,然后考完之后去查了一下百度,才发现自己选错.全局变量存放在静态存储区,位置是固定的. 局部变量在栈空间,栈地址是不固定的.栈:就是那些由编译器在需要的时候分配 ...

  3. 前端开发工具Brackets介绍,安装及安装Emme插件时踩过的坑

    对于前端开发的园友来说有可能IDE工具有很多,层次不穷,还有每个人的喜好及习惯也不一样,因为我是一名后端开发的.Net程序员,但是大家都知道,现在都提倡什么全栈工程师,所以也得会点前端开发,所以我对于 ...

  4. React Native 系列(八) -- 导航

    前言 本系列是基于React Native版本号0.44.3写的.我们都知道,一个App不可能只有一个不变的界面,而是通过多个界面间的跳转来呈现不同的内容.那么这篇文章将介绍RN中的导航. 导航 什么 ...

  5. HTML 基础学习笔记

    HTML 指超文本标记语言(Hyper Text Markup Language),一种标记语言,用来描述网页的一种语言. 一.HTML 基本结构示意图 1. HTML 标签 (HTML tag),由 ...

  6. git入门(4)团队中git保管代码常用操作

    在团队中协作代码时候,一定要熟练使用以下git命令,不至于把代码库弄乱, PS:一定要提交自己代码(git push)时候,先进行更新本地代码库(git pull),不然提交异常 git常用命令 1· ...

  7. 程序员从技术到项目管理PM--思维转变

    对以往所做项目的经验做下总结,作为项目经理首先要对项目负责,思维要做下转变,要从项目全局角度考虑问题:     从个人成就到团队成就. 无论是做管理还是做技术,成就导向意识是优秀员工的基本素质.只有具 ...

  8. 【MySQL】Linux下MySQL 5.5、5.6和5.7的RPM、二进制和源码安装

      [MySQL]Linux下MySQL 5.5.5.6和5.7的RPM.二进制和源码安装 1.1  BLOG文档结构图 1.2  前言部分 1.2.1  导读和注意事项 各位技术爱好者,看完本文后, ...

  9. 8.8.1 Super关键字

    Super关键字 1.super不是引用类型,super中存储的不是内存地址,super指向的不是父类对象. 2.super代表的是当前子类对象中的父类型特征. //通过子类的构造方法去调用父类的构造 ...

  10. 前后端分离(手)-- 使用mock.js(好样的)

    ## 前言: 本篇博文昨天七夕写的,一天下来被虐得体无完肤,苦逼的单身狗只能学习,对!我爱学习,关掉朋友圈,并写了一篇博文发泄发泄.这次写mock.js的使用,能使前后端分离,分离,分离,重要的是说三 ...