JavaScript 第十三章(原始值与对象的深度剖析)

在JavaScript的世界里,数据类型可以分为两大阵营:原始值和对象。这两者之间的区别不仅仅是理论上的细微差别,它们在实际编程中有着非常具体且重要的影响。

原始值,包括undefined、null、布尔值、数值和字符串,是基础的数据类型。它们的共同特点是不可变性。这意味着一旦一个原始值被创建,你无法改变这个值。对于数值和布尔值,这个概念相对直观。但是,当我们看到字符串时,直觉可能会告诉我们,字符串应该可以像操作数组那样,通过索引修改其中的字符。然而,JavaScript中的字符串是不可变的。任何看似在修改字符串的操作,实际上都是在创建一个新的字符串。例如,当你尝试修改一个字符串时,实际上你是在创建一个新的字符串,而不是修改原始字符串。

javascript 复制代码
let car = "car";
console.log(car); // car
car.toUpperCase();
console.log(car); // car 依然是小写,因为原始字符串不可变
car[0] = "b";
console.log(car); // car 依然是原来的值

// 但我们可以将变量重新赋值为一个新的字符串
car = car.toUpperCase();
console.log(car); // CAR

原始值的比较是基于它们的值的。这意味着,只有当两个原始值的内容完全一致时,它们才被认为是相等的。这个规则适用于所有原始数据类型,包括那些看起来有些抽象的类型,如null和undefined。

另一方面,对象(包括数组和函数)是可变的。你可以随时添加、修改或删除对象的属性。对象的这种可变性带来了灵活性,但同时也引入了复杂性。对象的比较是基于它们的引用而不是值。即使两个对象包含着完全相同的属性和值,只要它们不是同一个对象的引用,它们就是不相等的。

javascript 复制代码
let cars = ["bmw", "toyota"];
console.log(cars); // ["bmw", "toyota"]
cars.push("tesla");
console.log(cars); // ["bmw", "toyota", "tesla"]

let car = { brand: "tesla" };
car.year = 2021;
console.log(car); // { brand: "tesla", year: 2021 }

在JavaScript中,对象是通过引用传递的。这意味着当你将一个对象赋值给另一个变量时,你只是在复制这个对象的引用,而非对象本身。这就解释了为什么修改一个对象的属性会影响到所有引用了这个对象的变量。如果你需要一个对象的副本,而非引用,你必须手动复制每一个属性。

javascript 复制代码
let car = "tesla";
let newCar = car;
car = "audi";
console.log(car); // audi
console.log(newCar); // tesla

let cars = ["tesla"];
let newCars = cars;
cars.push("audi");
console.log(cars); // ["tesla", "audi"]
console.log(newCars); // ["tesla", "audi"] 因为两个变量引用同一个数组

在实际应用中,这些差异意味着开发者在处理原始值和对象时需要采用不同的策略。例如,当比较两个对象或数组时,不能简单地使用等号(=====),因为这只会比较引用。相反,你需要进行深度比较,即逐一比较对象的属性或数组的元素。

javascript 复制代码
let year = 2021;
let newYear = 2021;
console.log(year === newYear); // true

let cars = ["tesla"];
let otherCars = ["tesla"];
console.log(cars === otherCars); // false 因为它们引用不同的数组对象

当你将原始值或对象作为参数传递给函数时,对于原始值,其值被复制到函数的参数中;对于对象,其引用被复制。

javascript 复制代码
let year = 2021;
function getYearWithoutCovid(freeYear) {
    freeYear = 2022;
    return freeYear;
}
const newYear = getYearWithoutCovid(year);
console.log(year); // 2021
console.log(newYear); // 2022

let person = { name: "Paul", status: "unemployed" };
function getAJob(personObject) {
    personObject.status = "employed";
    return personObject;
}
const newPerson = getAJob(person);
console.log(person); // { name: "Paul", status: "employed" }
console.log(newPerson); // { name: "Paul", status: "employed" }

理解原始值和对象之间的这些关键差异,对于编写可靠和高效的JavaScript代码至关重要。它不仅影响到变量的赋值和比较,还涉及到内存管理和性能优化。掌握这些概念,将帮助你更深入地理解JavaScript这门语言的核心机制。

相关推荐
子兮曰1 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万1 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝1 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄1 天前
JavaScript 隐式全局变量解析
javascript
汉堡大王95272 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大2 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师2 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端