面试官: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,我和我的小伙伴们有个面试群,可以进群讨论你面试过程中遇到的问题,我们一起解决

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

相关推荐
轻口味1 小时前
命名空间与模块化概述
开发语言·前端·javascript
前端小小王2 小时前
React Hooks
前端·javascript·react.js
迷途小码农零零发2 小时前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
娃哈哈哈哈呀2 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
旭东怪3 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
ekskef_sef4 小时前
32岁前端干了8年,是继续做前端开发,还是转其它工作
前端
sunshine6415 小时前
【CSS】实现tag选中对钩样式
前端·css·css3
真滴book理喻5 小时前
Vue(四)
前端·javascript·vue.js
蜜獾云5 小时前
npm淘宝镜像
前端·npm·node.js