首先捋清 javascript有哪些数据类型
JavaScript 数据类型
1 基本类型(7个)
string(字符串)
number(数字)
boolean(布尔值)
symbol(符号) //ES6中新增的数据类型,symbol 表示独一无二的值
null(空)
undefined(未定义)
BigInt
原始值的概念( primitive values ) 除 Object 以外的所有类型都是不可变的(值本身无法被改变)。如JavaScript 中对字符串的操作一定返回了一个新字符串,原始字符串并没有被改变。 string 、number 、boolean 和 null undefined 这五种类型统称为原始类型(Primitive),表示不能再细分下去的基本类型。
2 对象类型 (Object)
Object
Array
Date(Date对象,日期)
强制类型转换规则
ToPrimitive 算法(JavaScript对象转换到基本类型值算法)
ToPrimitive方法大概长这么个样子
/**
* @obj 需要转换的对象
* @type 期望转换为的原始数据类型,可选(string、number、default)
*/
ToPrimitive(obj,type)
JavaScript对象什么场景下会转换到基本类型值呢?
- 1 数学运算:obj1 + obj2、obj1 - obj2 等。
- 2 期望值是基本类型值的运算:alert(obj)。
ToPrimitive(obj,type),type不同值的说明
1 type为string:
if(obj.toString()结果为原始值){
return obj.toString()
}else{
if(obj.valueOf()结果为原始值){
return obj.valueOf()
}else{
抛出TypeError 异常
}
}
2 type为number:
if(obj.valueOf()结果为原始值){
return obj.valueOf()
}else{
if(obj.toString()结果为原始值){
return obj.toString()
}else{
抛出TypeError 异常
}
}
3 type参数为空
if(obj为Date对象){
type被设置为String!
}else{
type被设置为Number!
}
ToPrimitive总结 ToPrimitive转成何种原始类型,取决于type,type参数可选,若指定,则按照指定类型转换,若不指定,默认根据实用情况分两种情况,Date为string,其余对象为number。那么什么时候会指定type类型呢,那就要看下面两种转换方式了。
- 1 toString 【Object.prototype.toString()】 返回一个表示该对象的字符串
- 2 valueOf 【Object.prototype.valueOf()】 返回该对象的原始值(数值、字符串和布尔值)
不同内置对象的valueOf实现:
String => 返回字符串值
Number => 返回数字值
Date => 返回一个数字,即时间值,字符串中内容是依赖于具体实现的
Boolean => 返回Boolean的this值
Object => 返回this
代码例子:
var str = new String('123');
console.log(str.valueOf());//123
var num = new Number(123);
console.log(num.valueOf());//123
var date = new Date();
console.log(date.valueOf()); //1526990889729
var bool = new Boolean('123');
console.log(bool.valueOf());//true
var obj = new Object({valueOf:()=>{
return 1
}})
console.log(obj.valueOf());//1
var obj2 = new Object();
console.log(obj2.valueOf())//{}
Number运算符转换规则
Number(null) //0
Number(undefined) //NaN
Number(true) // 1
Number(false) // 0
//字符串转换时遵循数字常量规则,转换失败返回NaN
Number('abc') //NaN
Number('123') //123
注意:对象这里要先转换为原始值,调用ToPrimitive转换,type指定为number,继续回到ToPrimitive进行转换。
String 运算符转换规则
String(null) //'null'
String(undefined) //undefined
String(true) //'true'
String(false) //'false'
//数字转换遵循通用规则,极大极小的数字使用指数形式
String(1) // '1'
String(-1) // '-1'
String(0) // '0'
String(-0) // '0'
String(Math.pow(1000,10)) // '1e+30'
String(Infinity) // 'Infinity'
String(-Infinity) // '-Infinity'
String({}) // '[object Object]'
String([1,[2,3]]) // '1,2,3'
String(['koala',1]) //koala,1
注意:对象这里要先转换为原始值,调用ToPrimitive转换,type就指定为string,继续回到ToPrimitive进行转换。
Boolean 运算符转换规则
Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false
Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true
/*说明:
除了下述 6 个值转换结果为 false,其他全部为true。
其中包括所有对象(包括空对象)的转换结果都是true,
甚至连false对应的布尔对象new Boolean(false)也是true。
1.undefined
2.null
3.-0
4.0或+0
5.NaN
6.''(空字符串)
*/
js转换规则不同场景应用
什么时候自动转换为string类型
- 1 没有对象的情况
字符串的自动转换,主要发生在字符串的加法运算时。当一个值为字符串,另一个值为非字符串,则后者转为字符串。
'2' + 1 // '21'
'2' + true // "2true"
'2' + false // "2false"
'2' + undefined // "2undefined"
'2' + null // "2null"
- 2 有对象,且与对象+时候
//toString的对象
var obj2 = {
toString:function(){
return 'a'
}
}
console.log('2'+obj2)
//输出结果2a
//常规对象
var obj1 = {
a:1,
b:2
}
console.log('2'+obj1);
//输出结果 2[object Object]
//几种特殊对象
'2' + {} // "2[object Object]"
'2' + [] // "2"
'2' + function (){} // "2function (){}"
'2' + ['koala',1] // 2koala,1
什么时候自动转换为Number类型
- 1 有加法运算符,但是无String类型的时候,都会优先转换为Number类型
true + 0 // 1
true + true // 2
true + false //1
- 2 除了加法运算符,其他运算符都会把运算自动转成Number类型
'5' - '2' // 3
'5' * '2' // 10
true - 1 // 0
false - 1 // -1
'1' - 1 // 0
'5' * [] // 0
false / '5' // 0
'abc' - 1 // NaN
null + 1 // 1 null转为数值时为0
undefined + 1 // NaN undefined转为数值时为NaN
//一元运算符(注意点)
+'abc' // NaN
-'abc' // NaN
+true // 1
-false // 0
- 3 == 抽象相等比较与+运算符不同,不再是String优先,而是Number优先。
//情景一:均为number
1 == 2 //false
//情景二:存在对象,ToPrimitive()type为number进行转换,再比较
var obj1 = {
valueOf:function(){
return '1'
}
}
1 == obj1 //true
[] == ![] //true
//[]作为对象ToPrimitive得到 ''
//![]作为boolean转换得到0
//'' == 0
//转换为 0==0 //true
//情景三:存在boolean,按照ToNumber将boolean转换为1或者0,再进行后面比较
//boolean 先转成number,按照上面的规则得到1
//3 == 1 false
//0 == 0 true
3 == true // false
'0' == false //true
//情景四:如果x为string,y为number,x转成number进行比较
//'0' toNumber()得到 0
//0 == 0 true
'0' == 0 //true
什么时候进行布尔转换
- 布尔比较时
- if(obj) , while(obj)等判断时或者 三元运算符只能够包含布尔值
条件部分的每个值都相当于false,使用否定运算符后,就变成了true
if ( !undefined
&& !null
&& !0
&& !NaN
&& !''
) {
console.log('true');
} // true
//下面两种情况也会转成布尔类型
expression ? true : false
!! expression
js中的数据类型判断
如何判断数据类型?怎么判断一个值到底是数组类型还是对象?
三种方式,分别为 typeof、instanceof 和Object.prototype.toString()
-1 typeof 通过 typeof操作符来判断一个值属于哪种基本类型。
typeof 'seymoe' // 'string'
typeof true // 'boolean'
typeof 10 // 'number'
typeof Symbol() // 'symbol'
typeof null // 'object' 无法判定是否为 null,这是javascript中的一个bug
typeof undefined // 'undefined'
typeof {} // 'object'
typeof [] // 'object'
typeof(() => {}) // 'function'
//说明:1.null 的判定有误差,得到的结果 如果使用 typeof,null得到的结果是object
//2.操作符对对象类型及其子类型,例如函数(可调用对象)、数组(有序索引对象)等进行判定,则除了函数都会得到 object 的结果。
//总结:综上可以看出typeOf对于判断类型还有一些不足,在对象的子类型和null情况下。
-2 instanceof 通过 instanceof 操作符也可以对对象类型进行判定,其原理就是测试构造函数的prototype 是否出现在被检测对象的原型链上。
[] instanceof Array // true
({}) instanceof Object // true
(()=>{}) instanceof Function // true
let arr = []
let obj = {}
arr instanceof Array // true
arr instanceof Object // true
obj instanceof Object // true
在这个例子中,arr 数组相当于 new Array() 出的一个实例,所以 arr.proto === Array.prototype,又因为 Array属于 Object 子类型,即Array.prototype.proto === Object.prototype,因此 Object 构造函数在 arr 的原型链上。所以 instanceof 仍然无法优雅的判断一个值到底属于数组还是普通对象。
Object.prototype.toString() 可以说是判定 JavaScript 中数据类型的终极解决方法了,具体用法请看以下代码:
Object.prototype.toString.call({}) // '[object Object]'
Object.prototype.toString.call([]) // '[object Array]'
Object.prototype.toString.call(() => {}) // '[object Function]'
Object.prototype.toString.call('seymoe') // '[object String]'
Object.prototype.toString.call(1) // '[object Number]'
Object.prototype.toString.call(true) // '[object Boolean]'
Object.prototype.toString.call(Symbol()) // '[object Symbol]'
Object.prototype.toString.call(null) // '[object Null]'
Object.prototype.toString.call(undefined) // '[object Undefined]'
Object.prototype.toString.call(new Date()) // '[object Date]'
Object.prototype.toString.call(Math) // '[object Math]'
Object.prototype.toString.call(new Set()) // '[object Set]'
Object.prototype.toString.call(new WeakSet()) // '[object WeakSet]'
Object.prototype.toString.call(new Map()) // '[object Map]'
Object.prototype.toString.call(new WeakMap()) // '[object WeakMap]'
//该方法本质就是依托Object.prototype.toString()方法得到对象内部属性 [[Class]]
//传入原始类型却能够判定出结果是因为对值进行了包装
//null 和 undefined 能够输出结果是内部实现有做处理
什么是 NaN
NaN 是一个全局对象的属性。英文名称是not a number,即非数值。请使用 isNaN() 来判断一个值是否是数字。 NaN 与所有值都不相等,包括它自己。它用来表示一个本来要返回数值的操作数未返回数值的情况。在JavaScript中,任何数值除以非数值都会得到NaN。
NaN特点
有两个特点 -1 任何涉及NaN的操作都会返回NaN -2 NaN与任何值都不想等,包括NaN本身。
console.log(NaN == NaN); // false
Infinity / Infinity; //NaN 无穷大除以无穷大
Math.sqrt(-1); //NaN 给任意负数做开方运算
'a' - 1; //NaN 算数运算符与不是数字或无法转换为数字的操作数一起使用
'a' * 1; //NaN
'a' / 1; //NaN
parseInt('a'); //NaN 字符串解析成数字
parseFloat('a'); //NaN
Number('a'); //NaN
'abc' - 1 // NaN
undefined + 1 // NaN
//一元运算符(注意点)
+'abc' // NaN
-'abc' // NaN
isNaN函数
这个函数接受一个任意类型的参数,该函数会帮我们确认这个参数是否“不是数值”。isNaN()在接收到一个值后,会尝试将这个值转为数值。某些不是数值的值会直接被转换为数值,类似字符串“10”或者Boolean值。
console.log(isNaN(NaN)); //true
console.log(isNaN(10)); //false
console.log(isNaN("10")); //false
console.log(isNaN("blue")); //true
console.log(isNaN(true)); //false
toString()、String()、valueOf() 区别
toString和String的区别
-1 数值、布尔值、对象和字符串值都有一个toString()方法,该方法返回字符串的一个副本,但null和undefined值没有这个方法。因此在对一个变量进行了toString()后,如果变量为null或者undefined的时候就会报错。
-2 toString()括号中可以写数字,默认toString()方法以【十进制】格式返回数值的字符串表示。而通过传递基数,toString()可以输出以二进制、八进制、十六进制。
var num = 10;
console.log(num.toString()); // "10"
console.log(num.toString(2)); //"1010"
-3 String()可以将null和undefined转换为字符串,但是没法转进制字符串
console.log(String(null)); // null
console.log(String(undefined)); // undefined
toString和valueOf的区别
toString() 和 valueOf() 是对象的两个方法。
toString( ):返回对象的字符串表示。
valueOf( ):返回对象的字符串、数值或布尔值表示。
undefined和null都没有这两个方法,所以会报错的。
//先看看toString()方法的结果
var a = 3;
var b = '3';
var c = true;
var d = {test:'123',example:123}
var e = function(){console.log('example');}
var f = ['test','example'];
a.toString(); // "3"
b.toString(); // "3"
c.toString(); // "true"
d.toString(); // "[object Object]"
e.toString(); // "function (){console.log('example');}"
f.toString(); // "test,example"
//再看看valueOf()方法的结果
var a = 3;
var b = '3';
var c = true;
var d = {test:'123',example:123}
var e = function(){console.log('example');}
var f = ['test','example'];
a.valueOf();// 3
b.valueOf();// "3"
c.valueOf();// true
d.valueOf();// {test:'123',example:123}
e.valueOf();// function(){console.log('example');}
f.valueOf();// ['test','example']
toString( )就是将其他东西用字符串表示,比较特殊的地方就是,表示对象的时候,变成"[object Object]",表示数组的时候,就变成数组内容以逗号连接的字符串,相当于Array.join(',')。 而valueOf( )就返回它自身了。