数据类型(8种)
ES5: Number,String,Boolean,undefined、Object、null
ES6: Symbol 每个从Symbol()返回的symbol值都是唯一的 ,表示独一无二的值
谷歌67版本中还出现了一种 BigInt。是指安全存储、操作大整数。
基本类型
除Object 以外的数据类型
特点
- 按值访问的 ,可以操作保存在变量中的实际的值
- 基本数据类型的值是不可变的,任何方法都无法改变一个基本数据类型的值
为什么基本数据类型不可变?
堆和栈
程序运行的时候,需要内存空间存放数据 ,一般来说,系统会划分出两种不同的内存空间 ,一种叫做堆(heap),另一种叫做栈(stack)
堆(heap)是没有结构的,数据可以任意存放,它是用于存放复杂数据类型(引用类型)的,例如数组对象、object对象等。
栈(stack)是有结构的,每个区块按照一定次序存放(先进后出),栈中主要存放的是基本类型的变量的值以及指向堆中的数组或者对象的地址,存在栈中的数据大小与生存期必须是确定的。除此之外,还可以明确知道每个区块的大小,因此,stack的寻址速度要快于heap
栈有一个很重要的特殊性,就是存在栈中的数据可以共享首先定义一个变量 a=3; b= 3; 编译器先处理a = 3;首先它会在栈中创建一个变量为 a 的引用,然后查找有没有字面值为 3 的地址,没找到,就开辟一个存放 3 这个字面值的地址,然后将 a 指向 3 的地址
接着处理 b = 3,在创建完 b 的引用变量后,由于在栈中已经有 3 这个字面值,便将 b 直接指向 3 的地址。这样,就出现了 a 与 b 同时均指向 3 的情况
但是和引用类型不同,基本类型的存储都是在栈内,这里的a只是指向3的一个指针,当我们定义 a = 4;它就会重新搜索栈中是否有 4 的字面值,如果没有,重新开辟地址存放 4 的值;如果已经有了,则直接将 a 指向这个地址 ,因此 a 值的改变不会影响到 b 的值 ,而3从并未被改变
- 基本数据类型不可以添加属性和方法
- 基本数据类型的赋值是简单的赋值
- 基本数据类型的比较是值的比较
- 基本类型的值在内存中占据固定大小的空间,被保存在栈内存中
引用类型
Object: 包括 Array,Date,Function,Object
var a = new Object();
a.name = 'xz';
var b = a;
数据类型检测
typeof
"undefined" — 未定义
"boolean" — 布尔值
"string" — 字符串
"number" — 数值
"object" — 对象或null
"function" — 函数
instanceof
var sXzaver = new String("Xzavier");
console.log(sXzaver instanceof String); // "true"
var aXzaver = [1,2,3];
console.log(aXzaver instanceof Array); // "true"
constructor
'xz'.constructor == String // true
(123).constructor == Number // true
(true).constructor == Boolean // true
[1,2].constructor == Array // true
({name:'xz'}).constructor == Object // true
(function(){}).constructor == Function // true
(new Date()).constructor == Date // true
(Symbol()).constructor == Symbol // true
(/xz/).constructor == RegExp // true
Object.prototype.toString.call(obj)
Object.prototype.toString.call('xz'); //"[object String]"
Object.prototype.toString.call(123); //"[object Number]"
Object.prototype.toString.call(true); //"[object Boolean]"
Object.prototype.toString.call([1,2]); //"[object Array]"
Object.prototype.toString.call({name:'xz'}); //"[object Object]"
Object.prototype.toString.call(function(){}); //"[object Function]"
Object.prototype.toString.call(null); //"[object Null]"
Object.prototype.toString.call(undefined); //"[object Undefined]"
Object.prototype.toString.call(); //"[object Undefined]"
Object.prototype.toString.call(new Date()); //"[object Date]"
Object.prototype.toString.call(/xz/); //"[object RegExp]"
Object.prototype.toString.call(Symbol()); //"[object Symbol]"
Object.prototype.toString.call判断数据类型原理
toString为Object的原型方法,而Array 、Function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(Function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串…),而不会去调用Object上原型toString方法(返回对象的具体类型)
Array.isArray( arr ) 检测是否为数组
数据类型转化
隐式转换
undefined == null; // true
1 == true; // true
2 == true; // false
0 == false; // true
0 == ''; // true
NaN == NaN; // false NaN不等于任何值
[] == false; // true
[] == ![]; // true
'6' - '3' // 3
1234 + 'abcd' // "1234abcd"
[] == ![]
!优先于==, 因此会先计算![]的结果,[]是真值,转化为Boolean是true,所以![] 结果为false,因此当前表达式相当于 [] == false,任何类型与boolean类型比较 ,boolean将转为Number,Number(false)结果是0,最终 [] == 0
- undefined 和 null 相等, 但是不恒等(===)
- 一个是number,一个是string,会尝试将string转为number
- boolean与其他类型比较,会转number,0或1
显示转换
Number
Number('1234') // 1234
Number('1234abcd') // NaN
Number('') // 0
Number(true) // 1
Number(false) // 0
Number(null) // 0
Number(undefined) // NaN
String
String(1234) // "1234"
String('abcd') // "abcd"
String(true) // "true"
String(undefined) // "undefined"
String(null) // "null"
Boolean
Boolean('') //flase
Boolean(0) //flase
Boolean(NaN) //flase
Boolean(null) //flase
Boolean(undefined) //flase
Boolean([]) //true
Boolean({}) //true
希望大家能坚持读完,本来以为数据类型很少的,闲来复习总结了一下,谁知道零碎的点这么多,另外有一点值得注意,判断数据类型时,如果使用typeof这个方法
typeof null // objecf
typeof function(){} // function
大家不用混淆,null是基本类型,只是历史遗留问题,导致判断为object,而function是属于object的