从Object和Function说说JS的原型链
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回来了。
原型链基本结构如下图:
从图上看来:
- array等非POJO对象在原型链上和他们的构造器属于同一级别
- POJO在原型链上比他的构造器还靠后一个级别
参考文档:ES5
注:
- 内部属性是不开放给JS访问的属性,但现代浏览器已经可以通过__proto__属性访问和设置[[Prototype]]
- own property,即直接设置在此对象上的属性
- 执行以下代码感受下:
var a = {};
a.__proto__ = a; - Object.prototype和基础对象的关系好比快捷方式和应用程序,本身没有任何关系,现在可以指向基础对象,以后也可以指向其他对象。当然原则上是不允许的,基础对象没有引用内存会被回收,所以ECMAScript规定Object下的prototype属性的writable和configuration特性都是false(特性的问题以后另起一篇)
- 假设func为一个函数,func()即作为函数调用(调用内部函数属性[[Call]]),new func()即作为构造器调用(调用内部函数属性[[Construct]])
从Object和Function说说JS的原型链的更多相关文章
- 前端基本知识(二):JS的原型链的理解
之前一直对于前端的基本知识不是了解很详细,基本功不扎实,但是前端开发中的基本知识才是以后职业发展的根基,虽然自己总是以一种实践是检验真理的唯一标准,写代码实践项目才是唯一,但是经常遇到知道怎么去解决这 ...
- js javascript 原型链详解
看了许多大神的博文,才少许明白了js 中原型链的概念,下面给大家浅谈一下,顺便也是为了巩固自己 首先看原型链之前先来了解一下new关键字的作用,在许多高级语言中,new是必不可少的关键字,其作用是为了 ...
- 怎么理解js的原型链继承?
前言 了解java等面向对象语言的童鞋应该知道.面向对象的三大特性就是:封装,继承,多态. 今天,我们就来聊一聊继承.但是,注意,我们现在说的是js的继承. 在js的es6语法出来之前,我们想实现js ...
- 自己对js对原型链的理解
js对象分为2种 函数对象和普通对象 函数对象 比如 function Show(){}var x=function Show2(){}var b=new Function("show3&q ...
- JS中原型链继承
当我们通过构造函数A来实现一项功能的时候,而构造函数B中需要用到构造函数A中的属性或者方法,如果我们对B中的属性或者方法进行重写就会出现冗杂的代码,同时写出来也很是麻烦.而在js中每个函数都有个原型, ...
- js的原型链和constructor
转载:http://www.108js.com/article/article1/10201.html?id=1092 请先瞻仰上边的这篇文章. 对象的原型链: box.__proto__.__pro ...
- js的原型链
js中的原型链是一个很重要的概念,理解了原型链,对js程序的开发有很大的好处,废话不说,先上图: javascript是基于原型的语言,所以一个对象可以另一个对象继承.不过javascript实现的时 ...
- 关于js中原型链的理解
我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,一个对象.无论什么时候,我们只要创建一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性对象 ...
- js面向对象-原型链
var Person = function (name) { this.name = name; } Person.prototype.say = function () { console.log( ...
随机推荐
- swift UITextView内容距离边框边距设置
des_textView.textContainerInset = UIEdgeInsets(top: 5, left: 10, bottom: 5, right: 10) 设置对应的四个边距的值
- MySQL中的基本知识
本文是MySQL中的一些基本知识,包括各种基本操作.数据类型和表的约束等. ps:都是自己总结.手打出来的,虽然不是什么新东西,但也勉强算原创吧.. 一.数据库 1.创建:CREATE DATABAS ...
- c# 函数简述
函数是具有独立功能,并且能够重复使用的代码块.函数必须先声明后调用,使用函数使代码更简洁易读. 一.函数的声明与调用 1.声明格式: static 返回类型 函数名(参数类型 参数名称,参数类型 参数 ...
- KVO实现自定义文件复制进度展示
一.创建文件 说明:自定义文件类,通过NSFileManager 以及NSFileHandle 实现文件的创建和copy,为了控制内存的并发使用,通过控制每次赋值的固定长度来分多次复制: NSStri ...
- js面试题知识点全解(一作用域和闭包)
问题: 1.说一下对变量提升的理解 2.说明this几种不同的使用场景 3.如何理解作用域 4.实际开发中闭包的应用 知识点: js没有块级作用域只有函数和全局作用域,如下代码: if(true){ ...
- How to resolve the truncate/drop/delete/join hang issue in ADW
In some case, we found that when we execute the sql commands like truncate table, drop table, delete ...
- oracle多表连接查询竟然还有这种操作
仔细观察上面几个图,比较下 oracle数据库中的+操作符竟然可以替换left join 和right join sql server暂时没用到过
- 细说 Azure Storage 的冗余策略
当我们想要把应用搬到云端的时候,首先要关注的便是数据的安全性.当然所有的云服务厂商都会对用户数据承诺一个非常高的安全性,但万一出现意外呢?我们是不是还要有适当的应对方案?比如今年的3月8日晚间,Azu ...
- 【Linux】修改Linux字符集
一.查看字符集 常见的几种方法: (1) [root@devhxyw03 ~]# echo $LANG zh_CN.GBK (2) [root@devhxyw03 ~]# env | grep LAN ...
- Django 学习笔记(五)模板标签
关于Django模板标签官方网址https://docs.djangoproject.com/en/1.11/ref/templates/builtins/ 1.IF标签 Hello World/vi ...