JS之数据类型笔记

201 阅读9分钟

首先捋清 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

什么时候进行布尔转换

  1. 布尔比较时
  2. 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( )就返回它自身了。