2024年最全关于JS隐式类型转换的完整总结,小白都会

最后

前端CSS面试题文档,JavaScript面试题文档,Vue面试题文档,大厂面试题文档

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

是不是感觉还有Function,毕竟能用typeof获取到?不,函数、数组都是Object的子类型。

类型分为基本类型复合类型两种,除了对象,其它都是基本类型。

To Primitive

============

发音:[ˈprɪmətɪv]

结构:toPrimitive(input: any, preferedType?: ‘string’ |‘number’)

作用:内部方法,将任意值转换成原始值

转换规则:

  1. 如果是基本类型,则不处理。

  2. 调用valueOf(),并确保返回值是基本类型。

  3. 如果没有valueOf这个方法或者valueOf返回的类型不是基本类型,那么对象会继续调用toString()方法。

  4. 如果同时没有valueOf和toString方法,或者返回的都不是基本类型,那么直接抛出TypeError异常。

注意:如果 preferedType=string,那么2、3顺序调换。

接着,我们看下各个对象的转换实现

| 对象 | valueOf() | toString() | 默认 preferedType |

| — | — | — | — |

| Object | 原值 | “[object Object]” | Number |

| Function | 原值 | “function xyz() {…}” | Number |

| Array | 原值 | “x,y,z” | Number |

| Date | 数字 | “Sat May 22 2021…” | String |

  1. 数组的toString()可以等效为join(","),遇到null, undefined都被忽略,遇到symbol直接报错,遇到无法ToPrimitive的对象也报错。

  2. 使用模板字符串或者使用String(...)包装时,preferedType=string,即优先调用 .toString()。

[1, null, undefined, 2].toString() === ‘1,2’;

// Uncaught TypeError: Cannot convert a Symbol value to a string

[1, Symbol(‘x’)].toString()

// Uncaught TypeError: Cannot convert object to primitive value

[1, Object.create(null)].toString()

To Number

=========

一些特殊值转为数字的例子,等下要用到

Number(“0”) === 0;

Number(“”) === 0;

Number(" ") === 0;

Number(“\n”) === 0;

Number(“\t”) === 0;

Number(null) === 0;

Number(false) === 0;

Number(true) === 1;

Number(undefined); // NaN

Number(“x”); // NaN

加减法 ±

======

加减法运算中遵循了一些隐式转换规则:

遇到对象先执行ToPrimitive转换为基本类型,然后按照基本类型的规则处理

// {}.toString() === “[object Object]”

1 + {} === “1[object Object]”

// [2, 3].toString() === “2,3”

1 + [2, 3] === “12,3”

[1] + [2, 3] === “1,2,3”

function test() {}

// test.toString() === “function test() {}”

10 + test === “10function test() {}”

加法过程中,遇到字符串,则会被处理为字符串拼接

上面的对象最后也都转成了字符串,遵循本条规则。接着来几个纯字符串的例子

1 + “1” === “11”

1 + 1 === 2

1 + 1 + “1” === “21”

“1” + 1 === “11”

“1” + “1” === “11”

1 + “1” + 1 === “111”

减法操作时,一律需要把类型转换为Number,进行数学运算

3 - 1 === 2

3 - ‘1’ === 2

‘3’ - 1 === 2

‘3’ - ‘1’ - ‘2’ === 0

// [].toString() => “” => Number(…) => 0

3 - [] === 3

// {}.toString() => “[object Object]” => Number(…) => NaN

3 - {} // NaN

加法操作时,遇到非字符串的基本类型,都会转Number

1 + true === 2

1 + false === 1

1 + null === 1

1 + null + false + 1 === 2

1 + undefined // NaN

1 + undefined + false // NaN

1 + undefined + [1] === “NaN1”

1 + undefined + “1” === “NaN1”

// 1 + false

1 + ![] === 1

1 + !{} === 1

!{} + !{} === 0

+ x 和 一元运算 +x 是等效的(以及- x),都会强制转换成Number
  • 0 === 0
  • 0 === -0

// 1 + (+“1”)

1 + + “1” === 2

// 1 + (+(+(+[“1”])))

1 + + + + [“1”] === 2

// 1 + (-(+(-[1])))

1 + - + - [1] === 2

// 1 - (+(-(+1)))

1 - + - + 1 === 2

1 - + - + - 1 === 0

// 1 + [“”]

1 + + [“”] === 1

// [“1”, “2”].toString() => “1,2” => Number(…) => NaN

1 + + [“1”, “2”] // NaN

// 吃根香蕉???

// “ba” + (+undefined) + “a” => “ba” + NaN + “a”

(“ba” + + undefined + “a”).toLowerCase() === “banana”


回到一开始抛出的问题[] + {},这样太简单了吧?

[].toString() === “”;

{}.toString() === “[object Object]”;

[] + {} === “[object Object]”;

{} 在最前面时可能不再是对象

不是对象是什么?是你的八块腹肌?别急,看看经典的例子

{} + [] === 0;

{ a: 2 } + [] === 0;

这啥玩意?说好的"[object Object]"呢?

好吧,这是{}其实代表的是代码块,最后就变成了+ [],根据前面的原则,数组先被转换成字符串"",接着因为+x的运算,字符串被转成数字0

那 { a: 2 } 总该是对象了吧?其实这时候a不是代表对象属性,而是被当成了标签(label),标签这东西IE6就已经有了。所以如果我们写成对象是会报错的,逗号要改成分号才能通过编译。

// Uncaught SyntaxError: Unexpected token ‘:’

{ a: 2, b: 3 } + []

// 分号OK

{ a: 2; b: 3 } + [] === 0;

⚠️注意:在 Node >= 13.10.0 的版本,{}被优先解释为空对象,仅在非对象结构的情况才会被认为是代码块。

// nodeJs >= 13.10.0 的运行结果

{} + [] === “[object Object]”;

{ a: 2 } + [] === “[object Object]”;

{ a: 2, b: 3 } + [] === “[object Object]”;

// 注意是分号,当成代码块

{ a: 2; b: 3 } + [] === 0;

// 有JS语句或者表达式,当成代码块

{ var a = 1; } + [] === 0;

{ ; } + [] === 0;

{ 123 } + [] === 0;

{ 1 + 2 } + [] === 0;

定论还是下的太早了,我们还是有办法让引擎优先处理成代码块

// 所有node版本

;{} + [] === 0;

;{ a: 2 } + [] === 0;

// Uncaught SyntaxError: Unexpected token ‘:’

;{ a: 2, b: 3 } + [];

加个分号?有趣。


在使用这个刺激的规则前,你需要记住的是,代码块 {} 必须在最前面,否则它就是对象,但也有特例(分号)。

console.log({} + []); // “[object Object]”

alert({} + []); // “[object Object]”

function test(x) { console.log(x); }

test({} + []); // “[object Object]”

var result = {} + [];

console.log(result); // “[object Object]”

({}) + [] === “[object Object]”

!{} // !对象 => false

{} // 对象

{ a: 2 } // 对象

{ a: 2, b: 3 } // 对象

{ a: 2; b: 3 } // 代码块

;{ a: 2 } // 代码块

{ a: 2 }; // 代码块

symbol不能加减

如果在表达式中有symbol类型,那么就会直接报错。比如1 + Symbol("x")报错如下:

Uncaught TypeError: Cannot convert a Symbol value to a number

宽松相等 ==

=======

相等于全等都需要对类型进行判断,当类型不一致时,宽松相等会触发隐式转换。下面介绍规则:

对象与对象类型一致,不做转换

{} != {}

[] != {}

[] != []

对象与基本类型,对象先执行ToPrimitive转换为基本类型

// 小心代码块

“[object Object]” == {}

[] == “”

[1] == “1”

[1,2] == “1,2”

文末

从转行到现在,差不多两年的时间,虽不能和大佬相比,但也是学了很多东西。我个人在学习的过程中,习惯简单做做笔记,方便自己复习的时候能够快速理解,现在将自己的笔记分享出来,和大家共同学习。

个人将这段时间所学的知识,分为三个阶段:

第一阶段:HTML&CSS&JavaScript基础

第二阶段:移动端开发技术

第三阶段:前端常用框架

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 推荐学习方式:针对某个知识点,可以先简单过一下我的笔记,如果理解,那是最好,可以帮助快速解决问题;

  • 大厂的面试难在,针对一个基础知识点,比如JS的事件循环机制,不会上来就问概念,而是换个角度,从题目入手,看你是否真正掌握。所以对于概念的理解真的很重要。

方便自己复习的时候能够快速理解,现在将自己的笔记分享出来,和大家共同学习。

个人将这段时间所学的知识,分为三个阶段:

第一阶段:HTML&CSS&JavaScript基础

第二阶段:移动端开发技术

第三阶段:前端常用框架

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 推荐学习方式:针对某个知识点,可以先简单过一下我的笔记,如果理解,那是最好,可以帮助快速解决问题;

  • 大厂的面试难在,针对一个基础知识点,比如JS的事件循环机制,不会上来就问概念,而是换个角度,从题目入手,看你是否真正掌握。所以对于概念的理解真的很重要。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值