1、JS的基本数据类型
- number
- string
- Boolean
- null
- undefined
- Symbol
- Bigint
2、null不是对象
从逻辑上看,null值表示一个空对象指针,这就是为什么使用typeof操作符检测null值时会返回‘object’的原因,也是JavaScript遗留下来的bug。
而真正的原因是:
JS类型值是存在32bit 单元里,为了性能考虑用低位储存了变量的类型信息,其中000表示是Object类型,而null对应机器码的NULL指针,一般全为零,所以typeof(null)为Object。要想正确判断数据的类型,不妨使用Object.prototype.toString.call()。
null instanceof Object //false
var number = 1; // [object Number]
var string = '123'; // [object String]
var boolean = true; // [object Boolean]
var und = undefined; // [object Undefined]
var nul = null; // [object Null]
var obj = {a: 1} // [object Object]
var array = [1, 2, 3]; // [object Array]
var date = new Date(); // [object Date]
var error = new Error(); // [object Error]
var reg = /a/g; // [object RegExp]
var func = function a(){}; // [object Function]
function checkType() {
for (var i = 0; i < arguments.length; i++) {
console.log(Object.prototype.toString.call(arguments[i]))
}
}
checkType(number, string, boolean, und, nul, obj, array, date, error, reg, func)
console.log(Object.prototype.toString.call(Math)); // [object Math]
console.log(Object.prototype.toString.call(JSON)); // [object JSON]
3、基本数据类型和复杂数据类型有什么区别?
内存的分配不同
-
基本数据类型 的值存储于栈中;
-
复杂数据类型 的值存储在堆中,栈中存放指向堆中的地址。
值的结构不同
-
基本数据类型 值指的是简单的数据段
-
复杂的数据类型 值是由一个或多个值构成的对象。
复制变量时不同
-
基本数据类型 拷贝时,拷贝的是值,并且原变量和拷贝后的变量是相互独立的,这两个变量可以参与任何操作而不会相互影响;
-
复杂数据类型 拷贝时,也就是所说的引用类型的值拷贝时,副本拷贝的是指针,而这个指针指向存储在堆中的一个对象。复制操作结束后,两个变量实际上引用的是同一个对象,因此,改变其中一个变量,就会影响另一个变量。
传递参数时不同
道理和拷贝一样。
-
在向参数传递基本类型的值时,被传递的值会被赋值给一个
arguments
对象中的一个元素(即局部变量); -
在向参数传递引用类型的值时,会把对应值的地址复制给一个局部变量,因此局部变量的变化会反映到函数的外部。
例如:
function test(person) {
person.age = 26
person = {
name: 'yyy',
age: 30
}
return person
}
const p1 = {
name: 'yck',
age: 25
}
const p2 = test(p1)
console.log(p1) // -> {name: "yck", age: 26}
console.log(p2) // ->{name: "yyy", age: 30}
赠一个题:
JavaScript:对象作为对象的属性名
例1:
var a = {};
b = {key:'b'};
c = {key:'c'};
a[b] = 123;
a[c] = 456;
console.log(a[b]);//456
对象的属性名只能是string类型的,因此,对象b和对象c先变成string类型,默认通过toString()的方法进行转换变成string,而不是valueOf()方法。
console.log(b.toString()); //'[object Object]'
console.log(c.toString()); //'[object Object]'
所以相当于a["[object Object]"]多次复制,最后一次赋值为最终结果。
//这个更简单的例子原理同上
var a={}, b='123', c=123;
a[b]='b';
a[c]='c';
console.log(a[b]);//c
例2:
var a={}, b=Symbol('123'), c=Symbol('123');
a[b]='b';
a[c]='c';
console.log(a[b]);//b
Symbol是一种新的原始数据类型,表示独一无二的值。Symbol 值通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
所以:
console.log(b.toString()); //"Symbol(123)"
console.log(c.toString());
//"Symbol(123)"
b.toString() === c.toString()
//false
所以控制台打印出来的是b
注意:
- Symbol函数前不能使用new命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。所以不能添加属性。它是一种类似于字符串的数据类型。
- Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
- 如果 Symbol 的参数是一个对象,就会调用该对象的toString方法,将其转为字符串,然后才生成一个 Symbol 值。
- Symbol 值作为对象属性名时,不能用点运算符。
- Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的。
- Symbol 值不能与其他类型的值进行运算,会报错。
- Symbol 值可以显式转为字符串。
- Symbol 值也可以转为布尔值,但是不能转为数值。
整理自己学到的,放到纸上太容易丢了,虽然已经在脑子里,但难免会忘一些。>,<