快速掌握JavaScript数据类型

105 阅读4分钟

一、基本类型 vs 引用类型

1. 基本类型都有哪些

JavaScript 一共有5+2种基本数据类型,分别是:

  • undefined (未定义)
  • null (空)
  • Boolean (布尔)
  • Number (数字)
  • String (字符串)
  • Symbol (符号:独一无二的值) ES6新增
  • BigInt(任意精度格式整数)ES11新增

知识点扩充

  1. null 表示空指针对象。
  2. undefined表示为未定义,当使用var或let声明了变量但是没有初始化时,就相当于给变量赋予了undefined。JS是一门动态类型语言,成员除了表示存在的空值外,还有可能根本就不存在(因为存不存在只在运行时才知道),这就是undefined的意义所在。
  3. Boolean表示布尔值,true和false。
  4. Number表示整数或浮点数,还有一些特殊值(-Infinity负无穷、+Infinity正无穷、NaN没有数值)。
  5. String表示字符串。
  6. Symbol代表创建后独一无二且不可变的数据类型,它的出现主要是为了解决可能出现的全局变量冲突的问题。
  7. BigInt 是一种数字类型的数据,它可以表示任意精度格式的整数,使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。

2. 引用类型都有哪些

引用类型包括:

  • 对象Object(包含普通对象-Object,数组对象-Array,正则对象-RegExp,日期对象-Date,数学函数-Math,函数对象-Function)

  • 基本类型的包装类型(Boolean、Number、String)

3. 基本类型和引用类型的区别

// 值类型
let a = 100;
let b = a;
a = 200;
console.log(b); // 100

let a = null;
let b = a;  // b 复制了 a 的值(null)
a = { name: "obj" }; // 修改 a 不影响 b
console.log(b); // null(值类型独立)
// 引用类型
let a = {
  age: 200,
  name: 'nini',
};
let b = a;
b.age = 21;
console.log(a.age); // 21
  • 值类型存在栈中,引用类型存在堆中。当把a赋值给b时:

    • 值类型的赋值操作:a与b各自的值都存在于栈中,互不影响,互相独立。修改a不影响b。
    • 引用类型的赋值操作:a与b存入栈中的都是引用内存地址,相当于是同一个东西,而数据则存在堆中,通过内存地址指向堆,因此修改a也会修改b。
  • 为什么要这么设计?性能的原因。值类型占用的空间比较小,引用类型一般较大。内存的空间和CPU计算的耗时等方面考虑,将值类型与引用类型做了区分。

4, 如何判断类型

(1)typeof 操作符

作用有三个:

  • 识别所有值类型
  • 能判断函数
  • 能识别引用类型(不能再继续识别)
// 识别所有值类型 (这里不包括null)
let a;                     typeof a // 'undefined'
const str = 'abc';         typeof str // 'string'
const n = 100;             typeof n  // 'number'
const b = true;            typeof b  // 'boolean'
const s = Symbol('s');     typeof s  // 'symbol'

// 能识别函数
typeof function () {}  // 'function'
typeof console.log // 'function'

// 能识别引用类型,但是不能继续识别下去了
typeof null    // 'object'  JS初版就流传下来的bug,后面由于修改会造成大量的兼容问题就一直没有被修复
typeof ['a','b']  // 'object'
typeof { x: 100 }  // 'object'

(2)instanceof 操作符

  • instanceof 操作符可以帮助我们判断引用类型具体是什么类型的对象
  • 使用instanceof不能检测基本数据类型,因为不是对象
[] instanceof Array  // true
new Date() instanceof Date  // true
new RegExp() instanceof RegExp  // true

(3)toString

  • 通过Object原型中的toString方法来判断数据类型
var obj = {};  obj.toString() // "[object Object]"
  • 上面代码调用空对象的toString方法,结果返回一个字符串[object Object],其中第二个Object表示该值的构造函数。这是一个十分有用的判断数据类型的方法。
  • 由于实例对象可能会自定义toString方法,覆盖掉Object.prototype.toString方法,所以为了得到类型字符串,最好直接使用Object.prototype.toString方法。通过函数的call方法,可以在任意值上调用这个方法,帮助我们判断这个值的类型。
Object.prototype.toString.call(value)表示对value这个值调用Object.prototype.toString方法。
Object.prototype.toString.call(2) // "[object Number]"
Object.prototype.toString.call('') // "[object String]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(Math) // "[object Math]"
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call([]) // "[object Array]"

(4)手写一个很准确的类型判断函数

const typeJudge = () => {
  const s = Object.prototype.toString.call(o);
  return s.match(/[object (.*?)]/)[1].toLowerCase();
}

typeJudge({}); // "object"
typeJudge([]); // "array"
typeJudge(5); // "number"
typeJudge(null); // "null"
typeJudge(); // "undefined"
typeJudge(/abcd/); // "regex"
typeJudge(new Date()); // "date"

// 在上面这个typeJudge函数的基础上,还可以加上专门判断某种类型数据的方法。
['Null',
 'Undefined',
 'Object',
 'Array',
 'String',
 'Number',
 'Boolean',
 'Function',
 'RegExp'
].forEach(function (t) {
  typeJudge['is' + t] = function (o) {
    return typeJudge(o) === t.toLowerCase();
  };
});
 
typeJudge.isObject({}) // true
typeJudge.isNumber(NaN) // true
typeJudge.isRegExp(/abc/) // true