JS 的数据类型你了解多少?

数据类型

在ES5的时候,我们认知的数据类型确实是 6种:Number、String、Boolean、undefined、object、Null

ES6 中新增了一种 Symbol :这种类型的对象永不相等,即使创建的时候传入相同的值,可以解决属性名冲突的问题

谷歌67版本中还出现了一种 bigInt:是指安全存储、操作大整数

图片

JavaScript 的数据类型最后都会在初始化之后放在不同的内存中,因此上面的数据类型大致可以分成两类来进行存储:

1.基础类型存储在栈内存,被引用或拷贝时,会创建一个完全相等的变量;

2.引用类型存储在堆内存,存储的是地址,多个引用指向同一个地址,这里会涉及一个“共享”的概念。

JavaScript 的数据类型最后都会在初始化之后放在不同的内存中,因此上面的数据类型大致可以分成两类来进行存储:

1.基础类型存储在栈内存,被引用或拷贝时,会创建一个完全相等的变量;

2.引用类型存储在堆内存,存储的是地址,多个引用指向同一个地址,这里会涉及一个“共享”的概念。

let a = {

  name: '张三',

  age: 20

}

function change(o) {

  o.age = 24;

  o = {

    name: '李四',

    age: 30

  }

  return o;

}

let b = change(a);     // 注意这里没有new

console.log(b.age);    // 第一个console

console.log(a.age);    // 第二个console

函数传参进来的 o,传递的是对象在堆中的内存地址值,通过调用 o.age = 24(第 7 行代码)确实改变了 a 对象的 age 属性;12 行把参数 o 的地址重新返回了,将 {name: "Kath", age: 30} 存入其中,最后返回 b 的值就变成了 {name: "Kath", age: 30}。而如果把第 12 行去掉,那么 b 就会返回 undefined。

第一个 console 的结果是 30

第二个 console 的返回结果是 24

JS数据类型:null 和 undefined 有什么区别?

Null 只有一个值,是 null。不存在的对象。

Undefined 只有一个值,是undefined。没有初始化。undefined 是从 null 中派生出来的。

简单理解就是:undefined 是没有定义的,null 是定义了但是为空。

数据类型检测

第一种判断方法:typeof

typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof null // 'object'
typeof [] // 'object'
typeof {} // 'object'
typeof console // 'object'
typeof console.log // 'function'

为什么第 6 个 null 的 typeof 是 'object' 呢?

这里要和你强调一下,虽然 typeof null 会输出 object,但这只是 JS 存在的一个悠久 Bug,不代表 null 就是引用数据类型,并且 null 本身也不是对象。因此,null 在 typeof 之后返回的是有问题的结果,不能作为判断 null 的方法。如果你需要在 if 语句中判断是否为 null,直接通过 ‘===null’来判断就好

第二种判断方法:instanceof

我们 new 一个对象,那么这个新对象就是它原型链继承上面的对象了,通过 instanceof 我们能判断这个对象是否是之前那个构造函数生成的对象,这样就基本可以判断出这个新对象的数据类型

let Car = function() {}let benz = new Car()benz instanceof Car // truelet car = new String('Mercedes Benz')car instanceof String // truelet str = 'Covid-19'str instanceof String // false

instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型

而 typeof 也存在弊端,它虽然可以判断基础数据类型(null 除外),但是引用数据类型中,除了 function 类型以外,其他的也无法判断

第三种判断方法:Object.prototype.toString

toString() 是 Object 的原型方法,调用该方法,可以统一返回格式为 “[object Xxx]” 的字符串

Xxx 就是对象的类型。对于 Object 对象,直接调用 toString() 就能返回 [object Object];而对于其他对象,则需要通过 call 来调用,才能返回正确的类型信息

Object.prototype.toString({})       // "[object Object]"Object.prototype.toString.call({})  // 同上结果,加上call也okObject.prototype.toString.call(1)    // "[object Number]"Object.prototype.toString.call('1')  // "[object String]"Object.prototype.toString.call(true)  // "[object Boolean]"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(/123/g)    //"[object RegExp]"Object.prototype.toString.call(new Date()) //"[object Date]"Object.prototype.toString.call([])       //"[object Array]"Object.prototype.toString.call(document)  //"[object HTMLDocument]"Object.prototype.toString.call(window)   //"[object Window]"

Object.prototype.toString.call() 可以很好地判断引用类型,甚至可以把 document 和 window 都区分开来。

但是在写判断条件的时候一定要注意,使用这个方法最后返回统一字符串格式为 "[object Xxx]" ,而这里字符串里面的 "Xxx" ,第一个首字母要大写(注意:使用 typeof 返回的是小写),这里需要多加留意

实现一个全局通用的数据类型判断方法,来加深理解


function getType(obj){

  let type  = typeof obj;

  if (type !== "object") {    // 先进行typeof判断,如果是基础数据类型,直接返回

    return type;

  }

  // 对于typeof返回结果是object的,再进行如下的判断,正则返回结果

  return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1');  // 注意正则中间有个空格

}

/* 代码验证,需要注意大小写,哪些是typeof判断,哪些是toString判断?思考下 */

getType([])     // "Array" typeof []是object,因此toString返回

getType('123')  // "string" typeof 直接返回

getType(window) // "Window" toString返回

getType(null)   // "Null"首字母大写,typeof null是object,需toString来判断

getType(undefined)   // "undefined" typeof 直接返回

getType()            // "undefined" typeof 直接返回

getType(function(){}) // "function" typeof能判断,因此首字母小写

getType(/123/g)      //"RegExp" toString返回

数据类型转换

在日常的业务开发中,经常会遇到 JavaScript 数据类型转换问题,有的时候需要我们主动进行强制转换,而有的时候 JavaScript 会进行隐式转换,隐式转换的时候就需要我们多加留心

强制类型转换

强制类型转换方式包括 Number()、parseInt()、parseFloat()、toString()、String()、Boolean(),这几种方法都比较类似,通过字面意思可以很容易理解

Number() 方法的强制转换规则

  • 如果是布尔值,true 和 false 分别被转换为 1 和 0;

  • 如果是数字,返回自身;

  • 如果是 null,返回 0;

  • 如果是 undefined,返回 NaN;

  • 如果是字符串,遵循以下规则:如果字符串中只包含数字(或者是 0X / 0x 开头的十六进制数字字符串,允许包含正负号),则将其转换为十进制;如果字符串中包含有效的浮点格式,将其转换为浮点数值;如果是空字符串,将其转换为 0;如果不是以上格式的字符串,均返回 NaN;

  • 如果是 Symbol,抛出错误;

Boolean() 方法的强制转换规则

这个方法的规则是:除了 undefined、 null、 false、 ''、 0(包括 +0,-0)、 NaN 转换出来是 false,其他都是 true

隐式类型转换

凡是通过逻辑运算符 (&&、 ||、 !)、运算符 (+、-、*、/)、关系操作符 (>、 <、 <= 、>=)、相等运算符 (==) 或者 if/while 条件的操作,如果遇到两个数据类型不一样的情况,都会出现隐式类型转换

'==' 的隐式类型转换规则

  • 如果类型相同,无须进行类型转换;

  • 如果其中一个操作值是 null 或者 undefined,那么另一个操作符必须为 null 或者 undefined,才会返回 true,否则都返回 false;

  • 如果其中一个是 Symbol 类型,那么返回 false;

  • 两个操作值如果为 string 和 number 类型,那么就会将字符串转换为 number;

  • 如果一个操作值是 boolean,那么转换成 number;

  • 如果一个操作值为 object 且另一方为 string、number 或者 symbol,就会把 object 转为原始类型再进行判断(调用 object 的 valueOf/toString 方法进行转换)

'+' 的隐式类型转换规则

  • 如果其中有一个是字符串,另外一个是 undefined、null 或布尔型,则调用 toString() 方法进行字符串拼接;如果是纯对象、数组、正则等,则默认调用对象的转换方法会存在优先级(下一讲会专门介绍),然后再进行拼接。

  • 如果其中有一个是数字,另外一个是 undefined、null、布尔型或数字,则会将其转换成数字进行加法运算,对象的情况还是参考上一条规则。

  • 如果其中一个是字符串、一个是数字,则按照字符串规则进行拼接。

总结

  1. 数据类型的基本概念:这是必须掌握的知识点,作为深入理解 JavaScript 的基础。

  2. 数据类型的判断方法:typeof 和 instanceof,以及 Object.prototype.toString 的判断数据类型、手写 instanceof 代码片段,这些是日常开发中经常会遇到的,因此需要好好掌握。

  3. 数据类型的转换方式:两种数据类型的转换方式,日常写代码过程中隐式转换需要多留意,如果理解不到位,很容易引起在编码过程中的 bug,得到一些意想不到的结果。

 可关注公众号,互相学习,实时更新

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值