深入理解JavaScript-JavaScript 中的始皇

简介: 深入理解JavaScript-JavaScript 中的始皇

前言


笔者在 继承 中发了一题关于原型链关系图的题,题目来源自颜海镜的如何回答面试中的JavaScript原型链问题[1],这题确实很好,当画完它时,会有种看到这幅图的感觉

image.png

确实,这图一看很懵,搞不懂。再来看看这几段代码


Object instanceof Object // true
Function instanceof Function // true
Object instanceof Function // true
Function instanceof Object // true


为什么会如此,Object 和 Function 谁才是始皇,还有 Object.prototype 处于什么位置,Function.prototype 呢?


在知乎曾讨论过这个话题,JS中先有Object还是先有Function?[2]

这里,笔者查一查谁是最先出现的皇


正文


在写 一切皆对象 时,笔者阐释 JavaScript 中的对象有内置对象,而这些内置对象是语言内部创建,这些内置对象都是构造函数,即又被称为内置构造函数,它们存在的目的是为了让开发者更方便的书写代码。这些内置构造函数包括 Object、Function、Array、String、Number、RegExp 等等


因为它们是构造函数,所以它们必然属于函数,因为是函数,所以它们都是 Function 创建的,因为是 Function 创建的,所以它们都是 Function 的实例,即


String instanceof Function // true
Array instanceof Function // true
Function instanceof Function // true
Object instanceof Function // true


所以它们的原型链关系图是

image.png

又因为 Function 是函数,所以它有 prototype 属性。因为函数也是对象,所以 Function 也有 constructor 和 [[Prototype]],它的关系图是

image.png

所以就有了


Function.__proto__ === Function.prototype

即:

image.png

原型 中,我们讲到了原型链,因为每个对象都有[[Prototype]]属性,它会指向它的原型对象,一层一层,最终指向 null。而 null 的上一站是 Object.prototype


无论你是构造函数的原型,还是自定义对象的原型,都会先指向 Object.prototype,再由 Object.prototype 指向 null


String.prototype.__proto__ === Object.prototype // true
Number.prototype.__proto__ === Object.prototype // true
Array.prototype.__proto__ === Object.prototype // true
Function.prototype.__proto__ === Object.prototype // true
Object.prototype.__proto__ === null // true
var obj = {};
var arr = [];
function func() {}
obj.__proto__ ===  Object.prototype // true
arr.__proto__.__proto__ === Object.prototype // true
// arr.__proto__ 指向 Array.prototype
func.__proto__.__proto__ === Object.prototype // true
// func.__proto__ 指向 Function.prototype


它们的原型链关系图如下所示:

image.png

image.png

所以看代码和图我们知道,所有原型继承的源头都在 Object.prototype,Object.prototype 对象上的属性,会被任何值使用,所以判断类型最准确的办法是 Object.prototype.toString.call(source)


如果我们将构造函数的源头和原型的源头结合一下,就成了这样:

image.png

此图和 Object Layout 的图大差不差,关键在于 Object 和 Function

Object.prototype 的原型之母,任何原型都源自它


Function.prototype 是构造函数之母,任何构造函数都由它创建,包括它自己

理解了这两点,我们再回过头看这个问题


Object instanceof Object // true
// Object 由 Function.prototype 创建,Function.prototype 的原型对象指向 Object.prototype
Function instanceof Function // true
// Function 由 Function.prototype 创建
Object instanceof Function // true
// Object 由 Function.prototype 创建
Function instanceof Object // true
// Function 由 Function.prototype 创建,Function.prototype 的原型对象指向Object.prototype


注意一点:构造函数也是实例,找出创建他们的构造函数和原型就能明白


总结


谁是始皇,无疑。Object.prototype 才是真正的始皇,任何原型都源自它;而 Function.prototype 是仅次于 Object.prototype 的存在,它是内置构造函数的创建者,任何构造函数都源自它


参考资料


[1如何回答面试中的JavaScript原型链问题: https://zhuanlan.zhihu.com/p/356980105

[2] JS中先有Object还是先有Function?: https://www.zhihu.com/question/35442532

相关文章
|
3月前
|
JavaScript 前端开发 安全
从0开始学习JavaScript--初识JavaScript
JavaScript最初由Netscape的Brendan Eich设计,最初将其脚本语言命名为LiveScript,后来Netscape在与Sun合作之后将其改名为JavaScript。JavaScript最初受Java启发而开始设计的,目的之一就是“看上去像Java”,因此语法上有类似之处,一些名称和命名规范也借自Java,但JavaScript的主要设计原则源自Self和Scheme。JavaScript与Java名称上的近似,是当时Netscape为了营销考虑与Sun微系统达成协议的结果。微软同时期也推出了JScript来迎战JavaScript的脚本语言。
从0开始学习JavaScript--初识JavaScript
|
3月前
|
自然语言处理 JavaScript 前端开发
三个JavaScript面试题
【5月更文挑战第7天】- 闭包是JavaScript函数能记住词法作用域,即使在外部执行。示例:计数器函数`createCounter()`返回访问`count`的匿名函数,每次调用计数递增。 - 事件循环处理异步操作,通过检查任务队列执行回调。示例:`setTimeout`异步任务在3秒后添加到队列,待执行,输出顺序为同步任务1、2,然后异步任务1。 - 箭头函数是ES6简洁的函数定义方式,如`greet = name => `Hello, ${name}!`。它没有自己的`this`,不适用作构造函数。
42 6
|
3月前
|
前端开发 JavaScript
每日一道javascript面试题(三)
每日一道javascript面试题(三)
|
3月前
|
JavaScript 前端开发 Java
javaScript(一):javaScript基础知识
JavaScript是一种常用的脚本语言,通常用于为网页添加动态功能和交互性。它是一种解释性语言,可以直接在网页的HTML代码中嵌入,并由浏览器解释执行。JavaScript广泛用于网页开发,可以用于验证表单输入、创建动态效果、操作网页元素、处理用户事件等。
45 2
|
3月前
|
缓存 前端开发 JavaScript
JavaScript面试题(二)
JavaScript面试题(二)
94 0
|
移动开发 JavaScript 前端开发
《JavaScript高级程序设计》__ HTML中的JavaScript
前言 大家好,我是HoMeTown,web领域有一本神书大家应该都有看过,这本书我看过两遍,但是每次看都是粗粗的略过一些重要的知识点,甚至一些面试过程中的问题,在这本书里都能找到答案
119 3
|
Web App开发 JavaScript 前端开发
深入理解JavaScript-JavaScript 由什么组成
深入理解JavaScript-JavaScript 由什么组成
83 0
深入理解JavaScript-JavaScript 由什么组成
|
自然语言处理 JavaScript 前端开发
深入理解JavaScript-JavaScript 是什么
深入理解JavaScript-JavaScript 是什么
98 0
|
存储 缓存 开发框架
JavaScript入门【JavaScript专题1】
JavaScript入门 从今天开始就与大家一起学习JavaScript了 在本系列教程中,您将学习如何制作 JavaScript 驱动的网页。
136 0
|
JavaScript 前端开发 程序员
JavaScript常见面试题五
  好程序员Java教程分享JavaScript常见面试题五   1、以下代码行将输出什么到控制台?   console.log("0||1="+(0||1));console.log("1||2="+(1||2));console.log("0&&1="+(0&&1));console.log("1&&2="+(1&&2));   并解释。
669 0