基本数据类型
Null、 Undefined 、String、 Number、 Boolean、 Symbol(唯一值)、 bigInt(大数据类型)
原始数据类型:直接存储在栈中,占据空间小、大小固定、频繁使用的数据。
引用数据类型
Object、Array、Function、Date和正则、Map、Set等
引用数据类型存储在堆(heap)内存中,并且变量本身存储在栈内存中,但是栈中的这个变量存储的并不是实际的数据值,而是一个指向堆内存中实际对象所在位置的指针(或引用)。
引用数据类型:保存在内存中的对象(同时保存在栈内存和堆内存中),占据空间大、大小不固定。在栈中存储指针,该指针指向堆中该实体的起始地址。解释器寻找引用值时,首先检索其在栈中的地址,取得地址后从堆中获得实体。
存储的区别:[基栈、引堆]
基本数据类型直接存储在栈中,数据大小确定,内存空间大小可以分配,按值传递,值不可变,可以重新赋值。引用数据类型存放在堆中,变量实际是一个存放在栈内存的指针,指针指向堆内存中的地址,每个空间大小不一样。按引用传递。
null与undefined的区别
null:表示一个值被定义了,定义为空值。
// 使用场景
(1) 作为函数的参数,表示该函数的参数不是对象。
(2) 作为对象原型链的终点。
undefined:表示根本不存在定义。
// 使用场景
(1)变量声明但未赋值
let x
console.log(x)// undefined
(2)函数没有return值时
function test(){}
console.log(test()) // undefined
(3)访问对象中不存在的属性
let obj = {}
console.log(obj.name) // undefined
- 检测
null == undefined // true
null === undefined // false
typeof undefined // undefined
typeof null // object
检测数据类型得几种方法
typeof (只能判断js的基本数据类型,无法判断数组、null、对象)支持两种语法形式:
// 作为运算符:typeof x
// 函数形式:typeof(x)
// 特殊情况:typeof null ---->object
【null的二进制表示为全零(即00000000),与对象类型标签相同。所以typeof null 错误识别为“object”】
总结:
- 对于基本类型,除null以外,均可以返回正确的结果(typeof null --->object)
- 对于引用类型,除function以外,一律返回object类型
- 对于null,返回object类型.在js中,如果二进制前三位都为0,就会被`typeof`判断为object。
其中null的二进制全是0,故返回值为object。
- 对于function返回function类型
instanceof
用于检测构造函数的prototype属性是否出现在某个实例对象原型链上
console.log(bool instanceof Boolean);// false
console.log(num instanceof Number);// false
console.log(str instanceof String);// false
console.log(und instanceof Object);// false
console.log(null instanceof Object);// false
console.log(arr instanceof Array);// true
console.log(obj instanceof Object);// true
console.log(fun instanceof Function);// true
var bool2 = new Boolean()
console.log(bool2 instanceof Boolean);// true
var num2 = new Number()
console.log(num2 instanceof Number);// true
var str2 = new String()
console.log(str2 instanceof String);// true
instanceof的原理
检测constructor.prototype是否存在于参数object的原型链上。instanceof查找的过程中遍历object的原型链,直到找到constructor的prototype,如果查找失败,则返回false,成功则返回true。
function myInstanceof(obj,constructor){
// 检查obj是否为null或undefined
if(obj === null || typeof obj !== 'object'){
return false
}
// 获取对象的原型
let proto = Object.getPrototypeOf(obj)
// 循环检查原型链
while(proto !== null){
if(proto == constructor.prototype){
return true //找到匹配的原型,返回true
}
proto = Object.getPrototypeOf(proto) // 继续向上查找原型链
}
return false; // 原型链中没有找到匹配的构造函数原型,返回false
}
// 示例使用
console.log(myInstanceof({},Object)) // true
判断构造函数(constructor)
构造函数原型上由一个constructor属性指向构造函数自身的。如果在实例上使用constructor时,就会直接使用其构造函数原型的上的该属性,并指向其构造函数。
console.log([].constructor === Array); // true
console.log({}.constructor === Object); // true
使用Object.prototype.toString.call()函数
原理:
- “根”原型(Object.prototype)下,有个toString的方法,记录着所有 数据类型(构造函数)
- .call作用是改this指向。让传入的对象,执行 “根”原型的toString方法
首先,取得对象的一个内部属性[[class]],依据这个属性,返回一个类似于'[object Array]'的字符串作为结果。利用这个方法,在配合call,可以取得任何对象的内部属性[[Class]],然后将类型检测转化为字符串比较。
call()方法可以改变this的指向,Object.prototype.toString最终会返回形式如[object,class]的字符串,class指代的时其检测出的数据类型。
console.log(Object.prototype.toString.call(boolean));//[object Boolean]
console.log(Object.prototype.toString.call(number));//[object Number]
console.log(Object.prototype.toString.call(string));//[object String]
console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call(null));//[object Null]
console.log(Object.prototype.toString.call(array));//[object Array]
console.log(Object.prototype.toString.call(object));//[object Object]
console.log(Object.prototype.toString.call(Function));//[object Function]
// 去除掉返回值中的object
console.log(Object.prototype.toString.call(Function).slice(8,-1));// Function
slice(startIndex,endIndex),从0开始索引,其中8代表从第8位(包含)开始截取(本例中代表空格后面的位置),-1代表截取到倒数第一位(不含),所以正好截取到[object String]中的String。
- 最好的数据类型检测方法
function type(obj){
return typeof obj !== "object" ? typeof obj :Object.prototype.toString.call(obj).slice(8,-1).toLowerCase();
}
typeof、instanceof的区别
typeof用于基本数据类型的类型判断,无法甄别对象具体类型instanceof用于对象的类型判断,基于原型链上的继承关系
额外补充点(JS中的强制转换规则)
- Number()强制转换
- 布尔值,true转换为1,false转换为0
- 数字返回自身
- null返回0
- undefined返回NaN
- 字符串转换
- 空字符串,转换为0
- 字符串中只包含数字(Ox/0X开头数字可以有正负),将其转换为十进制
- 字符串中包含有效的浮点格式,转换为浮点数
- 以上都不是,返回NaN
- 如果是Symbol,抛出错误
Number(true) // 1
Number(false) // 0
Number('0111') // 111
Number(null) // 0
Number('') // 0
Number('1a') // NaN
Number(-0X11) // -17
Number('0X11') // 17
- Boolean()方法的强制转换规则 undefined,null,false,'',0(+0,-0),NaN转换为false,其他转换为true。
Boolean(0) // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(NaN) // false
Boolean(1) // true
Boolean(12) // true
Boolean('a') // true
-
什么时候自动转换为string类型
- 在没有对象的前提下 字符串的自动转换,主要发生在字符串的加法运算时。当一个值为字符串,另一个值为非字符串,则后者转为字符串
'2' + 1 // '21' '2' + true // '2true' '2' + false // '2false' '2' + null // '2null' '2' + undefined // '2undefined'- 当有对象且与对象+时候
// toString对象 var obj = { toString:function(){ return 'a' } } console.log('2' + obj) // 2a //常规对象 var obj = { a:1, b:2 } console.log('2' + obj) //2[object object] // 几种特殊对象 ‘2’ + {} // '2[object object]' '2' + [] // '2' '2' + function(){} // '2fuction(){}' '2' + ['koala',1] // 2koala,1- string类型转换时,易出错点
var obj = { width:'200' } obj.width + 20 // 20020 -
什么时候自动转换为Number类型
- 有加法运算符,但无String类型时,会优先转换为Number类型
true + 0 // 1 true + true //2 true + false // 1