首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

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

  • 25-04-17 17:01
  • 4286
  • 10996
juejin.cn

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

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


一、基本定义与存储方式

  1. 原始值(Primitive Values)

    • 类型:包括字符串(String)、数字(Number)、布尔值(Boolean)、null、undefined、Symbol、BigInt1。
    • 存储方式:直接存储在栈内存中,占用固定大小空间。例如一个数字或字符串直接保存其实际值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") 会创建一个 字符串包装对象,内部存储字符串的字符序列和一个固定属性 length4。

  • 键(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字符索引和 length4
实际值false(需用 valueOf())"text"(通过 valueOf())
行为差异逻辑运算中视为 true3字符和长度可直接访问4

目录:总目录 上篇文章:第三讲: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章 ↩

注:本文转载自juejin.cn的kovli的文章"https://juejin.cn/post/7490876486291947546"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top