详细解读JS中的9大数据类型
数据类型分类
+ 基本数据类型 【7】
+ 引用数据类型 【2】
+ isNaN、NaN、Infinity
学习之前先来看一道面试题,看下这道题是否能做对。
let res = parseFloat('left:200px');
if(res===200){
alert(200);
}else if(res===NaN){
alert(NaN);
}else if(typeof res==='number'){
alert('number');
}else{
alert('Invalid Number');
}
- 基本数据类型(原始值类型):
- number NaN/Infinity
- string 单引号/双引号/反引号``
- boolean true/false
- null
- undefined
- symbol 创建唯一值【比较重要】
- bigint 【了解即可】
- 引用数据类型:
- object
- {} 普通对象
- [] 数组对象
- /^ [+ -]?(?:\d|(?:[1-9]\d+))(.\d+)?$/ 正则对象
- 日期对象
- 数学对象
- …
- function
- object
typeof 是按照二进制的底层机制来检测数据类型的,默认以000开头的都是对象,而null全是0,所以把null看作对象数据类型。
结合代码详解上述知识点:
- Number数据类型中的特殊点–NaN:not a number 不是一个有效数字,但是它属于number数据类型的
//NaN是数字类型,不是有效数字
console.log(typeof NaN); //=>"number"
//NaN和任何值都不相等,包括它自己
console.log(NaN == NaN); //=>false
//想要判断一个值是否为NaN,用方法isNaN([val])
let n = 10;
if (isNaN(n)) {
// 条件成立:证明它真的是非有效数字
}
//Object.is([val1],[val2]):检测两个值是否相等
console.log(Object.is(NaN, NaN)); //=>true
Object.is([val1],[val2]):检测两个值是否相等,返回一个 Boolean 类型标示两个参数是否是同一个值。
Object.is() 方法判断两个值是否为同一个值。如果满足以下条件则两个值相等:
- 都是 undefined
- 都是 null
- 都是 true 或 false
- 都是相同长度的字符串且相同字符按相同顺序排列
- 都是相同对象(意味着每个对象有同一个引用)
- 都是数字且
—— 都是 +0
—— 都是 -0
—— 都是 NaN
—— 或都是非零而且非 NaN 且为同一个值与== 运算不同。 == 运算符在判断相等前对两边的变量(如果它们不是同一类型) 进行强制转换 (这种行为的结果会将 “” == false 判断为 true), 而 Object.is不会强制转换两边的值。
与=== 运算也不相同。 === 运算符 (也包括 == 运算符) 将数字 -0 和 +0 视为相等 ,而将Number.NaN 与NaN视为不相等.
- 唯一值Symbol
let val = Symbol('00');
console.log(val == val); //=>true
console.log(Symbol('AA') == Symbol('AA')); //=>false
let a = NaN;
console.log(a == a); //=>false
- BigInt
JS中超过这个最大安全数之后再计算就不准确了,如下图:
Number.MAX_SAFE_INTEGER;//=>9007199254740991
JS中的最大安全数,超过这个值的,需要用bigint处理(在一个数值后面加n就是bigint类型)
现在来看下最开始的面试题,相信你一定得出正确答案了,就是【‘number’】。
JS底层运行机制之堆(Heap)栈(Stack)
- ECStack(Execution [ˌeksɪˈkjuːʃn] Context Stack)和 EC(Execution Context )
- GO(Global Object)
- VO(Varibale Object)
- 变量赋值的步骤
首先思考下:数据类型为啥分成两大类型,两种类型有啥区别?
先来看一道面试题,由此题来引申出思考题的答案
var a = 12;
var b = a;
b = 13;
console.log(a); //12
var a = {
n: 12
};
var b = a;
b.n = 13;
console.log(a.n);
var a = {
n: 12
};
var b = a;
b = {
n: 13
};
console.log(a.n);
图解一:
var a = 12;
var b = a;
b = 13;
console.log(a); //12
图解二:
var a = {
n: 12
};
var b = a;
b.n = 13;
console.log(a.n);
图解三:
var a = 12;
var b = a;
b = 13;
console.log(a); //12
-
第一:JS代码可以运行的环境:
- 浏览器(引擎/内核)
- node.js
- webview
- …
-
第二:浏览器之所以能够运行代码,是因为提供了-个供代码运行的环境,即栈内存 ECStack(Execution Context Stack),栈内存就是在计算机中分配出来的一块内存
-
第三:代码执行分为:全局代码、函数中代码、私有块中的代码…
不同环境下的代码执行的时候都有自己的上下文(环境)——EC(Execution Context)执行上下文 -
第四:当前环境上下文形成后会有一个进栈的过程【JS代码在浏览器中运行,首先浏览器开辟一个栈内存即 ESCStack执行环境栈;全局代码在运行前先形成自己的EC即执行上下文,这个执行上下文形成后会有一个进栈过程即进入浏览器分配的这块内存[ECStack:执行环境栈],函数执行的时候同理】
-
第五:代码在当前上下文中执行的时候,创建的变量总会存储在当前上下文中指定的变量对象[VO (Varibale Object)]中,所以变量对象就是用来存储当前上下文中创建的变量的。
-
第六:代码执行之前先进行变量提升/词法解析……
-
第七:等号赋值的详细过程:var a=12;.
- 创建一个值12,把它存储起来(基本类型值是直接存储在栈内存中的)
- 声明一个变量,把它存储到当前上下文所属的变量对象中.
- 最后进行等号赋值(定义) :本质也是一个指针指向的过程
var a;声明变量,但是在变量提升阶段并没有赋值,所以是未定义,默认值是undefined。等号每次赋值都会重新创建一个值。
- 第八:如果是引用数据类型的值:
- 不会直接存储在栈内存中,他会开辟一个堆内存(也是计算机内存中分配的一个空间),用来存储自己的键值对,每一个堆内存都有一个16进制的地址
- 在堆内存中分别存储键值对
- 把16进制的地址放到栈中,供变量调用
【基本数据类型是按值操作[在栈内存中],引用数据类型都是按照地址来操作[堆内存中]】
- 连等赋值:a=b=10;=>[先b=10;再a=10]连等赋值一般以右侧先运算[连等赋值只创建一次10],但是某些操作的优先级很高,比如a.x成员访问,它的优先级是19,比等号赋值高很多,所以优先计算它a.x=10;
最后一起来看几道相关练习题:
- 第一题
//example 1
var a={}, b='0', c=0;
a[b]='你好';
a[c]='世界';
console.log(a[b]);
---------------------
//example 2
var a={}, b=Symbol('1'), c=Symbol('1');
a[b]='你好';
a[c]='世界';
console.log(a[b]);
---------------------
//example 3
var a={}, b={n:'1'}, c={m:'2'};
a[b]='你好';
a[c]='世界';
console.log(a[b]);
- 第二题
var a = {n: 1};
var b = a;
a.x = a = {n: 2};
console.log(a.x);
console.log(b);
- 第三题
var x = [12, 23];
function fn(y) {
y[0] = 100;
y = [100];
y[1] = 200;
console.log(y);
}
fn(x);
console.log(x);