面试官: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]

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

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

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

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

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

[].toString()

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

xx.toString

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

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

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

其余原始类型如下

scss 复制代码
(123).toString()
'123'
('dolphin').toString()
'dolphin'
(true).toString()
'true'
(Symbol('hello')).toString()
'Symbol(hello)'
(BigInt(11)).toString()
'11'

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

[] == 1 true还是false

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

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

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

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

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

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

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

最后

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

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

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

相关推荐
Myli_ing1 小时前
HTML的自动定义倒计时,这个配色存一下
前端·javascript·html
dr李四维1 小时前
iOS构建版本以及Hbuilder打iOS的ipa包全流程
前端·笔记·ios·产品运营·产品经理·xcode
ifanatic1 小时前
[面试]-golang基础面试题总结
面试·职场和发展·golang
I_Am_Me_1 小时前
【JavaEE进阶】 JavaScript
开发语言·javascript·ecmascript
雯0609~1 小时前
网页F12:缓存的使用(设值、取值、删除)
前端·缓存
℘团子এ2 小时前
vue3中如何上传文件到腾讯云的桶(cosbrowser)
前端·javascript·腾讯云
学习前端的小z2 小时前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
程序猿进阶2 小时前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
前端百草阁2 小时前
【TS简单上手,快速入门教程】————适合零基础
javascript·typescript
彭世瑜2 小时前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript