JavaScript基础提升
目录
前言
JavaScript数据类型
undefined和null
Number类型
String类型
布尔类型(boolean)
对象类型(Object)
JS数字
整数
浮点数
数字分隔符
Boolean对象和boolean
字符串
JS的原生值与引用值【非常重要】
堆栈和堆内存
复制值
其他
前言
最近研究框架,发现很多JS基础都已忘记,因此决定重刷一遍JS基础,本文不适合新手,适合已掌握JS但希望拓展JS能力,了解JS实现逻辑的开发者。
JavaScript数据类型
undefined和null
- typeof undefined:返回undefined
- typeof null:返回object(其实应该返回null,但是因为某些原因,JS官方承认这个BUG,但不会修复)
undefined和null是两种“原始数据类型”,表示:“该类型只有一个值,就是他本身”,例如undefined类型只有undefined这一个值,null类型只有null这一个值
- undefined == null:true
- undefined === null:false
Number类型
- Infinity:无穷大,大于任何数字
- -Infinity:无穷小,小于任何数字

NaN表示“Not a Number”,它是一个特殊数字值,表示无效的数字,常出现在Number类型转换失败的场景:
![]()
NaN具有两个特征:
- Number类型数据与NaN的任何运算都会返回NaN
- NaN不等于任何值,包括自己

String类型
JS里的字符串是不可变的,这意味着你对一个字符串进行拼接、删除、替换,其实都是将原字符串删除返回一个新字符串。
例如,我们可以通过索引访问字符串中的某个字符,但无法使用索引修改这个字符,这与(Python这种可以直接访问和修改)的语言有很大不同:
let str = 'abcdefg';
console.log(str[0]); // a
str[0] = 'A'; // 报错

上图报错说明无法通过索引修改字符串abcdefg
如果确实希望通过索引修改字符串中的某个字符,可以尝试下面方法:
let str = 'abcdefg';
const strList = str.split('');
strList[0] = 'A';
str = strList.join('');
console.log(str);
这种方法也并不是直接修改原字符串,而是间接的生成一个新的字符串并重新赋值
布尔类型(boolean)
boolean类型只有两个值:“true”和“false”(小写!!!)
JS允许将其他类型的值转换为true或false,转换规则如下:
| 类型 | true | false |
|---|---|---|
| string | 非空字符串 | 空字符串 |
| number | 非0数字和Infinity、-Infinity | 0,NaN |
| 对象 | 任何对象 | null |
| undefined | 无 | undefined |
任何对象(哪怕是一个空对象)都会返回true,只有null会返回false:

对象类型(Object)
对象类型不同于字符串类型,它允许原地修改,它的访问方式有“点符号”和“数字式符号”两种方式,访问不存在的属性将返回undefined:
const a = {name: "test",age: 30
}console.log(a.name); // 可以访问
console.log(a['age']) // 可以访问a.name = "changed"; // 可以修改
a['age'] = 31; // 可以修改console.log(a.name); // changed
console.log(a['age']); // 31console.log(a.parent); // undefined
console.log(a['parent']); // undefined
点符号和数字式符号最大的区别在于遍历访问时,点符号无法直接在遍历中当做索引使用:
const a = {name: "test",age: 30
}for (let key in a) {console.log("key:",key);console.log("value:",a.key);
}

正确方法是使用数字式符号:
const a = {name: "test",age: 30
}for (let key in a) {console.log("key:",key);console.log("value:",a[key]);
}

JS数字
JS使用number类型表示“整数”和“浮点数”
整数
对于整数,JS允许使用“8进制”、“10进制”、“16进制”的格式来定义数据值,但是无论使用哪种格式,JS都会将这个值转换为10进制值存储。
8进制和16进制数的表示有“ES5”和“ES6”两种,但我更推荐“ES6”,因为ES6已逐渐替代ES5,且更稳定:
// 使用0o开头定义8进制数据,后面只能跟0-7数字
console.log(0o10); // 8
console.log(0o8); // 报错,8不是8进制数字
// 使用0x或0X开头定义16进制数据,后面只能跟0-9和A-F(不区分大小写)
console.log(0x10); // 16
console.log(0x1A);
console.log(0x1G); // 报错,G不是16进制数字
浮点数
浮点数的定义至少包含:“一个小数点,以及至少一个小数点后的数字”,下面三种格式都是正确的:
let price = 9.99;
let tax = 0.08;
let discount = .05;
下面三种格式都是合法的,但不是浮点数:
let price = 9.; // 语法合法,但不是浮点数,会变成整数9
let tax = 0.; // 语法合法,但不是浮点数,会变成整数0
let discount = .0; // 语法合法,但不是浮点数,会变成整数0
当有一个非常大的数字需要表示时,可以使用e记法,e记法表示一个数字应该乘以10的某个幂:
let a = 3.14e2; // 314
let b = 2.5e-3; // 0.0025
JS还会自动将小数点后至少有6个0的浮点数转换为e记法:
let a = 0.000005; // 0.000005
let b = 0.0000003; // 3e-7
JS浮点数的精度是17位小数,因此在对浮点数进行运算时,会得到近似结果:
console.log(0.1 + 0.2);
![]()
因此直接进行与浮点数进行比较是错误的,需要搭配toFixed()控制小数点位数:
console.log(0.1 + 0.2 == 0.3); // false
console.log((0.1 + 0.2).toFixed(1)); // 0.3
console.log((0.1 + 0.2).toFixed(1) == 0.3); // true
因为toFixed返回字符串,所以使用“===”(强相等)时,仍然不会相等:
console.log((0.1 + 0.2).toFixed(1) === 0.3); // false
使用Number转换后就可以相等了:
console.log(Number((0.1 + 0.2).toFixed(1)) === 0.3); // true
数字分隔符
JS提供数字分隔符“_”(下划线)在数字组之间创建视觉分隔
例如:“10000000000”很难阅读,使用分隔符后:“1_000_000_000_0”,这样数字就浅显易懂了
Boolean对象和boolean
- boolean:JS的原生类型之一
- Boolean:原生类型boolean的包装对象
Boolean(param)可以根据param返回一个boolean,boolean的值取决于param的值
因为Boolean是一个包装对象,因此我们也可以使用new关键字创建一个Boolean对象,因为Boolean是一个对象,而boolean是一个类型值,所以两者绝对不相等,不能混淆
考虑下面这个例子:
const a = true; // boolean
const b = new Boolean(false); // Boolean object
因为b是一个Boolean对象,所以你可以向它添加一些属性:
b.name = "我是Boolean";
使用typeof分别返回:“boolean”和“object”
console.log("a", typeof a);
console.log("b", typeof b);

使用instanceof:
console.log("a", a instanceof Boolean);
console.log("b", b instanceof Boolean);

字符串
JS中非字符串转换为字符串有三种方法:
- String(n)
- "" + n
- n.toString()
对于undefined和null,toString()是无效的
JS的原生值与引用值【非常重要】
JS有两种不同类型的值:
- 原生值:数据的基本单元
- 引用值:对象引用
堆栈和堆内存
当声明一个变量时,JS引擎会在两个内存位置分配内存:“堆栈”和“堆”
静态数据被存储在堆栈中,它包括:
- 原生值:null、undefined、boolean、string、number、symbol
- 引用值:它引用对象
静态数据的内存是固定的,变量和变量值都存储在一块内存单元中,例如下面声明两个变量:
let name = 'John';
let age = 25;

动态数据的内存是动态的,对象引用(变量、对象名)存储在堆栈的一块内存单元中,对象(变量值、对象值)存储在堆中:
let name = 'John';
let age = 25;let person = {name: 'John',age: 25,
};

对象值所占内存由JS引擎自动分配,因此通常会说“person”变量是一个引用,它引用了一个对象
复制值
固定数据值的复制非常简单,JS引擎会创建一个该值的副本,并将该副本赋值给目的变量:
let age = 25;
let newAge = age;
- 第一步:JS引擎创建变量age,并将其值初始化为25
- 第二步:JS引擎创建变量newAge,发现初始化值是另一个变量,于是创建age值的副本
- 第三步:将age副本赋值给newAge

因此在堆栈中,修改一个变量不会影响另一个变量
动态数据值的复制略微复杂,JS引擎会再创建一个引用,以便两个变量都引用堆内存中同一个对象:
let person = {name: 'John',age: 25,
};let member = person;member.age = 26;console.log(person);
console.log(member);
- 第一步:声明一个person变量(引用),并初始化为一个有两个属性name和age的对象
- 第二步:声明一个member变量(引用),初始化为引用person变量所引用的对象
- 第三步:修改两者共同引用的对象的值

因此person和member都引用同一个对象,修改任意一个变量都会影响另一个变量,这也是我们常说的“浅拷贝”
其他
更多JS知识可以参考我的专栏:
JavaScript_是洋洋a的博客-CSDN博客
