一、JS中的两种数据类型
Javascript有两种数据类型,基本数据类型和引用数据类型。
基本数据类型有7种:
- String
- Numbe
- Boolean
- Undefined
- Null
- Symbol (ES6新增,表示独一无二的值)
- bigInt(ES11新增,表示超长数据,以n结尾,大整数只能和大整数进行计算)
引用数据类型统称为Object对象,主要包括:
- Object
- Array
- Function
- Date
- RegExp
二、基本数据类型
1、值是不可变的
多次赋值,只取最后一个
var name = 'tom';
name.toUpperCase(); // ''TOM"
console.log(name); // ''tom"
2、存放在栈结构
直接存储在栈中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储。
三、引用数据类型
1、值是可变的
// 引用类型可以拥有属性和方法,并且是可以动态改变的
var a={name:'xiaoming'};
a.name='xiaohong';
console.log(a.name) //xiaohong
2、同时保存在栈内存和堆内存
引用数据类型存储在堆中,占据空间大、大小不固定,如果存储在栈中,将会影响程序运行的性能。
引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
特别注意:
两个变量指向同一对象,改一个属性,另一个也会受影响。
操作对象的属性不会导致变量指针发生改变,改对象,会导致指针指向改变。
四、类型检测
1、typeof
typeof的返回值有六种,返回值是字符串,可以判断基本数据类型,不能判断数组和null的数据类型,返回object。
typeof ''; // string 有效
typeof 1; // number 有效
typeof true; //boolean 有效
typeof undefined; //undefined 有效
typeof new Function(); // function 有效
typeof null; //object 无效
typeof [] ; //object 无效
2、instanceof
检查对象原型链上有没有该构造函数,可以精准判断引用数据类型,不能判断基本数据类型。
[] instanceof Array; //true
{} instanceof Object;//true
new Date() instanceof Date;//true
new RegExp() instanceof RegExp//true
var arr = [1, 2, 3];
console.log(arr instanceof Array) // true
console.log(arr instanceof Object); // true
function fn(){}
console.log(fn instanceof Function)// true
console.log(fn instanceof Object)// true
// 不能检测null 和 undefined
3、constructor
类似instanceof,既可以检测基本类型又可以检测对象。
console.log((10).constructor===Number);//true
console.log([].constructor===Array);//true
var reg=/^$/;
console.log(reg.constructor===RegExp);//true
console.log(reg.constructor===Object);//false
函数的 constructor 是不稳定,如果把函数的原型进行重写,这样检测出来的结果会不准确,其次不能检测null和undefined。
function Fn(){}
Fn.prototype = new Array()
var f = new Fn
console.log(f.constructor)//Array
4、Object.prototype.toString.call()
获取Object原型上的toString方法,让方法执行,让toString方法中的this指向第一个参数的值,最准确方式。
第一个object:当前实例是对象数据类型的(object),
第二个Object:数据类型。
Object.prototype.toString.call('') ; // [object String]
Object.prototype.toString.call(1) ; // [object Number]
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(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
五、类型转换
1、强制类型转换
(1)转数值
Number()
字符串
- 合法数字,将字符串直接转化为对应的数字,不合法,转化为NaN。
- 空串、空格字符串转化为0。
布尔值
- true转化为1
- false转化为0
null和undefined
- null转化为0
- undefined转化为NaN
(2)转字符串
toString()
null和undefined不具有toSring()方法,会报错。
var a = 10
a = a.toString()
console.log(a, typeof a); //'10' string
var b = true
b = b.toString()
console.log(b, typeof b); //'true' true
var c = undefined
c =c.toString();//报错
var d = null
d = d.toString();//报错
Sting()
String函数相比toString方法适用范围更广,可以将null和undefined转化为字符串不会报错。
(3)转布尔
Boolean()
6转化为false情况:false、0、””、null、undefined、NAN
2、隐式类型转换
(1)任意值+空串 转字符串
(2)+a转数值
(3)a-0 转数值
(4)a*1
(4)对一个值进行两次取反转化成布尔值
3、手动类型转换
parseInt()
提取一个字符串的合法整数位。
注意:字符串要求数字字符必须在字符串的前面(前面可以有空白符),否则就是NaN。
a = '123'; //123
a = '123.45'; //123
a = '100px'; //100
a = 'abc100px' // NAN
parseFloat()
提取一个字符串的合法小数位。
注意:字符串要求数字字符必须在字符串的前面(前面可以有空白符),否则就是NaN。
a = '123'; //123
a = '123.45'; //123.45
a = '100px'; //100
a = 'abc100px' // NAN
4、总结
(1)判等情况下
①先看两边是不是同种数据类型,如果是直接看是不是一样;如果不是那么两边都转数字。
②当遇到null的时候,会有特殊情况发生:
特殊情况:空串和null不相等
特殊情况:false和null不相等
特殊情况:0和null不相等
特殊情况:undefined 和 null 相等
(2)运算和比较情况下
①第一步:先看是不是 +
如果是 + 看有没有字符串,如果有就是拼接字符串
②第二步:再看是不是比较
如果是比较,看是不是两边都是字符串,
如果两边全是字符串,比较的是字符串的Unicode码
③第三步:其余情况全部转数字
(3)NaN
①所有的东西和NaN进行算术运算都是NaN
②所有的东西和NaN进行比较大小都是false
③所有的东西和NaN都不相等(包括自己)
(4)全等和不全等
他们在判等的时候,必须类型和值都相同,如果有一个不一样,就不全等。