JS中基本数据类型有哪几种?null 是对象吗?基本数据类型和复杂数据类型有什么区别?

498 阅读3分钟

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 值也可以转为布尔值,但是不能转为数值。

整理自己学到的,放到纸上太容易丢了,虽然已经在脑子里,但难免会忘一些。>,<