JavaScript 数据类型

JavaScript 数据类型

一、基本数据类型

  1. Undefined
  2. Null => Object 空对象 表示空指针
  3. Boolean
  4. Number
  5. String
  6. Object 细分
    • Function
    • Array
    • RegExp
    • Object

二、typeof 操作符

typeof 只是检测最基础的类型,对于Object类型的细分无能为力,比如检测不到数组。然而function有些例外,从技术角度讲,函数在 ECMAScript中是对象,不是一种数据类型。然而,函数也 确实有一些特殊的属性,因此通过 typeof 操作符来区分函数和其他对象是有必要的。那怎么判断数组的类型呢 1. Object.prototype.toString.call() , 2.Array.isArray()

  1. “undefined”——如果这个值未定义
var a
alert(a) //undefined
typeof undefined // 'undefined'

alert(b) //Reference Error
typeof b //'undefined'

因此typeof可以检测两种状态的:

  • 未声明
  • 未赋值
  1. “boolean”——如果这个值是布尔值
  2. “string”——如果这个值是字符串
  3. “number”——如果这个值是数值
  4. “object”——如果这个值是对象(包括Object的派生类)或者null

typeof 只是检测基础类型其实可以说只是检测

三、细说类型

(1) null 空对象 和 undefined 未定义

undefined 是 派生于 null 的,它们有许多的共同点,他们最有意思的地方就是被Object排除在外

  1. undefined 和 null 的特性

    • 两种种类型各只有一个值:undefined 和 null,undefined 和 null 就既是类型也是值
    • 都没有包装对象(或者说不可生成,应为null本身就是空对象,更别提包装成对象, undefined派生于null自然和其一个尿性),其实没有Object派生的对应的undefined和null的构造函数,也是证实他们不能转换为对象
    • null == undefined => true;null === undefined => false,相等操作符验证值相等,全等操作符验证类型是否相等
  2. 其实真正开发的时候大部分人还是分不清楚null和undefined的,或者说该怎么使用

    • 如果可以,请尽量不要使用undefined类型,即使要判断一个变量可能是undefined也不要尝试和 null相等比较,最简单直接的就是 typeof

    • 事实上没有任何必要给一个变量设置未undefined,如果你觉得声明变量可能有不安全值可以不显示赋值undefined,否则推荐给定初值,这种当typeof一个变量为’undefined’的时候就知道是为声明而不是赋值为undefined

      	var number = 0//希望一个数值则给定一个数值初始化
      	var string = ''
      	var boolean = false
      
    • 即使真的需要undefined也可能只是在调用函数传递参数是,为了数据配对而被迫的使用undefined实参

      myFun('a', undefined, 'b')
      
    • null 是当你需要使用一个引用变量的时候,作为初值使用;或者当你不需要使用该应用变量是赋值为null,方便清除对象内存

(2) Number类型

  • 浮点数值
  • 数值范围 zhengzhi、Infinity(无穷,分正负)
  • NaN 表示“非数值”的一种特殊的数值,注意NaN仍然是一种数值
  • 数值转换主要根据Number方法
  1. NaN 表示一个本应该返回数值的操作却未返回数值

    • 在进行计算的时候(+、-、*、/、%等)无论和什么值计算都是NaN
    • 在比较的时候是false,总某种意义上说是根据
      NaN == NaN //为false
      
      自然的进行比较(>、<、<=、>=等)都是false
    • isNaN函数,表示判断参数是否为能转换为数值且不为NaN
  2. Infinity 表示无穷,超出范围

    • 数值计算超出预定返回,返回Infinity,Number.MIN_VALUE、Number.MAX_VALUE:最小最带值
    • Infinity分正负,一个负值Infinity为-Infinity,同理正值Infinity为+Infinity
      Infinity == Infinity//true
      -Infinity == +Infinity//false
      Infinity == -Infinity//false
      Infinity == +Infinity//false
      

(3) String 类型

  • ''单引号、""双引号、``模板字符串
  • 转义字符
  • 字符串的值是不可变的,"变"只不过是生成新的值,销毁原来的值

(4) Object类型

{
	name: 'WcZix'	
} instanceof Object

Object的prototype上有

  • constructor 构造函数(当该对象作为原型使用时需要)
  • hasOwnProperty(propertyName) 参数是否是该对象自身的属性而不是原型的(和 in 的本质区别在后面一段)
  • isPrototypeOf
  • propertyIsEnumerable(propertyName) 属性是否可以枚举,即被for in 遍历获取到
  • toString 、 valueOf、[[ToPrimitive]] 是类型转换的时候默认调用的
1. 对象无法直接和原始类型比较
  • 对象真实存在堆内存中,代码中可操作的也只是其地址,因此对象和原始类型从本质上就不能进行比较
  • 但是为了能够比较,JS对对象绑定了一些方法,是得形式上对象和原始类型能够比较
  • 这就是为什么需要 toString 、 valueOf、[[ToPrimitive]] 等方法
2. toString、valueOf意味着对象希望转换成字符串和数值

[[ToPrimitive]] 是 ES6 新增的,但是本质和valueOf、toString没有太大区别

  • 注意,这里不包括转换Boolean的方法,说明对象默认不应该直接和Boolean比较,即使是和Boolean比较,最后也要转换为字符串和数值

  • toString、valueOf 表示将该对象转换为字符串、数值使用

  • 但是在真正使用的时候调用方式有很大的区别:

    • 当对象由于外部因素需要转换为数值时:该对象先调用valueOf判断是否返回原始类型,若不能则调用toString判断能否返回原始类型若能将结果再次转换为数值
    • 同理,当对象由于外部因素需要转换为字符串时,先toString,再valueOf
    //在第四点代码基础上
    1 / obj // 0.5
    1 + obj // '12'
    
  • toString、valueOf和[[ToPrimitive]]都是可以被重写的

    const obj = {}
    obj.valueOf = function() {
    	return '2' //这里是故意这么写的
    }
    obj.toString = function() {
    	return 2 //这里是故意这么写的
    }
    

    你也能看得出来,他们并不安全,并且返回的值可以是任意的

  • 对象在转换类型的时候,会调用内置的 [[ToPrimitive]] 函数,对于该函数来说,算法逻辑一般来说如下:

    • 如果已经该函数结果是原始类型了,那就不需要转换了
    • 调用 x.valueOf,如果转换为基础类型,就返回转换的值
    • 调用 x.toString,如果转换为基础类型,就返回转换的值
    • 如果都没有返回原始类型

PS:更改 [[ToPrimitive]] 决定对象在转换原始类型时,是否调用valueOf和toString,即更改对象转换原始类型的方案

四、类型转换

(1) null 和 undefined

它们在转换为数值和字符串表现不一致

Number(undefined) // NaN
Number(null)// 0
String(undefined) // 'undefined'
String(null) // 'null'

但是在转换为Boolean一致,都为false

(2) 数值和字符串

其实上面都说完了其它类型的转换,Object的转换其实最终也体现在数值和字符串的转换,因此几乎可以说数值和字符串的转换在程序中是大量存在的,无论是显式或者隐式,

这里就不介绍了,看看书就行,按照标准来,没有太多技巧

五、运算符的偏爱类型

前面说过对象在转换的时候由外部因素决定,其它类型也是如此。但是这个外部因素究竟是谁?运算符的偏爱类型

(1) 计算型运算符

  • +、-、*、/、%
  • –、++

这些运算符中除了+ ,其它都偏爱数值类型,即Number

+ 比较特殊,它偏爱字符串,如果一个操作数是字符串,那么另外一个也要被转换为字符串,如果操作数是对象的话字符串优先

const obj = {}
obj.valueOf = function() {
	return '2' //这里是故意这么写的
}
obj.toString = function() {
	return 2 //这里是故意这么写的
}
1 + obj // '12'

再次看最后一行代码,肯定能感觉到满满的 “不公平”

(2) 比较型运算符

  • >、>=、<、<=、== 偏爱数值

就拿 == 举例

1. 讨论两个操作数类型相同
  • undefined == undefined
  • null == null
  • NaN != NaN 其它都和自己相等(当然要除去不可完全转换的数值,浮点数不准确),比较大小时也是通过数值大小直接比较
  • 字符串逐字比较字符
  • 对象直接比较地址
  • Boolean没什么好说的
2. 讨论两个操作数类型不相同
  • 一个对象的时候,对象转换为原始类型
  • 字符串和Boolean转换都会优先转换为数值
    //字符串转数值,而不是数值转字符串
    1 == '01' //true 
    //Boolean不会直接转成字符串,而是转换成数值之后比较
    true == '0' //false
    

五、结语

类型转换非常复杂,但是如果你清晰了解各种运算符对数据类型的偏好,那掌握起来就很自然和舒服

一些面试题:

  • [] == ![] 输出结果是?
  • {} == !{} 输出结果是?
  • 1 + ‘1’ 输出结果是?
  • true + true 输出结果是?
  • 4 + [] 输出结果是?
  • 4 + {} 输出结果是?
  • 4 + [1] 输出结果是?
  • 4 + [1, 2, 3, 4] 输出结果是?
  • ‘a’ + + 'b’输出结果是?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值