针对高级前端的八个级JavaScript面试问题( 三 )


在像字符串连接或算术运算这样的场景中与对象一起工作时,这种转换至关重要 。为了实现这一点,JavaScript 依赖两个特殊的方法:valueOf 和 toString
valueOf 方法是JavaScript对象转换机制的一个基础部分 。当一个对象在需要基本值的上下文中被使用时,JavaScript 首先会在对象内部查找valueOf方法 。在valueOf方法不存在或不返回适当的基本值的情况下 , JavaScript会退回到toString方法 。这个方法负责提供对象的字符串表示形式 。
回到我们最初的代码片段:
const obj = {  valueOf: () => 42,  toString: () => 27};console.log(obj + '');当我们运行这段代码时,对象obj被转换为一个基本值 。在这种情况下 , valueOf 方法返回42,然后由于与空字符串的连接,它被隐式地转换为字符串 。因此 , 代码的输出将是 42
然而,在valueOf方法不存在或不返回适当的基本值的情况下,JavaScript会退回到toString方法 。让我们修改之前的示例:
const obj = {  toString: () => 27};console.log(obj + '');在这里 , 我们已经移除了 valueOf 方法,只留下了返回数字27toString方法 。在这种情况下,JavaScript 将依赖 toString 方法进行对象转换 。
6-理解对象键(Object Keys)当在JavaScript中使用对象时 , 理解键是如何在其他对象的上下文中被处理和分配的非常重要 。考虑以下代码片段,并花点时间猜测输出:
let a = {};let b = { key: 'test' };let c = { key: 'test' };a[b] = '123';a[c] = '456';console.log(a);乍一看,这段代码似乎应该生成一个具有两个不同键值对的对象a 。然而,由于JavaScript对对象键的处理方式,结果完全不同 。
JavaScript 使用默认的toString()方法将对象键转换为字符串 。为什么呢?在JavaScript中 , 对象键总是字符串(或 symbols),或者通过隐式强制转换自动转换为字符串 。当你在对象中使用除字符串之外的任何值(例如,数字、对象或符号)作为键时,JavaScript将在使用它作为键之前内部将该值转换为其字符串表示形式 。
因此,当我们在对象a中使用对象bc作为键时,两者都转换为相同的字符串表示形式:[object Object] 。由于这种行为,第二个赋值a[c] = '456';会覆盖第一个赋值a[b] = '123';
最终,当我们记录对象a时,我们观察到以下输出:
{ '[object Object]': '456' }7-双等号运算符console.log([] == ![]);这个有点复杂 。那么,你认为输出会是什么呢?
这个问题相当复杂 。那么,你认为输出结果会是什么呢?让我们一步一步地来评估 。首先,让我们看一下两个操作数的类型:
typeof([]) // "object"typeof(![]) // "boolean"对于 [],它是一个对象,这是可以理解的 , 因为在JavaScript中,包括数组和函数在内的一切都是对象 。但操作数 ![] 是如何具有布尔类型的呢?让我们尝试理解一下 。当你使用 ! 与一个原始值(primitive value)一起时 , 会发生以下转换:

  • Falsy Values(假值):如果原始值是一个假值(例如 false0nullundefinedNaN 或一个空字符串 ''),应用 ! 将把它转换为 true 。
  • Truthy Values(真值):如果原始值是一个真值(即任何不是假值的值),应用 ! 将把它转换为 false 。
在我们的案例中,[] 是一个空数组 , 这在JavaScript中是一个真值 。因为 [] 是真值,![] 变成了 false 。因此 , 我们的表达式变为:
[] == ![][] == false现在,让我们继续了解 == 运算符 。当使用 == 运算符比较两个值时 , JavaScript会执行“抽象相等性比较算法(Abstract Equality Comparison Algorithm)” 。这个算法会考虑比较值的类型并进行必要的转换 。


推荐阅读