红宝书第四讲:JavaScript原始值与引用值行为差异详解

红宝书第四讲:JavaScript原始值与引用值行为差异详解

资料取自《JavaScript高级程序设计(第5版)》。 查看所有教程:红宝书学习大纲


一、基本定义与存储方式

  1. 原始值(Primitive Values)

    • 类型 :包括字符串(String)、数字(Number)、布尔值(Boolean)、nullundefinedSymbolBigInt^1^。
    • 存储方式 :直接存储在栈内存中,占用固定大小空间。例如一个数字或字符串直接保存其实际值^1^。
  2. 引用值(Reference Values)

    • 类型 :对象(Object)、数组(Array)、函数(Function)等。
    • 存储方式 :实际数据存储在堆内存中,变量保存的是指向堆内存的指针地址^1^。

二、变量复制时的差异

  1. 原始值的复制:独立拷贝

    • 复制后,新旧变量完全独立。

      javascript 复制代码
      let num1 = 5;
      let num2 = num1; // 复制值本身
      num1 = 10;
      console.log(num2); // 输出5(num2不受num1修改影响)[^2]
  2. 引用值的复制:共享对象

    • 复制的是指针地址,新旧变量指向同一个对象:

      javascript 复制代码
      let obj1 = { name: "Alice" };
      let obj2 = obj1;   // 复制指针地址
      obj1.name = "Bob"; 
      console.log(obj2.name); // 输出"Bob"(通过指针修改同一对象)[^2]

三、动态属性操作能力

  1. 引用值可动态增删属性

    • 对象可以随时添加或删除属性:

      javascript 复制代码
      let person = {};        // 空对象
      person.name = "Alice";  // 新增属性
      delete person.name;     // 删除属性[^4]
  2. 原始值无法添加属性

    • 即使试图添加属性,也不会保留:

      javascript 复制代码
      let name = "Charlie";
      name.age = 30;          // 不会报错,但无意义
      console.log(name.age);  // 输出undefined[^4]

四、类型检测与包装对象

  1. 类型检测工具

    • typeof:返回原始值的类型(如 "string""number"),但引用值统一返回 "object"(函数返回 "function")^1^。
    • instanceof:用于检测引用值是否属于某个类(如 [] instanceof Array 返回 true)^1^。
  2. 原始包装对象的特殊行为

    • 原始值调用方法时临时创建对象包装器:

      javascript 复制代码
      let s = "hello";
      console.log(s.substring(1)); // 临时转换为String对象调用方法[^5]
    • 包装对象与原始值的区别:

      javascript 复制代码
      let a = "text";
      let b = new String("text"); 
      console.log(typeof a); // "string"(原始值)
      console.log(typeof b); // "object"(引用值)[^1]

五、典型陷阱:原始值与包装对象的逻辑差异

  1. 布尔值的逻辑陷阱
    • 原始值 false 与对象 new Boolean(false) 的不同行为:

      javascript 复制代码
      let bool1 = false;
      let bool2 = new Boolean(false);
      console.log(bool1 && true); // false(原值按false处理)
      console.log(bool2 && true); // true(对象按true处理)[^6]

总结核心差异

特性 原始值(如 5, "text" 引用值(如 {}, []
存储位置 栈内存 堆内存(变量保存指针地址)
复制行为 独立拷贝值 共享同一对象
属性动态修改 不允许 允许
类型检测 typeof 正确区分 instanceof 检测对象类型

原始包装对象特殊行为详细解释


一、原始值为什么能调用方法?

JavaScript 的基础类型(如 "hello")不是对象,但在调用方法时,会临时创建对应的包装对象,使原始值具备对象的行为:

javascript 复制代码
let s = "hello";
console.log(s.substring(1)); // "ello"
  1. 实际发生了什么
    • 当调用 substring() 时,JS 引擎自动将 s 转换为 new String("hello")(String 对象)。
    • 调用完方法后,临时对象被销毁^2^。

二、原始值与包装对象的本质区别

通过 typeof 可以直观看出两者的存储方式不同:

javascript 复制代码
let a = "text";         // 原始值
let b = new String("text"); // 包装对象

console.log(typeof a);  // "string"(直接存储值)
console.log(typeof b);  // "object"(指针,指向堆内存中的对象)[^1]
  • 行为差异
    • a 无法添加属性(如 a.age = 20 无效)。
    • b 可以动态增删属性(如 b.age = 20 生效)。

三、典型陷阱:布尔值的逻辑判断

原始值和包装对象在逻辑运算中行为完全不同:

javascript 复制代码
let bool1 = false;          // 原始值
let bool2 = new Boolean(false); // 包装对象(本质是对象)

console.log(bool1 && true); // false(直接按原值 false 处理)
console.log(bool2 && true); // true(对象在逻辑运算中始终被视为 true)[^1]

原因解释

  • 所有对象(包括 new Boolean(false))在逻辑运算中会被强行转为 true
  • 原始值则严格按原值处理。

四、如何记住这些差异?

特征 原始值("text" 包装对象(new String("text")
存储方式 直接存储值 存储指针,指向堆内存中的对象
方法调用 临时创建包装对象 直接调用
逻辑判断 按实际值(如 false 始终视为 true(因为是对象)
添加属性 无效 有效(操作真实对象)

包装对象的键(key)与值(value)详解


1. new Boolean(false) 的键与值

  • 关键点
    new Boolean(false) 实际创建的是一个 对象 ,内部存储了原始值 false,但其行为完全遵循对象的规则^3^。

  • 键(keys)

    无显式可枚举属性(自身属性)。通过 Object.keys() 会返回空数组:

    javascript 复制代码
    let boolObj = new Boolean(false);
    console.log(Object.keys(boolObj)); // [](无直接属性)
  • 值(value)

    • 实际存储的原始值通过 valueOf() 获取:

      javascript 复制代码
      console.log(boolObj.valueOf()); // false(原始值)[^5]
    • 但在布尔表达式中,对象始终被视为 true

      javascript 复制代码
      console.log(boolObj && true); // true(包装对象的逻辑行为)[^2]

2. new String("text") 的键与值

  • 关键点
    new String("text") 会创建一个 字符串包装对象 ,内部存储字符串的字符序列和一个固定属性 length^4^。

  • 键(keys)

    包含字符索引(如 0, 1, 2, 3)和 length

    javascript 复制代码
    let strObj = new String("text");
    console.log(Object.keys(strObj)); 
    // ["0", "1", "2", "3", "length"](不同环境中可能仅包含 "length")[^6]
  • 值(value)

    • 索引对应字符:

      javascript 复制代码
      console.log(strObj[0]); // "t"
      console.log(strObj[1]); // "e"
    • length 表示字符长度:

      javascript 复制代码
      console.log(strObj.length); // 4 [^6]
    • valueOf() 返回原始字符串:

      javascript 复制代码
      console.log(strObj.valueOf()); // "text"(原始值)[^5]

原理总结

类型 new Boolean(false) new String("text")
本质上 对象(存储 false 对象(存储字符序列和 length
显式键(keys) 无^[5](#类型 new Boolean(false) new String("text") 本质上 对象(存储 false) 对象(存储字符序列和 length) 显式键(keys) 无5 字符索引和 length4 实际值 false(需用 valueOf()) "text"(通过 valueOf()) 行为差异 逻辑运算中视为 true3 字符和长度可直接访问4 "#user-content-fn-5")^ 字符索引和 length^[4](#类型 new Boolean(false) new String("text") 本质上 对象(存储 false) 对象(存储字符序列和 length) 显式键(keys) 无5 字符索引和 length4 实际值 false(需用 valueOf()) "text"(通过 valueOf()) 行为差异 逻辑运算中视为 true3 字符和长度可直接访问4 "#user-content-fn-6")^
实际值 false(需用 valueOf() "text"(通过 valueOf()
行为差异 逻辑运算中视为 true^[3](#类型 new Boolean(false) new String("text") 本质上 对象(存储 false) 对象(存储字符序列和 length) 显式键(keys) 无5 字符索引和 length4 实际值 false(需用 valueOf()) "text"(通过 valueOf()) 行为差异 逻辑运算中视为 true3 字符和长度可直接访问4 "#user-content-fn-2")^ 字符和长度可直接访问^[4](#类型 new Boolean(false) new String("text") 本质上 对象(存储 false) 对象(存储字符序列和 length) 显式键(keys) 无5 字符索引和 length4 实际值 false(需用 valueOf()) "text"(通过 valueOf()) 行为差异 逻辑运算中视为 true3 字符和长度可直接访问4 "#user-content-fn-6")^

目录:总目录 上篇文章:第三讲:JavaScript 操作符与流程控制详解

Footnotes

  1. 原始值和引用值的核心特性,文件 《JavaScript高级程序设计(第5版)》 第4章 2 3 4 5

  2. 原始值调用方法时的临时包装对象机制,文件 《JavaScript高级程序设计(第5版)》 第5章

  3. Boolean包装对象的逻辑行为,文件 《JavaScript高级程序设计(第5版)》 第5章 2

  4. String包装对象的length属性与字符索引,文件 《JavaScript高级程序设计(第5版)》 第5章 2 3

  5. 包装对象的valueOf方法,文件 《JavaScript高级程序设计(第5版)》 第5章

相关推荐
恋猫de小郭2 分钟前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅7 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60617 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了7 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅7 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅8 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment8 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅9 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊9 小时前
jwt介绍
前端