JavaScript隐式类型转换

栏目: JavaScript · 发布时间: 5年前

内容简介:ECMAScript 一共定义了七种每一种基本类型JavaScript 语言设计上试图模糊对象和基本类型之间的关系,比如,我们可以直接在基本类型上使用对象的方法:

JavaScript隐式类型转换

基本数据类型

ECMAScript 一共定义了七种 build-in types ,其中六种为 Primitive ValueNullUndefinedStringNumberBooleanSymbol 。而最后一种 Object build-in type 与通常意义上的 JavaScript 中 Object 并不一样,总的来说,只要不属于 Primitive Value 的值,就属于 Object 类型,比如数组、对象、日期、正则、函数。

装箱转换

每一种基本类型 number , string , boolean , symbolObject(build-in type) 中都有对应的类。所谓装箱转换,正是把基本类型转换为对应的对象,他是类型转换中一种相当重要的种类。

JavaScript 语言设计上试图模糊对象和基本类型之间的关系,比如,我们可以直接在基本类型上使用对象的方法:

console.log('abc'.charAt()); // a

甚至我们在原型上添加方法,都可以应用于基本类型。

实际上是 . 运算符提供了装箱操作,它会根据基础类型构造一个临时对象,使得我们能在基础类型上调用对应对象的方法。

拆箱转换

在 JavaScript 标准中,规定了 ToPrimitive 函数,它是对象类型到基本类型的转换(即,拆箱转换)。

对象到 String 和 Number 的转换都遵循“先拆箱再转换”的规则。通过拆箱转换,把对象变成基本类型,再从基本类型转换为对应的 String 或者 Number。

拆箱转换会尝试调用 valueOf 和 toString 来获得拆箱后的基本类型。如果 valueOf 和 toString 都不存在,或者没有返回基本类型,则会产生类型错误 TypeError。

ToPrimitive

ToPrimitive 用于将 Object 转为 Primitive Value

对于我们平常遇到的 Object,其处理逻辑是:

  • 调用 Object.valueOf ,如果结果是 Primitive Value ,则返回;
  • 调用 Object.toString ,如果结果是 Primitive Value ,则返回;
  • 都不是,返回 TypeError

普通对象和数组的这两个方法返回的结果如下:

var a = [12]
var b = {a: 123}

// [12]
a.valueOf()

// '12'
a.toString()

// {a: 123}
b.valueOf()

// '[object Object]'
b.toString()

如上,两者的 valueOf 返回的都不是 Primitive Value (返回了自身,还是 Object 类型)。那么,根据规范,两者调用 ToPrimitive 返回的将是一个 字符串

显示类型转换

ToBoolean

这个方法用于将不是 Boolean 类型的值转换为 Boolean 类型。

  • Undefined 返回 false
  • Null 返回 false
  • 所有 Object 类型都会被转换为 true;
  • Number 类型中,0,NaN 会被转换为 false,其它都为 true
  • 只有空字符串为 false,其它都为 true

ToNumber

其它类型转换为 Number 类型。

  • Undefined 返回 NaN
  • Null 返回 0
  • Boolean 类型, true 为 1; false 为 0
  • String 类型,如果满足数字语义则转为数字,否则转换为 NaN
  • Object 类型,先转换为 Primitive Value 再递归调用自身 ToNumber 来转换。
// '56' ==> 56
Number([56])

// ',56' ==> NaN
Number([,56])

// '55,56' ==> NaN
Number([55, 56])

ToString

Number
Boolean
Undefined
Null

隐式类型转换

了解了上面的知识,可以开始进入我们的正题了,在 JavaScript 中可以触发隐式类型转换的操作有:

  • 四则运算: + , - , * , /
  • 比较运算符: == , < , > , >= , <=
  • 判断语句: if , while
  • Native调用: console , alet 输入时会自动转换成 String 类型
  • 逻辑非 ! ,将直接调用 ToBoolean 方法,然后取反返回。

比较运算符

非严格比较(==)

  • 如果 Type 相同,等价于 A === B
  • 特别的, undefined == null
  • String == Number ,则把 String 转换成 Number
  • Boolean 值的,将 Boolean 转换成 Number
  • Object String/Number/Symbol ,将 Object 转换成 Primitive Value
  • 否则,返回 false
// '12' ==> 12;
// 返回 true
12 == '12'

// 转 boolean: [] == 0
// 转 object: '' == 0
// 转 string: 0 == 0
// 返回 true
[] == false

// 转 object: '45' == 45
// 转 string: 45 == 45
// 返回 true
[45] == 45

// 单目: {} == false
// 转 boolean: {} == 0
// 转 object: '[object Object]' == 0
// 转 string: NaN == 0
// 返回 false
{} == !{}

// 单目:[] == fasle
// 转 boolean: [] == 0
// 转 array: "" == 0
// 转 string: 0 == 0
// 返回 true
[] == ![]

[] == []
[] == 0

严格比较 (===)

  • 类型不同,直接返回 false
  • Number 类型判断:有 NaN 就 false;
  • 特别的 +0 === -0;
  • 最后调用 SameValueNonNumber

另外 != 和 !== 则是指出了 A != B 与 !(A == B) 是完全等价的。在判断 !=/!== 时,其实就是在判断 ==/===.

不等关系

  • 两边操作数调用 ToPrimitive 转换为 Primitive Value
  • 由于 Primitive Value 出来有 StringNumber 两种结果,分别有不同的比较规则;

    1. 如果两边的值都是 String,则 按 code unit 比较,
    2. 如果一边是 Number,则将另一边也转换为 Number;注意 Number 需要处理 +0/-0/NaN/Infinity 等情况
// 注意转换后为 '45' < '46'
// 按字符串规则比较 最终比较的是 '5'.charCodeAt() < '6'.charCodeAt() => 53 < 54
// 返回 true
[45] < [46]

// 同理 [10] < [9] 最后进行的是 '10' < '9' 的比较,是字符串之间的笔记,不会转换为数字间的比较,
// 其实最终比较的是 '1'.charCodeAt() < '9'.charCodeAt() => 49 < 57.
[10] < [9]

练习题

// 每个表达式是 true 还是 false 呢?为啥呢?

// 初阶
!{}
12 == '12'
'false' == false
null == undefined

// 高阶
[] == []
[] == false
[] === false
[45] == 45

// 终阶
[45] < [46] ?
[10] < [9] ?
{} == !{}
{} != {}
-0 === +0
NaN === NaN
NaN != NaN

// 转换条件 转换后类型 结果
[]+[] // String “”
[1,2]+[3,4] // String “1,23,4”
[]+{} // String “[object Object]”
[1,2] + {a:1} // String “1,2[object Object]”
{}+[] // Number 0
{}+[1] //Number 1
{a:1}+[1,2] // Number NaN
{a:1}+{b:2} // Chrome - String “[object Object][object Object]” (背后实现eval)
{a:1}+{b:2} // Firefox - Number NaN
true+true // Number 2
1+{a:1} // String “1[object Object]”

reference

JavaScript 中的隐式类型转换的规范

JavaScript 运算符规则与隐式类型转换详解

JavaScript类型:关于类型,有哪些你不知道的细节?

深入浅出弱类型JS的隐式转换

JavaScript字符串间的比较

ecma-sec-relational-operators


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Out of their Minds

Out of their Minds

Dennis Shasha、Cathy Lazere / Springer / 1998-07-02 / USD 16.00

This best-selling book is now available in an inexpensive softcover format. Imagine living during the Renaissance and being able to interview that eras greatest scientists about their inspirations, di......一起来看看 《Out of their Minds》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

MD5 加密
MD5 加密

MD5 加密工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试