简单数据类型种类
JavaScript中有7种简单数据类型(也称原始数据类型):
Undefined、Null、Boolean、Number、String 、BigInt和Symbol。接下来一一介绍。typeof操作符
typeof在正常情况下有8种返回结果:
- "undefined"表示值未定义;
- "boolean"表示值为布尔值;
- "string"表示值为字符串;
- "number"表示值为数值;
- "object"表示值为对象(而不是函数)或 null;
- "function"表示值为函数;
- "symbol"表示值为符号;
- "bigint"表示值为大整数。
特性:调用typeof null返回的结果是“object”是因为特殊值null被认为是一个对空对象的的引用,而我们大多数情况下都是这么使用的。严格来讲函数应当是object,可是函数也有自己特殊的属性。为此有必要通过typeof来区分两者
Undefined 类型
当生命一个字面量时,引擎给他赋的默认值就是undefined,我们也可以自己赋值undefined。当使用 var 或 let 声明了变量但没有初始化时,就相当于给变量赋予了 undefined 值。
特性:一个从未声明的变量与一个已经声明但从未赋值的变量通过typeof操作符的结果是一样的,这就让人会有误解,所以建议变量声明时就赋值,避免上面的结果产生。
Null 类型
null只有一个值:null。逻辑上讲,null 值表示一个空对象指针,这也是给typeof 传一个 null 会返回"object"的原因。由于上面的undefined是由null派生而来。所以js解析时将它们定义为表面相等
console.log(null == undefined); // true
注:即使是这样我也永远不建议用==null来用作条件判断,因为上面两个之所以会相等是因为在==时js同时对两个值进行了隐式转换的,这将损耗浏览器的性能 建议:if(x === null || x === undefined)来判断。
Boolean 类型
Boolean有两个字面值:true 和 false。 虽然布尔值只有两个,但所有其他js类型的值都有相应的布尔值的等价。注意是所有! 要将一个其他类型的值转换为布尔值,可以调用特定的 Boolean()转型函数:
let a = 'str';
let b = Boolean(a); // true
下面的特性表需要熟记!不必去找原理!因为这已经是最底层的规则。
| 数据类型 | 转换为tue的值 | 转换为false的值 |
|---|---|---|
| Boolean | true | false |
| String | 非空字符串 | ""(空字符串) |
| Number | 非零数值(包括无穷值) | 0、NaN |
| Object | 任意对象 | null |
| Undefined | - | undefined |
Number类型
顾名思义表示数字,不过它不仅仅能表示十进制,其余的也能表示。 整数也可以用八进制(以 8 为基数)或十六进制(以 16 为基数)字面量表示。对于八进制字面量, 第一个数字必须是零(0),然后是相应的八进制数字(数值 0~7)。如果字面量中包含的数字超出了应 有的范围,就会忽略前缀的零,后面的数字序列会被当成十进制数。
数据处理的一些方法:
Math.abs(item)//绝对值
console.log(Math.max(1, 2, 3, 4)); // 4
console.log(Math.min(1, 2, 3, 4, 5)); // 1
// 保证最大值为1时
Math.min(1,x);
// 保证最小值为1时
Math.max(1,x);
// 求随机数
const randomFn = (min, max) => {
for (let i = 0; i < 100; i++) {
let res = Math.floor(Math.floor(Math.random() * (max - min + 1))) + min; //右区间闭合时需要+1,否则不需要
console.log("random", res);
}
};
// Math.floor 求接近象限内靠左的整数
Math.floor(-1.4)// -2
// Math.ceil 求接近象限内靠右的整数
Math.floor(-1.4)// -1
值的范围 由于内存的限制,Number 并不支持表示这个世界上的所有数值。Number 可以表示的最小 数值保存在 Number.MIN_VALUE 中,这个值在多数浏览器中是 5e324;可以表示的最大数值保存在 Number.MAX_VALUE 中,这个值在多数浏览器中是 1.797 693 134 862 315 7e+308。如果某个计算得到的 数值结果超出了 Number 可以表示的范围,那么这个数值会被自动转换为一个特殊的 Infinity(无 穷)值。任何无法表示的负数以-Infinity(负无穷大)表示,任何无法表示的正数以 Infinity(正 无穷大)表示。
特性: 有一个特殊的数值叫 NaN,意思是“不是数值”(Not a Number),用于表示本来要返回数值的操作 失败了(而不是抛出错误)。比如,用 0 除任意数值在其他语言中通常都会导致错误,从而中止代码执 行。但在 ECMAScript 中,0、+0 或0 相除会返回 NaN: console.log(0/0); // NaN console.log(-0/+0); // NaN 如果分子是非 0 值,分母是有符号 0 或无符号 0,则会返回 Infinity 或-Infinity: console.log(5/0); // Infinity console.log(5/-0); // -Infinity 需要注意NaN===Nan返回的是false,想要判断一个数是否是NaN得用isNaN(x)加上typeof x === 'number'(因为字符串放到isNaN也是true) 数值转换:
- 布尔值,true 转换为 1,false 转换为 0。
- 数值,直接返回。
- null,返回 0。
- undefined,返回 NaN。
String 类型
String(字符串)数据类型表示零或多个 16 位 Unicode 字符序列。字符串可以使用双引号(")、
单引号(')或反引号(`)标示,因此下面的代码都是合法的:
let firstName = "John";
let lastName = 'Jacob';
let lastName = `Jingleheimerschmidt`
特点: ECMAScript 中的字符串是不可变的(immutable),意思是一旦创建,它们的值就不能变了。要修改 某个变量中的字符串值,必须先销毁原始的字符串。
方法:
- charAt(index):返回指定位置的字符
- charCodeAt(index):返回指定位置字符的 Unicode 编码
- concat(str1, str2, ...):拼接字符串
- includes(substring):判断是否包含子串
- indexOf(substring):返回子串首次出现的位置
- slice(start, end):截取字符串
- substring(start, end):截取字符串 :在计算时间时补0很有用
- substr(start, length):截取字符串(已废弃)
- replace(regexp, newStr):替换字符串
- split(separator):分割字符串为数组
- toUpperCase() / toLowerCase():大小写转换
- trim():去除首尾空格
- startsWith(str) / endsWith(str):判断开头/结尾
例子:取YYYY-MM-DD的日期:
function getCurrentDate() {
const date = new Date();
let year = date.getFullYear()
let month = '0' + (date.getMonth() + 1)
let day = '0' + date.getDate()
month = month.substring(month.length - 2);
day = day.substring(day.length - 2);
return `${year}-${month}-${day}`
}
Symbol 类型
Symbol(符号)是 ECMAScript 6 新增的数据类型。符号是原始值,且符号实例是唯一、不可变的。 可以理解为new Symbol产生一个实例,实例为一个永远不可见的永不重复的密码串,所以这个数据类型最适合用于的对象的键,用来确保对象属性使用唯一标识符。
let sym = Symbol();
console.log(typeof sym); // symbol
let genericSymbol = Symbol();
let otherGenericSymbol = Symbol();
let fooSymbol = Symbol('foo');
let otherFooSymbol = Symbol('foo');
console.log(genericSymbol == otherGenericSymbol); // false
console.log(fooSymbol == otherFooSymbol); // false
传入字符串或数字可以作为描述符,但不能通过描述符反向获取Symbol的值。 要重复使用一个符号的值,普通的new行不通,得使用Symbol的静态防范的for。
let fooGlobalSymbol = Symbol.for('foo'); // 创建新符号
let otherFooGlobalSymbol = Symbol.for('foo'); // 重用已有符号
console.log(fooGlobalSymbol === otherFooGlobalSymbol); // true
// 创建全局符号
let s = Symbol.for('foo');
console.log(Symbol.keyFor(s)); // foo,用来查询描述
Object:数组类型以及方法
- push(item) :在数组末尾添加元素
- pop() :移除并返回数组最后一个元素
- shift() :移除并返回数组第一个元素
- unshift(item) :在数组开头添加元素
- concat(arr1, arr2, ...) :合并数组,返回新数组
- join(separator) :将数组元素拼接成字符串
- slice(start, end) :截取数组的一部分,返回新数组
- splice(start, deleteCount, ...items) :删除/插入/替换数组元素
- forEach(callback) :遍历数组,每个元素执行回调
- map(callback) :返回新数组,每个元素执行回调
- filter(callback) :返回新数组,保留满足条件的元素
- reduce(callback, initialValue) :累计处理数组元素,返回最终结果
- find(callback) :返回第一个满足条件的元素
- findIndex(callback) :返回第一个满足条件元素的索引
- some(callback) :判断是否有元素满足条件
- every(callback) :判断是否所有元素都满足条件
- sort(compareFunction) :对数组进行排序
- reverse() :反转数组顺序
- includes(item) :判断数组是否包含某元素
- indexOf(item) :返回元素首次出现的索引
- lastIndexOf(item) :返回元素最后一次出现的索引 应用:
// 手写一个深拷贝,思路:简单类型直接返回,复杂数据类型循环递归
const deepClone = (obj) => {
if (obj === null || typeof obj !== 'object') {
return obj
}
if (obj instanceof Date) {
return new Date(obj)
}
if (Array.isArray(obj)) {
return obj.map(item => {
return deepClone(item)
})
}
let res = {}
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
res[i] = deepClone(obj[i])
}
}
return res
}
如何判断各个数据类型:
// 辨别常见的数据类型
const getType = (val) => {
if (val === null) {
return 'null';
}
if (val === undefined) {
return 'undefined';
}
if (typeof val === 'number') {
if (isNaN(val)) {
return 'NaN';
} else {
return 'number'
}
}
if (Array.isArray(val)) {
return 'array'
}
if (typeof val === 'function') { return 'function' }
if (typeof val === 'object') { return 'object' }
if (typeof val === 'string') { return 'string' }
if (typeof val === 'boolean') { return 'boolean' }
if (typeof val === 'symbol') { return 'symbol' }
if (typeof val === 'bigint') { return 'bigint' }
return 'unknown' //除非js新版本,否则不会是unknown
}