JavaScript 数据类型

366 阅读4分钟

一、基本(原始)数据类型

JavaScript目前有6种基本数据类型:numberstringbooleanundefinednullsymbol(ES6新增)。

基本数据类型保存在栈内存中,因为基本数据类型占用空间小、大小固定,通过按值来访问,属于被频繁使用的数据。

二、引用(复杂)数据类型

常见的引用数据类型有:ObjectArrayFunctionDateRegExp

引用数据类型存储在堆内存中,因为引用数据类型占据空间大、占用内存不固定。 如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体

三、两种数据存储方式的不同


基本数据类型存在栈里,引用数据类型在栈里存地址,而在堆里存内容,如果定义数组m与数组n相等,表示地址相同,所以m与n的指针指向同一个内容,改变其中任意一个的内容,m与n都会改变。

四、栈内存和堆内存?

JavaScript的内存分为栈内存(stack)和堆内存(heap)

  • 栈内存:是一种特殊的线性表,它具有后进先出的特性,存放基本类型。
  • 堆内存:存放引用类型(在栈内存中存一个基本类型值保存对象在堆内存中的地址,用于引用这个对象)。

五、隐式转换

在JavaScript,当运算符在运算的时候,如果两边数据类型不统一,就无法直接计算,编译器会对运算符两边的数据做一个数据类型转换,转成相同的数据类型再计算。

1. +和-

巧用 + 和 - 规则转换类型:

  • 把变量转换成数字: numStr - 0;
  • 把变量转换成字符串: numStr + '';

2. a == b

类型相同,等同于 ===;
类型不同,尝试类型转换后比较:

null == undefined; // true
null === undefined; // false
// number == string; => string转number
1 == '1.0' // true
// boolean == ?; => 转number
1 == true // true
0 == fasle // true
'abc' == true // false => Number('abc') == NaN
// Obejct == number | string;尝试将对象转换为基本类型
new String('abc') == 'abc' // true
// 特殊的
NaN == NaN; // false

3. a===b

类型不同,返回false;
类型相同:

null === null; // true
undefined === undefined; // true
NaN === NaN; // false
new Object() ≠ new Object()

4. 布尔值为false的6种情况

undefined, null, false, 0, NaN, ""

六、包装对象

基本类型中的number,string,boolean都有对应的包装类型。

let str = 'abcde';
console.log(str.length); // 5
str.name = 233;
console.log(str.name); // undefined

把一个基本类型尝试用对象的方式使用它的时候,比如访问 length 属性,或者增加一些属性的操作时,JavaScript 会把这些基本类型转化为对应的包装类型对象。完成这样一个访问比如 str.length 返回以后或者 str.name 设置了以后,这个临时对象会被销毁掉。所以 str.name 赋值233以后,再去输出 str.name 的值是undefined。

七、类型检测

JavaScript 中检测类型的方法有很多:

  • typeof
  • instanceof
  • Object.prototype.toString
  • constructor

1. typeof

typeof 100; // "number"
typeof true; // "boolean"
typeof 'abc'; // "string"
typeof undefined; // "undefined"
typeof null; // "object"
typeof NaN; // "number"
typeof [1,2,3]; // "object"
typeof date; // "object"
typeof function; // "function"

比较特殊的是typeof null返回“object”。
历史原因,规范尝试修改typeof null返回“null”修改完大量网站无法访问,为了兼容,或者说历史原因返回"object"。
typeof对 基本类型 和 函数对象 很方便,但是其他类型就没办法了。
判断一个对象是不是数组?用typeof返回“object”。因此对对象的判断常用到的是instanceof。

2.instanceof

基于原型链操作。obj instanceof Object。
左操作数为对象,不是就返回false,右操作数必须是函数对象或者函数构造器,不是就返回typeError异常。
原理:判断左边的左操作数的对象的原型链上是否有右边这个构造函数的prototype属性。

任何一个构造函数都有一个prototype对象属性,这个对象属性将用作new出来的对象的原型(_proto_)。

3.Objetc.prototype.toString

Object.prototype.toString.call(null); 	// "[object Null]"
Object.prototype.toString.call(undefined);// "[object Undefined]"
Object.prototype.toString.call(“abc”);	// "[object String]"
Object.prototype.toString.call(123);	// "[object Number]"
Object.prototype.toString.call(true);	// "[object Boolean]"
Object.prototype.toString.call([]);	// "[object Array]"
Object.prototype.toString.call(function(){});// "[object Function]"
Object.prototype.toString.call(person); // 自定义类型 "[object Object]"

4.constructor

任何对象都有constructor属性,继承自原型的,constructor会指向构造这个对象的构造器或者构造函数。(constructor可以被改写,所以使用要小心。)

5.类型检测小结

  • typeof:适用于检测基本类型及function,遇到null失效
  • 对象:通过Object.prototype.toString检测,适合内置对象和基元类型
  • instanceof:适合自定义对象,也可以用来检测原生对象

tips:检测字符串