序、范例代码

以下为范例代码,本文中讲解多次用到这段代码,可以在阅读本文前提前运行,边看文边敲码验证。

function Person(){}; //构造函数
var person = new Person(); //实例对象复制代码

一、对象

每个对象都是基于一个引用类型创建的,这个引用类型可以是原生类型(Object、Array、Function等),也可以是用户自定义的类型。

对象总的来说大致可以分成两种:

1、函数对象(Function Object)

通过new Function()生成函数并为其指定函数名,通过函数名来进行调用,其实就是我们通常所说的函数。

2、其他类型的对象(Object)

直接通过new操作符生成(除了Function类型)的对象,如new Object(); 。

对象通过new操作符创建的过程:

(1)创建一个新对象;

(2)将构造函数的作用域赋给新对象(this就会指向这个新对象);

(3)执行构造函数中的代码(为对象添加属性);

(4)返回新对象。

二、原型指针(__proto__)

当构造函数创建一个新实例(又称实例对象,下同)后,该实例下都会存在一个指针__proto__(内部属性),指向创建这个实例的构造函数(constructor指向值)下的原型对象(prototype)。只要是个对象,都会有__proto__。

根据范例代码来看,person是属于构造函数Person的一个实例,person.__proto__ === Person.prototype为true。要明确的真正重要的一点就是,这个连接存在于实例与构造函数的原型对象之间,而不是存在于实例与构造函数之间。

这里出现了另外两个名词:构造函数和原型对象,请看下面内容。

三、构造函数(constructor指向值)

构造函数的解释是这样的,创建对象时初始化对象。任何函数,只要通过new操作符来调用,那它就可以作为构造函数。像Object和Array等这样执行环境自带的称为原生构造函数,它们会在运行时自动出现在执行环境中。

观察范例代码,person是一个对象,而他的构造函数就是Person,Person.prototype.constructor === Person为true。

四、原型对象(prototype)

原型对象比较特殊(划重点),只有函数对象会拥有,是用来解决构造函数在创建实例的时候,防止重复执行所导致的性能的降低(这里主要指占用内存),为复用带来方便。

无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性是一个指针,指向函数的原型对象,这个原型对象的用途是包含可以由特定类型的所有实例共享的属性和方法,如果按照字面意思来理解,那么prototype也是通过调用构造函数而创建的那个对象实例的原型对象(__proto__指向值)。

在默认情况下,所有原型对象(prototype)都会自动获得一个constructor属性,这个属性包含一个指针,指向prototype属性所在函数,通常会是构造函数。

五、原型搜索机制

每当代码读取某个对象的某个属性时,都会执行一次搜索,目标是具有给定名字的属性。搜索首先从对象实例本身开始。如果在实例中找到了具有给定名字的属性,则返回该属性的值;如果没有找到,则继续搜索指针指向的原型对象,在原型对象中查找具有给定名字的属性。如果在原型对象中找到了这个属性,则返回该属性的值。

以上就是原型搜索机制的大致介绍。原型链继承(此篇不讲,有兴趣自行谷歌百度)则是在这个基础上进行扩展,然后实现继承,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。

六、原型关系图

如上图,我们从最简单的关系入手。以范例代码为例,创建Person函数,然后进行实例化生成实例对象person。

我们来看看实例对象person和函数Person各自的原型关系:

1、person(实例对象)

person会有一个__proto__指针,指向构造函数的原型对象Person.prototype。Person.prototype会有两个属性constructor和__proto__,constructor指向构造函数Person,__proto__指向原生类型Object的原型对象Object.prototype。Object.prototype有两个属性constructor和__proto__,constructor指向它的构造函数Object,而比较特殊的是__proto__的值为null(原型链的终点),用下列代码可验证。

person.__proto__ === Person.prototype; //true
person.__proto__.__proto__ === Person.prototype.__proto__; //true
person.__proto__.__proto__ === Object.prototype; //true
Person.prototype.__proto__ === Object.prototype; //true
Object.prototype.__proto__ === null; //true复制代码

2、Person(构造函数)

Person函数也会有一个__proto__指针,不同的是多了一个prototype对象属性。prototype的构成上面已经介绍过就不重复了,__proto__指向原生类型Function的原型对象Function.prototype。Function.prototype有两个属性constructor和__proto__,constructor指向构造函数Function,__proto__指向Object的原型对象Object.prototype,介绍同上。

Person.__proto__ === Function.prototype; //true
Function.prototype.__proto__ === Object.prototype; //true
Person.prototype.__proto__ === Object.prototype; //true
Object.prototype.__proto__ === null; //true复制代码

3、原生类型函数

Function函数和Object函数除了prototype之外都存在一个__proto__指针,都是指向Function的原型对象Function.prototype,介绍同上。

Object.__proto__ === Function.prototype; //true
Function.__proto__ === Function.prototype; //true复制代码

4、总结

构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型的内部指针。所有构造函数的__proto__指针指向都是Function.prototype;所有对象的__proto__指针最终指向都是指向Object.prototype,而Object.prototype的__proto__属性值则为null。

七、写在最后

最近在网上看见一个类似关于Function和Object谁是爸爸(由谁而来)的问题,记得最开始学js时就把“js中万物皆对象”这句话给记牢了,想着应该是对象最原始,但是凡事都要有个理(拿出证据来),所以就深究了一下以上函数和对象的一些关系,至于谁是爸爸,明确不出来,但是有一点可以肯定的是,无论是谁,按关系图最后的走向都是null(貌似已经出现结果。。。)。

八、参考文献

最详尽的 JS 原型与原型链终极详解

彻底理解JavaScript原型链(一)—__proto__的默认指向

高能!typeof Function.prototype 引发的先有 Function 还是先有 Object 的探讨

《javascript高级程序设计》

附录一:较为完整的原型链关系图

附录二:浏览器在初始化JS 环境时都发生了些什么(猜的)

1.用 C/C++ 构造内部数据结构创建一个 OP 即(Object.prototype)以及初始化其内部属性但不包括行为。

2.用 C/C++ 构造内部数据结构创建一个 FP 即(Function.prototype)以及初始化其内部属性但不包括行为。

3.将 FP 的[[Prototype]]指向 OP。

4.用 C/C++ 构造内部数据结构创建各种内置引用类型。

5.将各内置引用类型的[[Prototype]]指向 FP。

6.将 Function 的 prototype 指向 FP。

7.将 Object 的 prototype 指向 OP。

8.用 Function 实例化出 OP,FP,以及 Object 的行为并挂载。

9.用 Object 实例化出除 Object 以及 Function 的其他内置引用类型的 prototype 属性对象。

10.用 Function 实例化出除Object 以及 Function 的其他内置引用类型的 prototype 属性对象的行为并挂载。

11.实例化内置对象 Math 以及 Grobal

至此,所有 内置类型构建完成。

原创不容易,转载请声明出处,谢谢!

函数对象、对象、原型相关推荐

  1. 一张图说明 函数, 实例(对象), 原型之间的关系

    前言 很多初学者都对函数,实例(对象), 原型之间的关系理不清楚. 网上五花八门的文章很多,要么不知所云,要么是晦涩难懂. 本文意在用最简洁的语言跟示例让初学者理清楚这三者之间的关系,无需理会其内部原 ...

  2. 深入理解javascript原型和闭包(2)——函数和对象的关系

    上文(理解javascript原型和作用域系列(1)--一切都是对象)已经提到,函数就是对象的一种,因为通过instanceof函数可以判断. var fn = function () { }; co ...

  3. 的函数原型_JS基础函数、对象和原型、原型链的关系

    JS的原型.原型链一直是比较难理解的内容,不少初学者甚至有一定经验的老鸟都不一定能完全说清楚,更多的"很可能"是一知半解,而这部分内容又是JS的核心内容,想要技术进阶的话肯定不能对 ...

  4. javaScript核心学习 (二)函数和对象,继承原型链

    javaScript的函数和对象,继承原型链 一.函数 1.初始函数 2.创建函数 2.1 参数设置 2.2 函数声明 来创建函数 2.3 函数表达式创建函数 3.变量作用域 4.匿名函数 5.回调函 ...

  5. js对象,原型,call,apply浅析

    //对象直接量,创建对象最简单的方式是在js里使用对象直接量var book = {"main title": "js", //属性里有空格,要用引号" ...

  6. Js 原型对象与原型链(转)

    原文出处 原创作者: abruzzi 原文图文并茂,很好的说明了原型链的原理,在这里感谢原文作者把文章写的那么通俗易懂. 原型对象 每个javascript对象都有一个原型对象,这个对象在不同的解释器 ...

  7. js 中对象--对象结构(原型链基础解析)

    对于本篇对于如何自定义对象.和对象相关的属性操作不了解的话,可以查我对这两篇博客.了解这两篇可以更容易理解本篇文章 用构造函数创建了一个对象 obj对象的本身创建了两个属性  x=1   ,y=2 对 ...

  8. javascript原型对象、原型链、构造函数

    1.原型对象(原型).原型链 先放一张在网上看到的关于原型和原型链的图,非常不错. 如果你能看懂,那就对原型链有了一定了解,如果看不懂,对照下面这几点来看图: js中所有函数都有一个prototype ...

  9. 为内置对象添加原型方法 把局部变量编程全局变量

    为内置对象添加原型方法 <!DOCTYPE html> <html lang="en"> <head><meta charset=&quo ...

  10. 《JavaScript专家编程》——第1章 对象和原型 1.1鸟瞰JavaScript

    本节书摘来自异步社区<JavaScript专家编程>一书中的第1章,第1.1节,作者:[美]Mark Daggett(达格特)著,更多章节内容可以访问云栖社区"异步社区" ...

最新文章

  1. 2月国内搜索市场:360继续上升 百度下降0.62%
  2. 用Python发送邮件[zt]
  3. JavaBeans四个作用域 范围
  4. 【机器学习基础】一文说透正则项与模型复杂度
  5. jqplot学习笔记
  6. 中功率继电器行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  7. 运输层详解(二)(TCP)
  8. 昨天跟朋友聊天谈技术工作,竟然吹了4个小时
  9. 关于IDEA中有关springboot快启动报错问题
  10. mysql 游标插入数据_mysql游标插入问题
  11. C#,提取avi,mpeg,mp4,rmvb,mkv,flv等等视频文件的摘要信息的方法及其源程序
  12. 微信降级adb备份android7.0,微信自动帮你更新7.0了?简单两步轻松降级
  13. 万字长文:上海交大校友、宾大直博博士细说五年读博经历
  14. 笔记本电脑计算机无法显示u盘,笔记本识别不了U盘|电脑无法识别优盘怎么办?...
  15. 收付款单提交时分录自动清空
  16. 二进制加权电容器阵列的构建公共质心布局和布线
  17. 论文阅读笔记——VulDeePecker: A Deep Learning-Based System for Vulnerability Detection
  18. word文档转pdf并在任意浏览器预览打印一体化方案
  19. 刀塔传奇这种类型的arpg客户端战斗架构设计
  20. 网络协议 -- HTTP协议,get和post的区别?

热门文章

  1. JavaScript之节点的创建、替换、删除、插入
  2. CentOS6.5恢复误删除的文件
  3. 结对项目 浪曦计时器
  4. delphi中exit,abort,break,continue 的区别
  5. 数据分析之处理丢失数据
  6. mybatis学习笔记(五):mybatis 逆向工程
  7. 车牌识别LPR系统系列文章汇总
  8. opencv图像处理8-卷积
  9. dropdownlist中DataTextfield与DataValue的区别
  10. K-Means原理及代码实现