javascript 数据类型及判断转换

272 阅读5分钟

1、JavaScript 数据类型

(1)数据类型

  • 基本数据类型:Undefined、Null、Boolean、Number、String、Symbol(es6新增,表示独一无二的值)和BigInt(es10新增);直接存储在(stack)中,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储。
  • 引用数据类型——Object      同时存储在(stack)和(heap)中,占据空间大、大小不固定。引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。

(2)null、undefined、NaN 

``null<span>表示“空”,</span>undefined<span>表示值未定义</span>

null表示一个“空”的值,它和0以及空字符串''不同,0是一个数值,''表示长度为0的字符串,

NaN主要出现在将字符串解析成数字出错的场合。  这个特殊的Number与所有其他值都不相等,包括它自己:

NaN === NaN; // false

//数组的indexOf方法内部使用的是严格相等运算符,所以该方法对NaN不成立。
[NaN].indexOf(NaN) // -1

Infinity > 1000 // true
-Infinity < -1000 // true

Infinity > NaN // false
-Infinity > NaN // false

Infinity < NaN // false
-Infinity < NaN // false

(3)判断相等

ES6中提出”Same-value equality“(同值相等)算法,用来解决这个问题。
Object.is就是部署这个算法的新方法,它用来比较两个值是否严格相等,与严格比较运算(===)行为基本一致。
Object.js()不同之处有两处,一是+0不等于-0,而是NaN等于自身,如下:

let a = {}
let b = {}
let c = b
console.log(a === b) // false
console.log(b === c) // true
console.log(Object.is(b, c)) // true 

注意两个空对象不能判断相等,除非是将一个对象赋值给另外一个变量,对象类型的变量是一个指针,比较的也是这个指针,而不是对象内部属性,对象原型等。

2、特殊数值

(1)正零和负零

JavaScript 内部实际上存在2个0:一个是+0,一个是-0,区别就是64位浮点数表示法的符号位不同。它们是等价的。

-0 === +0 // true
0 === -0 // true
0 === +0 // true

几乎所有场合,正零和负零都会被当作正常的0

+0 // 0
-0 // 0
(-0).toString() // '0'
(+0).toString() // '0'

唯一有区别的场合是,+0或-0当作分母,返回的值是不相等的。除以正零得到+Infinity(无穷),除以负零得到-Infinity,这两者是不相等的。

(1 / +0) === (1 / -0) // false

3、数据类型判断

(1) typeof  

typeof返回一个字符串,表示未经计算的操作数的类型,可能返回的值如下:

类型结果
Undefined“undefined”
**Null****“object”**
Boolean“boolean”
Number“number”
Bigint“bigint”
String“string”
Symbol“symbol”
宿主对象(由JS环境提供)取决于具体实现
Function对象“function”
其他任何对象“object”
console.log(typeof NaN) // number NaN是数字计算得到的结果
console.log(typeof '1') //string 内容为数字的字符串仍然是字符串

console.log(typeof !!(1)) // boolean 两次调用!!操作想短语Boolean()

console.log(typeof declaredButUndefinedVariabl) // 未赋值的变量返回undefined
console.log(typeof undeclaredVariable ) // 未定义的变量返回undefined

console.log(typeof new Date()) //object
console.log(typeof /s/) // 正则表达式返回object
console.log(typeof Math.sin) // function 

// 下面的例子令人迷惑,非常危险,没有用处,应避免使用
// 除Function之外所有构造函数的类型都是 object
console.log(typeof new Boolean(true)) // object
console.log(typeof new Number(1)) // object
console.log(typeof new String('abc')) // object

(2)instanceof

instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。其意思就是判断对象是否是某一数据类型(如Array)的实例,

语法:object instanceof constructor
参数:object 某个实例对象
constructor 某个构造函数

可以精准判断引用数据类型(Array,Function,Object),而基本数据类型不能。

//基本数据类型不能准确判断
console.log(2 instanceof Number);                    // false
console.log(true instanceof Boolean);                // false 
console.log('str' instanceof String);                // false  

//引用数据类型可以精准判断
console.log([] instanceof Array);                    // true
console.log(function(){} instanceof Function);       // true
console.log({} instanceof Object);                   // true    
// console.log(undefined instanceof Undefined); 报错
// console.log(null instanceof Null);

(3) constructor

//不更改原型
console.log((2).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(('str').constructor === String); // true
console.log(([]).constructor === Array); // true
console.log((function() {}).constructor === Function); // true
console.log(({}).constructor === Object); // true//创建一个对象,更改它的原型,constructor就会变得不可靠了function Fn(){};
Fn.prototype=new Array();
var f=new Fn();

console.log(f.constructor===Fn);    // false
console.log(f.constructor===Array); // true 

(4) toString

toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型。

  • Object 对象,直接调用 toString() 就能返回 [object Object] 。

  • 其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。

    Object.prototype.toString.call('') ;   // [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(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]
    Object.prototype.toString.call(document) ; // [object HTMLDocument]
    Object.prototype.toString.call(window) ; //[object global] window 是全局对象 global 的引用
    

4、数据类型转换

JavaScript是一种弱类型的编程语言,定义时无须指定数据类型。
数据类型转换包括隐式类型转换和显式类型转换两种。

隐式类型转换

window对象的alert方法和document对象的write方法。可以向这两种方法中传入任何类型的数据,这些数据最终都被自动转换为字符串型。

document.write(1+"1"); //输出11

显式类型转换 JavaScript 变量可以转换为新变量或其他数据类型,主要用到的三个API为:

  • Number:将数据类型转换为number类型;
  • String:将数据类型转换为string类型;
  • Boolean:将数据类型转换为boolean类型;

(1) 数值转换

  • Number()

    对象的值转换为数字。如果参数是Date对象,Number()返回从1970年1月1日至今的毫秒数。如果对象的值无法转换为数字,那么将返回NaN.

    Number(1) //1Number([ ]) //0Number({ }) //NaN
    
    var a = new Date()
    Number(a) // 1596526844931
    
  • parseInt()
    字符串解析转化为数字类型,并返回一个整数,不遵循四舍五入。

    parseInt("a") // NaN
    parseInt("10.11") // 10
    
  • parseFloat()
    返回一个浮点数

    parseFloat('3.14') //3.14parseFloat('abc') //NaNparseFloat('3.14abc') //3.14parseFloat('abc3.14') //NaN
    
  • **toFixed() 
    **返回字符串值,它包含了指定位数小数的数字,遵循四舍五入

    var a = 9.3487
    a.toFixed(2)// 9.35
    a.toFixed(9) // "9.348700000"
    
  • **不四舍五入保留小数

    var a = 2.461;
    var b = ( parseInt( a * 100 ) / 100 ).toFixed(2);** 
    

(2) Boolean转换

  • null undefined、""、+0、-0、false、NaN  转布尔结果是false,
  • 其余情况包括-1、"0"、{} 、[]都会转为true。
  • 用任何东西取反两次就会得到一个 Boolean
Boolean({}) // true
Boolean([]) // true

!!"abc" ; // true
!!'' ; // false
!!{} ; // true

(3) String转换

使用加号运算符、""4 + 3 + "2" // "72" "4" + 3 + 1 // "431" true + "" // "true" var f = function(){return 1;}; f + "" // "function(){return 1;}" 对象与字符串

var a = { x :1 }
a + "" // "[object Object]"
//利用原生JSON对象,将对象转为字符串
var obj = {test : 3}
var obj2 = JSON.stringify(obj)obj // "{"test":3}"

//从JSON字符串转为对象
JSON.parse(obj2) // {test: 3}
  • ** 数组与字符串**

    var arr = [1,2,3]var arr2 = [4,5,6] var arr3 = [1,[2,3],[4,5]],[6,[7,[8,9],0]]];

    arr3.toString() // "1,2,3,4,5,6,7,8,9,0" arr + '' // "1,2,3" arr.toString() // "1,2,3" arr + arr2 = "1,2,34,5,6"

    var str = arr.join(",")
    str // "1,2,3"

    str.split(",") // [1,2,3]

(4) valueOf  和toString

**valueOf() **

返回指定对象的原始值。不同类型对象的valueOf()方法的返回值

  1. Array 返回数组对象本身。

  2. Boolean 布尔值。

  3. Date 存储的时间是从 1970 年 1 月 1 日午夜开始计的毫秒数 UTC。

  4. (Function 函数本身:

    function a(){console.log(1)}  
    a.valueOf()  //   ƒ a(){console.log(1)}
    
  5. Number 数字值。

  6. Object 对象本身:

  7. String 字符串值。

  8. Math 和 Error 对象没有 valueOf 方法。

**toString() **

1.每个Object对象都包含该方法。
2.当Object对象以字符串方式引用时会被自动调用,注意,是Object对象。
3.默认调用时返回[object type]。例如:

var o = new Object();
o.toString();
控制台返回结果:"[object Object]"

4.可以使用toString()检测对象类型
例如:

var a="dd";
toString.call(a);//需要通过apply或者call方式调用
"[object String]"

不过貌似没啥实用性,采取这种调用方式无法获得"[object String]"。

两者都可以通过显示原型重新定义:

myObject.prototype.valueOf() = function myValueOf(){};
myObject.prototype.toString() = function myToString(){};

重写函数都可以为匿名函数。