前言在微信公众号前端大全上看过《js中原型和原型链的深入理解》,个人认为这是我看过的js原型链的文章中,在思维结构上理解最清楚的一个文章了,本着温故而知新,有害怕找不到这个文章,我就把文章中的重要的和自己理解与不理解的知识点写下来,以方便以后查看。

首先要明白几个概念:
1. 函数(function)
2. 函数对象(function Object)
3. 本地对象(native object)
4. 内置对象(build-in object)
5. 宿主对象(host object)

函数

function foo(){}
var foo = function(){}

前者为函数声明,后者为函数表达式,typeof foo的结果都是function。

函数对象
《js《js中原型和原型链的深入理解》中原型和原型链的深入理解》的作者的解释是“函数就是对象,代表函数的对象就是函数对象。”
前面这句话,觉的特别难理解,代表函数的对象是什么意思,之后作者给出了官方定义:

官方定义, 在Javascript中,每一个函数实际上都是一个函数对象.JavaScript代码中定义函数,或者调用Function创建函数时,最终都会以类似这样的形式调用Function函数:var newFun = new Function(funArgs, funBody)

其实也就是说,我们定义的函数,语法上,都称为函数对象,看我们如何去使用。如果我们单纯的把它当成一个函数使用,那么它就是函数,如果我们通过他来实例化出对象来使用(new出来的),那么它就可以当成一个函数对象来使用,在面向对象的范畴里面,函数对象类似于类的概念。给出这样的定义就清晰多了,函数对象类似与类的概念。这里的函数Foo是构造函数。

var foo = new function(){}
typeof foo // object//或者function Foo (){}
var foo = new Foo();typeof foo // object

本地对象

ECMA-262 把本地对象(native object)定义为“独立于宿主环境的 ECMAScript 实现提供的对象”。简单来说,本地对象就是 ECMA-262 定义的类(引用类型)。它们包括:
Object,Function,Array,String,Boolean,Number
Date,RegExp,Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError.

引申form W3C

在 ECMAScript 中,所有对象并非同等创建的。
一般来说,可以创建并使用的对象有三种:本地对象、内置对象和宿主对象。

内置对象

ECMA-262 把内置对象(built-in object)定义为“由 ECMAScript 实现提供的、独立于宿主环境的所有对象,在 ECMAScript 程序开始执行时出现”。这意味着开发者不必明确实例化内置对象,它已被实例化了。ECMA-262 只定义了两个内置对象,即 Global 和 Math (它们也是本地对象,根据定义,每个内置对象都是本地对象)。

宿主对象

所有非本地对象都是宿主对象(host object),即由 ECMAScript 实现的宿主环境提供的对象。
所有 BOM 和 DOM 对象都是宿主对象。

回归本地对象,我们不能被他们起的名字是本地对象,就把它们理解为对象(虽然他们就是对象,因为js中万物皆对象),但是通过:

typeof(Object)//function
typeof(Array)//function
typeof(Date)//function
typeof(RegExp)//function
typeof(Math)//object--《js中原型和原型链的深入理解》作者就把这个写成了function,幸好我自己运行了一下。Math也不是本地对象

也就是说上面那些输出结果为function的本地对象(类)是通过function建立起来的。

function Object(){}
function Array(){}
...

可以看出Object原本就是一个函数,通过new Object()之后实例化后,创建对象。
理清楚了这几个概念,有助于理解我们下面要讲述的原型和原型链。
prototype
prototype属性是每一个函数都具有的属性,但是不是一个对象都具有的属性。比如:

function Foo(){}var foo = new Foo();

其中Foo中有prototype属性,而foo没有。但是foo中的隐含的proto属性指向Foo.prototype。

foo.__proto__ === Foo.prototype

为什么会存在prototype属性?

Javascript里面所有的数据类型都是对象,为了使JavaScript实现面向对象的思想,就必须要能够实现‘继承’使所有的对象连接起来。而如何实现继承呢?JavaScript采用了类似C++,java的方式,通过new的方式来实现实例。

举个例子,child1,child2都是Mother的孩子,且是双胞胎。(虽然不是很好,但是还是很能说明问题的)

function Mother(name){this.name = name;this.father = 'baba';
}
var child1 = new Mother('huahua');
var child2 = new Mother('huihui');

如果有一天,发现孩子的父亲其实是Baba,那么就要对孩子每一个孩子的father属性。

child1.father ='Baba';
console.log(child2.father) // baba

也就是说修改了其中一个孩子的father属性不会影响到下一个,属性的值无法共享。
正是这个原因才提出来prototype属性,把需要共享的属性放到构造函数也就是父类的实例中去。

_proto_
proto属性是每一个对象以及函数(因为函数也是对象)都隐含的一个属性。对于每一个含有proto属性,他所指向的是创建他的构造函数的prototype。原型链就是通过这个属性构件的。
想像一下,如果一个函数对象(也称为构造函数)a的prototype是另一个函数对象b构件出的实例,a的实例就可以通过proto与b的原型链起来。而b的原型其实就是Object的实例,所以a的实例对象,就可以通过原型链和object的prototype链接起来。(笔者这里就有点晕了。。55555555555)

function a(){}
function b(){}
var b1 = new b();
a.prototype = b1;
var a1 = new a();
console.log(a1.__proto__===b1);//true
console.log(a1.__proto__.__proto__===b.prototype) //true
console.log(a1.__proto__.__proto__.__proto__===Object.prototype) //true

如果要理清原型和原型链的关系,首先要明确一下几个概念:

  1. JS中的所有东西都是对象,函数也是对象, 而且是一种特殊的对象
  2. JS中所有的东西都由Object衍生而来, 即所有东西原型链的终点指向Object.prototype
  3. JS对象都有一个隐藏的proto属性,他指向创建它的构造函数的原型,但是有一个例外,Object.prototype.proto指向的是null。
  4. JS中构造函数和实例(对象)之间的微妙关系
    构造函数通过定义prototype来约定其实例的规格, 再通过 new 来构造出实例,他们的作用就是生产对象.
function Foo(){}
var foo = new Foo();
//foo其实是通过Foo.prototype来生成实例的。
//构造函数本身又是方法(Function)的实例, 因此也可以查到它的__proto__(原型链)
function Foo(){}
等价于
var Foo= new Function();
//而Function实际上是
function Function(){Native Code
}
也就是等价于
var Function= new Function();
//所以说Function是通过自己创建出来的。正常情况下对象的__proto__是指向创建它的构造函数的prototype的.
//所以Function的__proto__指向的Function.prototype
//Object 实际上也是通过Function创建出来的
typeof(Object)//function 所以,
function Object(){Native Code
}
等价于
var Object = new Function();
//那么Object的__proto__指向的是Function.prototype,也即是Object.__proto__ === Function.prototype //true
//下面再来看Function.prototype的__proto__指向哪里
//因为JS中所有的东西都是对象,那么,Function.prototype 也是对象,既然是对象,那么Function.prototype肯定是通过//Object创建出来的,所以,Function.prototype.__proto__ === Object.prototype //true

综上所述,Function和Object的原型以及原型链的关系可以归纳为下图。(跟着作者一步步走,笔者慢慢有些明白了)

之前看文章也有这张图,现在有这篇清晰的解说就可以常来看看了。相信久而久之也就明朗了。
对于单个的对象实例,如果通过Object创建。

var obj = new Object();

那么它的原型和原型链的关系如下图。

如果通过函数对象来创建,

function Foo(){}
var foo = new Foo();

那么它的原型和原型链的关系如下图

那JavaScript的整体的原型和原型链中的关系就很清晰了,如下图所示


作者:erdu
作者网站:segmentfault.com/a/1190000014717972
笔者:小蜜峰
前端的搬运工。

《js中原型和原型链的深入理解》的笔记相关推荐

  1. JS 中原型和原型链深入理解

    作者: erdu segmentfault.com/a/1190000014717972 首先要搞明白几个概念: 函数(function) 函数对象(function object) 本地对象(nat ...

  2. 前端开发:JS中原型和原型链的介绍

    前言 在前端开发过程中,涉及到JS原理相关的内容也就是常用的几大模块,不仅常用而且很重要,但是涉及到原理的话会有点难懂,尤其是对JS接触不太久的开发者来讲.本篇博文就来分享一下关于JS的原型和原型链相 ...

  3. JS中的原型链(超清晰理解)

    什么是原型链 原型链,所有的原型构成了一个链条,这个链条我们称之为原型链(prototype chain). 原型链的案例 如果我们执行下面这段代码,因为没有定义address这个属性,程序结果理所当 ...

  4. JS原型链的一些理解

    关于原型链我的理解是一个构造函数的原型作为另一个构造函数的实例形成的继承关系 在JS高级程序设计中有这样一个图 当我们定义一个函数时会有一个原型,即图中的SuperType Prototype,这时原 ...

  5. JS题目总结:原型链/new/json/MVC/Promise

    JS题目总结:原型链/new/json/MVC/Promise 1原型链相关 解读: 上图中,Object,Function,Array,Boolean都是构造函数 第一个框: object是实例对象 ...

  6. 【JS继承】JS继承之原型链继承

    自我介绍:大家好,我是吉帅振的网络日志:微信公众号:吉帅振的网络日志:前端开发工程师,工作4年,去过上海.北京,经历创业公司,进过大厂,现在郑州敲代码. JS继承专栏 1[JS继承]什么是JS继承? ...

  7. [js] js怎样避免原型链上的对象共享?

    [js] js怎样避免原型链上的对象共享? 组合继承 优势 公有的写在原型 私有的卸载构造函数 可以向父类传递参数 劣势 需要手动绑定constructor 封装性一般 重复调用父类性能损耗

  8. 理解js中的原型链,prototype与__proto__的关系

    说到prototype,就不得不先说下new的过程. 我们先看看这样一段代码: 1 <script type="text/javascript"> 2 var Pers ...

  9. JS三座大山之原型链

    在JS中原型链的概念刚开始可能一直迷惑着大多数人,我也一样,不过花点时间仔细的梳理梳理,还是很容易理解的.本文就着重介绍一下原型链,如有不对之处,欢迎指正,共同探讨,共同进步. 在面试时,面试官可能会 ...

最新文章

  1. JavaScript中获取表单信息并添加在表格中
  2. CodeForces 258D Little Elephant and Broken Sorting(期望)
  3. pandaboard 安装_linux fb设备(pandaboard) | 学步园
  4. 从浪漫走向坚韧:开源数据库的演变
  5. 突发!Nginx 之父被拘留,原因竟然是“接私活儿”?
  6. Android的Dialog类设计的太糟糕了!
  7. 【Elasticsearch】 es 索引 内置 字段 _source
  8. python go rpc_Python RPC 之 gRPC
  9. 突然出现 -bash: pod: command not found 的解决方法
  10. UE4学习日记(十一)实现简单的御剑(板)飞行功能
  11. OpenCms for MySql安装
  12. 笔记本电脑耳机插入后声音还是外放的解决办法
  13. 计算机学硕比专硕累吗,2019计算机考研常识:学硕与专硕对比
  14. Python Post提交简单案例,文本内容在线语音合成
  15. hibernate hbb.xml 映射关系
  16. 网易音乐人2021年度盘点上线 揭晓2021年华语原创音乐年度记忆
  17. win7的Par虚拟机版优化(parellel desktop)
  18. UEFI开发与调试---edk2中的Package
  19. 汇编程序设计:代码转换程序
  20. CAN收发器TJA1040简介

热门文章

  1. 2022年首个交易日特斯拉股价暴涨 马斯克重回3000亿美元身价
  2. 对自己的工作越来越不喜欢了
  3. POI - 读取Excel2003、Excel2007或更高级的兼容性问题
  4. python实现sftp上传和下载
  5. vision下载地址
  6. mysql:5.7.28 Docker image analysis
  7. 2D检测经典算法框架介绍
  8. hash算法MurmurHash
  9. 2014年高考计算机试题答案,2014高考计算机试卷.doc
  10. java时间间隔_java 计算两个 日期时间 相间隔多少天小时分钟 等