“一切皆对象”是JavaScript的行为层面概括,并非字面意义;原始类型(string、number等)不可变、按值传递,而对象可扩展、按引用传递,引擎通过自动装箱使原始值能调用方法,实现易用性与性能的平衡。

JavaScript 中说“一切皆对象”,并不是字面意义上所有值都是 Object 实例,而是一种设计哲学和行为表现的概括;它同时承认原始类型的存在,是因为语言必须兼顾性能、语义清晰和底层效率——原始类型是不可变的轻量值,对象则是可变、可扩展的引用实体。
“一切皆对象”指的是行为层面的统一性
JS 允许对原始值(如 "abc"、42、true)直接调用方法或访问属性:
-
"hello".toUpperCase()—— 字符串虽是原始值,但能调用String.prototype上的方法 -
(123).toFixed(2)—— 数字字面量也能使用Number.prototype方法 -
false.toString()—— 布尔值同样支持原型链上的操作
这背后是 JS 引擎自动触发的「临时包装」(auto-boxing):每次访问属性或方法时,引擎悄悄把原始值转成对应的包装对象(String、Number、Boolean),用完即弃。所以它“像对象一样用”,但不等于“就是对象”。
原始类型是语言的底层优化机制
JS 明确定义了 7 种原始类型(ES2020+):string、number、boolean、null、undefined、symbol、bigint。它们的关键特征是:
立即学习“Java免费学习笔记(深入)”;
- 按值传递,存储在栈中,开销小
- 不可变(immutable):任何“修改”操作都返回新值,原值不变
- 没有自有属性:给
let s = "a"; s.x = 1赋值不会报错,但s.x读出来是undefined,因为赋值发生在临时包装对象上,瞬间销毁 -
null和undefined连包装对象都没有,访问其属性会直接报错(Cannot read property 'xxx' of null)
对象是可扩展、有身份、带原型的实体
除了原始类型,其余全是对象:数组、函数、正则、日期、Promise、Map、Set,甚至你写的 {} 或 class Foo{} 实例。它们共有的特点是:
- 按引用传递,可被多个变量共享
- 可动态添加/删除属性和方法
- 拥有
__proto__和constructor,构成原型链 - 可通过
typeof区分(返回"object"或"function"等),但注意typeof null === "object"是历史遗留 bug
为什么这样设计?平衡与折中
JS 作为嵌入式脚本语言,诞生之初就要兼顾易用性和执行效率:
- 让原始值“假装是对象”,开发者不用总写
new String("x")就能用方法,降低门槛 - 保留原始类型,避免每个数字都变成重量级对象,节省内存和提升运算速度
- 函数、数组等复杂结构天然以对象形式实现,统一模型便于引擎管理和扩展(比如给
Array.prototype加新方法,所有数组立刻可用)
所以,“一切皆对象”是表象与能力的总结;“存在原始类型”是实现与性能的必然选择。二者不矛盾,而是 JS 动态、务实设计观的体现。


















