JavaScript 数据类型与类型判断详解

一、JAVAScript 数据类型JavaScript 数据类型有两种,分别是基本数据类型和引用数据类型 。

  • 基本数据类型NumberStringBooleanUndefinedNullSymbol (ES6 新增,表示独一无二的值)
  • 引用数据类型ObjectFunctionArray
我们来详细了解一下这两种数据类型的特点
1.基本数据类型值不可变基本类型的值是 不可变 的
var name = 'javascript';name.toUpperCase(); //'JAVASCRIPT'console.log(name); //'javascript'但是我们不是经常有 ++a 这种操作吗?比如
let a = 1console.log(++a) // '2'其实这个时候并不是 a 指向的 1 直接加了 1,而是 新建了一个 1+1 = 2 的值,再将 a 指向这个新建出来的 2,原来的那个 1 并没有发生改变,留由垃圾回收机制处理 。也就是说不是 a 指向的值发生了改变,而是 a 变量指针指向了一个新的值,这和「基本类型的值是不可变的」这句话并不矛盾 。
数据存放在栈区原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储 。
2.引用数据类型值是可变的let a = { age : 20 };a.age = 21;console.log(a.age)//21同时保存在栈内存和堆内存引用数据类型占据空间大,大小不固定,储存在堆内存,但是指向该引用数据类型的变量指针「a」是储存在栈内存中 。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体 。
二、数据的赋值基本数据类型的赋值为复制了一个新的值,对新变量的修改不会影响原变量
let a = 1;let b = a;b++console.log(a)// 1console.log(b)// 2在内存中的变化如图:
JavaScript 数据类型与类型判断详解

文章插图
 
但是引用数据类型就不一样,因为引用数据内型占用空间大,所以赋值操作是将新变量指针指向了原对象,修改其一都会影响到另一个 。
let a={id=1234}let b=ab.id=1222console.log(a.id) // 1222console.log(b.id) // 1222在内存中的变化如图:
JavaScript 数据类型与类型判断详解

文章插图
 
关于引用对象的拷贝又分为深拷贝和浅拷贝,限于篇幅就留给下篇文章了
三、检验数据类型typeof这应该初学者首次接触的类型判断方法了,它返回一个表示数据类型的字符串,返回结果包括:
  • number
  • boolean
  • string
  • symbol
  • object
  • undefined
  • function
但是不能判断 array 和 null
typeof Symbol();// symbol正确typeof '';// string 正确typeof 1;// number正确typeof true;//boolean 正确typeof undefined; //undefined 正确typeof new Function(); // function 正确typeof null; //object 无效typeof [] ;//object 无效typeof new Date(); //object 无效typeof new RegExp(); //object 无效typeof 缺点可以看到 Date 和 RegExp 对象都只是被是被成了 object 对象,也就是说除 function 以外的对象都会被识别成 object ,这样显然是不合理的,这时就需要 instanceof 来进行判断 。
instanceofinstanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上 。简单来说就是 instanceof 是用来判断 A 是否为 B 的实例,表达式为
A (object) instanceof B (constructor)
如果A是B的实例,则返回true,否则返回 false 。
// 定义构造函数function C(){} function D(){} var o = new C();o instanceof C; // true,因为 Object.getPrototypeOf(o) === C.prototypeo instanceof D; // false,因为 D.prototype 不在 o 的原型链上o instanceof Object; // true,因为 Object.prototype.isPrototypeOf(o) 返回 trueC.prototype instanceof Object // true,同上C.prototype = {};var o2 = new C();o2 instanceof C; // trueo instanceof C; // false,C.prototype 指向了一个空对象,这个空对象不在 o 的原型链上.D.prototype = new C(); // 继承var o3 = new D();o3 instanceof D; // trueo3 instanceof C; // true 因为 C.prototype 现在在 o3 的原型链上现在就可以判断不同类别的对象了
[] instanceof Array; //true{} instanceof Object;//truenew Date() instanceof Date;//truenew RegExp() instanceof RegExp//trueinstanceof 的缺点1.是否处于原型链上的判断方法不严谨instanceof 方法判断的是是否处于原型链上,而不是是不是处于原型链最后一位,所以会出现下面这种情况:
var arr = [1, 2, 3];console.log(arr instanceof Array) // trueconsole.log(arr instanceof Object);// truefunction fn(){}console.log(fn instanceof Function)// trueconsole.log(fn instanceof Object)// true


推荐阅读