一、数据类型
原始值类型「值类型/基本数据类型」
number 数字 :NaN(不是有效数字) Infinity(无穷大的值)
string 字符串
boolean 布尔
null 空对象指针
undefined 未定义
symbol 唯一值
bigint 大数
对象类型「引用数据类型」
- 标准普通对象 object
- 标准特殊对象 Array、RegExp、Date、Math、Error、ArrayBuffer、DataView、Set Map……
- 非标准特殊对象 Number、String、Boolean、Symbol、BigInt…… 基于构造函数或者Object创造出来的原始值对象类型的格式信息,类型属于对象类型(Symbol和BigInt不能通过new创建)
- 可调用/执行对象「函数」function (实现了call方法)
if(NaN === NaN){
//不能基于"是否等于NaN"来检测值是否为有效数字
}
isNaN([value])//:不论[value]啥类型,默认隐式转换为数字类型 Number([value]), 再校验是否为有效数字,如果是有效数字,返回false
Object.is(NaN,NaN)//:true [不兼容IE(Edge除外)]
Symbol小示例
bigint
二、数据类型检测(typeof)
以下为常见的数据类型检测方式,目前先只针对与typeof做解释, 后面会写剩下的几种
typeof 检测数据类型
- typeof[value] :返回value所属类型的字符串,例如:”number" / “string”
- 不能检测null 返回object
- 除可调用对象
函数
会返回“function"
不论是箭头函数、还是构造函数、生成器函数以及普通函数都返回function 蹦年细分函数类型,其余的对象数据值返回的都是Object - 检测一个未被声明的变量不会报错,返回undefined
- typeof是用GetValue(val)进行检测,这是 c++内部提供的方法,按照存储的二进制进行检测的
typeof以二进制进行检测
- 对象:对象都是以000开头,null是0000,所以会检测成Object
function因为内部实现call,则会返回function - null:0000
- undefined: -2^30
- 数字:整数1 浮点数010
- 字符串:100
- 布尔:110
typeof检测数据类型还是很快的,检测原始值类型(除了null)还是很准确的
数据结构
数组结构
栈结构(先进后出),进栈和出栈都是在同一端操作
class Stack {
// => this.container=[];
container = [];
enter(item) {
// 进栈
this.container.push(item);
}
leave() {
// 出栈
return this.container.pop();
}
size() {
// 长度
return this.container.length;
}
value() {
// 内容
return this.container.slice(0);
}
}
let sk1 = new Stack;
sk1.enter(10);
sk1.enter(20);
sk1.enter(30);
console.log(sk1.leave())
最大进制和最小进制分别是36和2
在js中写的数字,浏览器一般都认为是10进制
如果是按照0x开始,浏览器会识别这是一个16进制的值,然后把其变为10进制结果 0x100=>256
如果是数字以0开始,浏览器会识别这是一个8进制的值,然后把其变为10进制结果012=>10
小练习: 把十进制转化为二进制
- 10.toString(2) //toString是Number原型上的方法
- 自己实现在Number的原型上添加一个的方法
Number.prototype.decimal2binary = function decimal2binary() {
// this->new Number(28) decimal->28
let decimal = +this;
if (/\./.test(decimal)) {
// 包含小数
throw new RangeError('处理的数字必须是整数');
}
// 整数
let sk = new Stack;
if (decimal === 0) return '0';
while (decimal > 0) {
sk.enter(decimal % 2);
decimal = Math.floor(decimal / 2);
}
return sk.value().reverse().join('');
};
let num = 28;
console.log(num.toString(2));
console.log(num.decimal2binary());
队列结构:先进先出、后进后出「从一端进,但是需要从另外一端出」 => EventLoop 涉及优先级队列
class Queue {
container = [];
// 从顶端进入队列
enter(item) {
this.container.unshift(item);
}
// 从底端出队列
leave() {
return this.container.pop();
}
// 长度
size() {
return this.container.length;
}
// 内容
value() {
return this.container.slice(0);
}
}
小练习:击鼓传花
N个人一起玩游戏,围成一圈,从1开始数数,数到M的人自动淘汰;最后剩下的人会取得胜利,问最后剩下的是原来的哪一位?
// + n参与的人数 >=1
// + m被淘汰的数字
const game = function game(n, m) {
// 让参与的人依次进入队列
let qe = new Queue;
for (let i = 1; i <= n; i++) {
qe.enter(i);
}
// 只要队列中还存在两个及两个以上的人,则重复这个逻辑
while (qe.size() > 1) {
for (let i = 1; i < m; i++) {
// 前m-1个人,出队列后立即进入队列
qe.enter(qe.leave());
}
// 数到m的人直接出队列被淘汰了
qe.leave();
}
return qe.value()[0];
};
console.log(game(8, 5));
数据类型转换
Number
把对象转换为数字:
+ 先调用对象的 Symbol.toPrimitive 这个方法,如果不存在这个方法
+ 再调用对象的 valueOf 获取原始值,如果获取的值不是原始值
+ 再调用对象的 toString 把其变为字符串
+ 最后再把字符串基于Number方法转换为数字
小练习
let arr = [27.2, 0, '0013', '14px', 123];
arr = arr.map(parseInt);//[NaN,NaN,1,1,27]
String
把对象obj转换为字符串
- String(obj):Symbol.toPrimitive -> valueOf -> toString 浏览器默认隐式转换用的是String(obj)
- obj.toString() :直接调用这个方法转字符串,不会在执行以上的规则