乐趣区

关于前端:深入理解JavaScript一切皆对象

先来看一句有争议的话——” 在 JavaScript 中,所有皆对象。了解了对象,就能了解 JavaScript”

你感觉这句话是对是错,为什么?其实在知乎上就曾有人提过一个问题——如何了解 javascript 中一切都是对象?

咱们无妨先放一放,在文末笔者会给出本人的答案,如想看答案可间接划到文末查看

在前文 JavaScript 由什么组成,笔者曾一句带过:

援用类型是 object(一组属性的汇合)

而这个 object 包含什么,前文中的案例中呈现的 Function、Array 之流又属于什么?

这里援用两本书和 MDN 中的内容,并联合下给它下个定性:

依照《JavaScript 高级编程第四版》(后文简写高程四)中的说法:

援用类型包含:Object、Array、定型数组(typed array)、Date、RegExp、Function、根本包装类型(String、Number、Boolean)、单体内置对象(Global、Math)、ES6 新增援用类型(Map、WeakMap、Set、WeakSet)

而在《JavaScript 启示录》中,则给出 9 个原生(或内置)对象构造函数,String、Number、Boolean、Object、Array、Function、Date、RegExp、Error

而 MDN 更全面,不仅有值属性(NaN、undefined)、函数属性(eval、isNaN、parseFloat、encodeURI)、根本对象(Object、Function、Boolean、Symbol)、谬误对象(Error、TypeError、ReferenceError)、数字和日期对象(Number、BigInt、Math、Date)、字符串(String、RegExp)、可索引的汇合对象(Array)、应用键的联合对象(Map、Set、WeakMap、WeakSet)、结构化数据(ArrayBuffer、JSON)、管制形象对象(Promise、Generator)、喷射(Reflect、Proxy)、国际化(Int1)、WebAssembly、arguments 等等

集体认为 MDN 上的内容能够当字典来查看,而对外(面试)能够以高程四为规范解释

等等等等

不是说援用类型就指 object(对象)吗,为什么还包含这些货色,它们不是内置对象吗?

对象~~

内置对象~~

难道说对象包含内置对象?

所以 MDN 才说:对象(object)是指内存中的能够被标识符援用的一块区域

高程四才说:ECMA-262 将对象定义为一组属性的无需组合。能够把 ECMAScript 的对象设想成一张散列表,其中的内存就是一组名 / 值对,值能够是数据或者函数

所以 JavaScript 中的对象蕴含内置对象(或者说对象由内置对象和自定义对象组成)

因为「原型」、「继承」等更底层的设计,对象是 ” 始祖伟人 ”。基于它,String、Number、Boolean、Array、Function、Date、RegExp、Error 等等以各自个性成一构造函数,当然不知它们,还有很多其余的内置对象

起初,笔者在看《JavaScript 权威指南 (第 6 版)》时看到这一解释:

以下术语来辨别三类 JavaScript 对象和两类属性

  • 内置对象(native object)是由 ECMAScript 标准定义的对象或类。例如,数组、函数、日期和正则表达式都是内置对象
  • 宿主对象(host object)是由 JavaScript 解释器所嵌入的宿主环境(比方 Web 浏览器)定义的
  • 自定义对象(user-defined object)是由运行中的 JavaScript 代码创立的对象
  • 自有属性(own property)是间接在对象中定义的属性
  • 继承属性(inherited property)是在对象的原型对象中定义的属性

所以说 JavaScript 中的「对象」很厉害,大多数元素都是基于「对象」构建。其中像 Object、Function、Array 之类比拟重要,后续会对其介绍。单体内置对象、其余内置函数及 ES6 新增的 Map、Set、WeakMap、WeakSet 暂不做介绍,这里咱们先讲讲根本包装类型

根本包装类型

根本包装类型包含:String、Number、Boolean,它和根本类型中的 string、number、boolean 有什么区别

先看一下以下代码:

var string1 = 'foo';
var string2 = String('foo');
var number1 = 10;
var number2 = Number('10');
var boolean1 = true;
var boolean2 = Boolean('true');

console.log(typeof string1, typeof string2); // 输入 'string, string'
console.log(typeof number1, typeof number2); // 输入 'number, number'
console.log(typeof boolean1, typeof boolean2); // 输入 'boolean, boolean'

// 如果应用创建对象的构造函数和 new 关键字
var myString = new String('male');
var myNumber = new Number(23);
var myBoolean = new Boolean(false);
console.log(typeof myString, typeof myNumber, typeof myBoolean);
// object, object, object

咱们看到如果应用字面量语法创立值, 数据类型的输入后果是根本类型

如果应用 new 关键字创立 String()、Number()、Boolean() 值时, 创立的对象实际上是一个对象(援用类型)

这阐明 new 关键字做了一些手脚,具体后续文章会对其介绍

还看出无论是字面量创立值还是不带 new 调用根本包装类型,它们都会转换为其绝对应的类型

再看看这个例子

let str = "Hello";

console.log(str.toUpperCase()); // HELLO

一个根本类型为什么会有 toUpperCase 这个办法,它既然是根本类型,那就是一个字符串,为什么会有办法呢?办法从何而来?

高程四的解释是:

在以读模式拜访字符串值的任何时候,后盾都会执行以下 3 步:

  1. 创立一个 String 类型的实例;
  2. 调用实例上的特定办法
  3. 销毁实例

能够把这 3 步设想成执行了如下 3 行 ECMAScript 代码:

let s1 = new String("some text")
let s2 = s1.substring(2)
s1 = null

JavaScript Info 给出的解答是:

以下是 JavaScript 创建者面临的悖论:

  • 人们可能想对诸如字符串或数字之类的原始类型执行很多操作。最好应用办法来拜访它们。
  • 原始类型必须尽可能的简略轻量。

而解决方案看起来多少有点难堪,如下:

  1. 原始类型依然是原始的。与预期雷同,提供单个值
  2. JavaScript 容许拜访字符串,数字,布尔值和 symbol 的办法和属性。
  3. 为了使它们起作用,创立了提供额定性能的非凡“对象包装器”,应用后即被销毁。

“对象包装器”对于每种原始类型都是不同的,它们被称为 StringNumberBooleanSymbolBigInt。因而,它们提供了不同的办法。

两则都给出了一个答案:

在调用字符串、数字之类的根本类型类型时,ECMAScript 引擎会以根本包装类型为构造函数,创立一个基于它的实例,调用完后,失去生成的后果,删除调用时的实例

所以也解释了尽管它们是根本类型,却能调用各种原型办法

也体现了个别类型既要又要的非凡场景(既要轻量占内存小,又要有不便的办法),而这所有是为了进步性能

JavaScript 中一切都是对象?

回到结尾说的:如何了解 JavaScript 中一切都是对象?

笔者的答复是:

不能说所有,然而根本不差

JavaScript 按数据类型分,分为原始类型和援用类型。原始类型又被成为原始值,它包含 string,number,boolean,null,undefined,symbol,bigint;而援用类型则是对象,其对象分为内置对象、宿主对象、自定义对象。内置对象中有 Object、Array、定型数组(typed array)、Date、RegExp、Function、根本包装类型(String、Number、Boolean)、单体内置对象(Global、Math)、ES6 新增援用类型(Map、WeakMap、Set、WeakSet)等等,更具体的可查看 MDN

你写的代码除了根本类型外,都是对象,而根本类型中的 string、number、boolean、symbol、bigInt 又和根本包装类型有了调用原型办法后删除实例的关系。简略来说,它们既享受了根本类型的轻量占内存小,又取得了调用内置构造函数的各种原型办法

根本类型中,除了 null、undefined,其余的都与对象无关,而援用类型就是指对象,所以说 JavaScript 中的一切都是对象,大抵上是正确的

缘起性空,下一节,去看看对象中的内置构造函数—— Object

参考资料

  • JavaScript 高级程序编程第四版
  • JavaScript 权威指南
  • JavaScript 启示录
  • MDN
  • 古代 JavaScript 教程

系列文章

  • 深刻了解 JavaScript- 开篇
  • 深刻了解 JavaScript-JavaScript 是什么
  • 深刻了解 JavaScript-JavaScript 由什么组成
退出移动版