面试官:js只有一个toString吗

这两天我有个小伙伴二面面b站的时候被面试官问到了这个问题,觉得挺有意思的,分享给大家~

jstoString其实不止对象身上的toString方法,虽然传统上我们一般说的toString就是对象身上的,也就是Object.prototype.toString,但其实toString是有三种的

  1. {}.toString()返回由”[object“和class和’]‘组成的字符串
  2. [].toString()返回由数组内部元素以逗号拼接的字符串
  3. xx.toString()直接返回字符串字面量

Object.prototype.toString()

js官方:带注释的 ES5 — Annotated ES5

对于普通对象来说,Object是构造函数,因此此时的toString就是构造函数原型身上的方法,而我们普通对象去寻找身上的属性就是先去构造函数显示具有的属性中去找,这个显示属性就是构造函数自身的属性,找不到时,就去自己自己的隐式原型身上找,而实例对象的隐式原型(__proto__)就是构造函数的显示原型(prototype),因此才能去调用这个toString,而这个toString的作用是用来判断数据类型的

既然是对象,那么就是输出[object Object]

面试官:js只有一个toString吗

数组也是对象,那数组调用这个toString,是否就是输出[object Array],我们来看下

面试官:js只有一个toString吗

哦嚯~,居然不是,是个空

注意:不是空字符串,就是空,因为空格也是字符串

如果数组构造函数Array身上没有写toString,那么这个输出结果一定不是空,而是[object Array],因为他会顺着原型链去找到对象身上的toString

这就是因为官方给数组原型身上已经打造了另一个toString,或者说是重写了个toString

[].toString()

没错!这就是因为数组身上的toString方法,数组里面有什么,就以字符串的方式返回出来

面试官:js只有一个toString吗

xx.toString

好了,既不是数组又不是对象,那么其余的类型就是这个版本的toString,也就是直接返回字符串字面量

那我写个函数函数表达式,看看这个值输出的字符串字面量长什么样子~

面试官:js只有一个toString吗

整个函数体都打上了引号,成了个字符串

其余原始类型如下

(123).toString()
'123'
('dolphin').toString()
'dolphin'
(true).toString()
'true'
(Symbol('hello')).toString()
'Symbol(hello)'
(BigInt(11)).toString()
'11'

注意:undefined和null没有这个方法,调用会报错

[] == 1 true还是false

面试官:js只有一个toString吗

===== 的区别就是在于前者会进行隐式类型转换,后者是严格相等

== 的比较有很多种情况:带注释的 ES5 — Annotated ES5

这里就不带大家一一查看了,总之,这里适用的情形如下

面试官:js只有一个toString吗

对象那一方需要调用 ToPrimitive(x)方法,这个方法我需要单独拿来说下

面试官:js只有一个toString吗

ToPrimitive(x, hint)

如果hintNumber,如下步骤

  1. 如果是基本类型,不进行转换
  2. 否则,调用valueOf方法,如果得到原始值,则返回
  3. 否则,调用toString方法,如果得到原始值,则返回
  4. 否则,报错

如果hintString,如下步骤

  1. 如果是基本类型,不进行转换
  2. 否则,调用toString方法,如果得到原始值,则返回
  3. 否则,调用valueOf方法,如果得到原始值,则返回
  4. 否则,报错

== 最终都是调用ToNumber,也就是说调用hintNumberToPrimitive,因此套用这个规则,[]是引用类型,走到第三步,去调用valueOf,我们都清楚,valueOf的作用是提供包装类,将其转换成原始类型的,因此,走到第三步,调用toString[].toString就是得到一个空,这个空最终再去ToNumber,空转数字就是0,因此最终得到0 == 1,返回false

[] == ![] true还是false

面试官:js只有一个toString吗

这个目测看肯定以为是false,但是在v8眼里,还是需要一步一步来看,首先,取非!的优先级高于==,因此先执行!,!的执行步骤是两个,现将被执行对象转成布尔,其次才是取非,因此,任何引用类型转布尔都是true,因此!true就是false,因此是[] == false , 好了,继续看,==都是要将数据调用ToNumber的,因此这个false就是0

面试官:js只有一个toString吗

现在就是[].ToNumber了,因为是引用类型转数字,所以最后会调用hint为数字的ToPrimitive,因此先valueOf,后再toStringvalueOf不走,因为只对包装类起作用,所以就是走toString,得到一个空,空再去调用ToNumber,得到0,因此最终就是0 == 0,返回true

最后

关于toString,你一定得搞明白,否则js的隐式类型转换你肯定会云里雾里,要是我被问到我肯定也会有点懵逼

如果你对春招感兴趣,可以加我的个人微信:Dolphin_Fung,我和我的小伙伴们有个面试群,可以进群讨论你面试过程中遇到的问题,我们一起解决

另外有不懂之处欢迎在评论区留言,如果觉得文章对你学习有所帮助,还请”点赞+评论+收藏“一键三连,感谢支持!

原文链接:https://juejin.cn/post/7346837205774893090 作者:Dolphin_海豚

(0)
上一篇 2024年3月17日 下午4:10
下一篇 2024年3月17日 下午4:20

相关推荐

发表回复

登录后才能评论