在 JavaScript 学习的道路上,理解数据类型及其操作是打好基础的关键。本文将结合实际代码示例,带你深入了解 JavaScript 中的基本数据类型、对象、数组等常用概念及操作方法。
一、原始数据类型/简单类型
JavaScript 中有多种基本数据类型,包括字符串、数字、布尔值、undefined、null、Symbol 和 BigInt,我们通过代码示例来逐一认识它们。
1. 字符串(String)
字符串用于表示文本数据,我们可以使用模板字符串轻松拼接变量:
let myname = '小橘';
// let str = 'Hello I am ' + myname // 字符串
let str = `Hello I am ${myname}`; // 往字符串中拼接一个变量
console.log(str); // 输出:Hello I am 小橘
模板字符串使用反引号包裹,通过 ${变量名} 语法可以方便地嵌入变量。
2. 数字(Number)
数字类型包括整数和浮点数,但需要注意字符串与数字拼接的特殊性:
let num = 123;
let count = 234;
console.log(num + count);//做加法,357
let num = '12a3'; // 这是字符串类型,不是数字
let count = 234.123; // 数字类型
console.log(num + count); // 输出:12a3234.123(字符串拼接)
当字符串与数字使用 + 操作时,会进行字符串拼接而非算术运算。
3. 布尔值(Boolean)
布尔值只有 true 和 false 两个值,常用于条件判断:
let flag = true; // 布尔类型 true
let unFlag = false; // 布尔类型 false
if (1) {
console.log('真'); // 输出:真(非 0 数字会被视为真)
} else {
console.log('假');
}
在条件判断中,非 0 数字、非空字符串等会被转换为 true,0、null、undefined 等会被转换为 false。
4. undefined 与 null
-
undefined表示变量已声明但未赋值 -
null表示一个空值
let u = undefined; // undefined
let n = null; // null
5. Symbol(定义一个独一无二的值)
Symbol 是 ES6 新增的类型,用于创建唯一标识符,即使描述相同,Symbol 实例也不相等:
let s = Symbol(123);
let t = Symbol(123);
console.log(s == t); // 输出:false
6. BigInt
BigInt 用于表示超出 Number 类型范围的大整数,通过在数字后加 n 定义:
let big = 123n; // bigint 类型
引用类型/复杂类型(数组、对象、函数)
二、数组(Array)操作
数组是用于存储多个值的有序集合,JavaScript 提供了丰富的数组操作方法。
1. 数组的创建与访问
let arr = [1, 'a', true, undefined, null]; // 创建包含多种类型元素的数组
console.log(arr[1]); // 访问索引为 1 的元素,输出:a
2. 常用数组方法
-
push():尾部加 -
pop():尾部删 -
unshift():头部加 -
shift():头部删 -
splice():添加、删除或替换数组元素
let arr = [1, 'a', true, undefined, null];
// arr.push(123n); // 末尾添加元素
// arr.pop(); // 删除最后一个元素
// arr.unshift(Symbol(100)); // 开头添加元素
// arr.shift(); // 删除第一个元素
// arr.splice(2, 1)//删除索引2的元素
arr.splice(4, 0, 123n); // 在索引 4 处插入 123n,不删除元素
console.log(arr); // 输出:[1, 'a', true, undefined, 123n, null]
splice(index, deleteCount, item1, item2, ...) 第一个参数是起始索引,第二个参数是要删除的元素数量,后续参数是要添加的元素。
三、对象(Object)操作
对象是键值对的集合,用于存储复杂数据,对象的属性可以动态修改和删除。
1. 对象的创建与修改
let obj = {
name: '男模',
age: 18,
};
// 修改属性值
obj.age = 20;//存在age,只能修改age的值
obj.girlFirend = '章若楠';//没有girlFirend,所以添加键值对
2. 删除对象属性
使用 delete 关键字可以删除对象的属性:
delete obj.girlFirend; // 删除 girlFirend 属性
console.log(obj); // 输出:{ name: '男模', age: 18 }
3. 对象的嵌套
对象可以嵌套,形成复杂的数据结构:
var obj = {
name: '铖哥',
age: 18,
like: {
n: '篮球' // 嵌套对象
}
};
四、函数(Function)基础
函数是执行特定任务的代码块,在 JavaScript 中可以像变量一样被赋值和使用。
// 函数表达式定义函数
let fn = function() {};
// 调用函数
fn();
除了函数表达式,还可以使用 function 声明语句定义函数(如注释中的 function fn() {})。
五、 在 v8 眼里数据的存储
- 原始类型的值存在 调用栈中
- 引用类型的值,因为有可能非常大,所以存在堆中,再将堆中的引用地址存在栈中
Maximum call stack size exceeded(爆栈):
function a() {
a()
}
a()
接下来,我们就用上面的原理,进行画图解释:
调用栈是用来管理函数调用执行上下文的结构,它的容量是有限的。在这段代码中,函数 a 内部又调用了自身(即递归调用),且没有终止条件。
当执行 a() 时,会不断地创建 a 函数的执行上下文并压入调用栈。由于每次调用都没有退出,调用栈中的执行上下文会持续堆积,直到超过调用栈的最大容量,就会触发 “爆栈” 错误。
简单来说,就是无终止的递归调用把调用栈 “撑满” 了,导致引擎无法再处理新的调用,从而抛出这个错误。
var obj = {
name: '铖哥',
age: 18,
like: {
n: '篮球' // 嵌套对象
}
};
爆栈 error 揭示了调用栈容量有限的特性。这也解释了为何引用类型要特殊存储:
将引用类型的实际数据存放在容量更大的堆内存中,而调用栈里只保留一个指向堆中数据的引用地址(类似指针)。这样一来,无论对象多复杂、数组多长,栈中只需要存储一个轻量的地址(通常是固定大小的内存块),既避免了大块数据占用宝贵的栈空间,又通过栈地址实现了对堆数据的快速访问。
总结
本文介绍了 JavaScript 中的基本数据类型(字符串、数字、布尔值等)、数组操作(增删改查)、对象操作(属性修改与删除)、函数基础以及原始类型和引用类型的数据存储。掌握这些基础知识是进行 JavaScript 开发的前提,后续可以在此基础上学习更复杂的概念和用法。