使 a === 1 a === 2 a === 3 为 true 的几种“下毒“方法

前言

这算得上是近些年的前端网红题了,曾经对这种网红题非常抵触,认为非常没有意义。

看到了不少人有做分享,有各种各样的方案,有涉及到 JS 非常基础的知识点,也不得不感叹解题者的脑洞之大。

但是,拿来做面试题为难没有看过的面试者,就非常非常不地道了。

鹤顶红

鹤顶红是武侠剧中出现最多的毒药,真的是江湖出行必备的毒药。

正常情况下,如果 let a = 1; 则,表达式的后半段必不成立。但是容易想到如果在每个阶段自增后,表达式是可能成立的。

let a = 1;  
a++ === 1 && a++ === 2 && a++ === 3; // true  

可是这就属于把题改了,我们需要把自增的逻辑藏起来。由于 a 是基础类型,我们基本上不可能对其做什么改造了。

但是我们如果把 a 定义到 window 上,再加上诸如 Object.defineProperty 的 api,是能够做到的。

let tmp = 1;  
Object.defineProperty(window, 'a', {  get: function () {  return tmp++;  },  
})  
a === 1 && a === 2 && a === 3; // true  

由于 defineProperty 的限制,我们不能把 1 作为 value, 设置在属性描述符号内部,不得不外部定义一个变量。

defineProperty 在诸如 Vue2 的框架中,用的非常多,几乎是面试高频会被问到的,所以这种“毒药”是你行走前端江湖必备的。

曼陀罗

曼陀罗这个名字颇具异域风情、《神雕侠侣》中杨过就是中了此毒。

说到这里我是要将此题改为另一道类似的题目:使 a == 1 && a == 2 && a == 3 返回 true

将严格相等改为了普通的相等,因为通常代码规范中要求使用严格相等,导致 == 不常写,故将此命名为这个异域的名字。

正因为是不严格相等,我们可以利用 JS 中的类型转换机制来下毒。

这个机制是这样的:

  • 如果两个值类型相同,则之间进行比较,和全等是一样的。
  • 如果一个是 null,另一个是 undefined,则相等。
  • 如果一个是数值,另一个是字符串,把字符串转换为数值,再比较转换后的数值。
  • 如果一个是 true,把它转成 1,再比较。
  • 如果一个是 false,把它转成 0,再比较。
  • 如果一个是对象,另一个是数值或字符串,会将对象转换为原始值,再比较。用到的是 valueOf() 和 toString() 方法。

我们可以利用最后一点解这个题:

const a = {  value: 1,  valueOf: function () {  return this.value++;  },  
}  
a == 1 && a == 2 && a == 3;  

先前提到的那种解法必然也可以解这道题,但是这个写法不能用于上一道题,因为全等不会触发类型转换。

十香软筋散

此毒无色无香,药性一发作便全身筋骨酸软,数日后虽行动如常,内力半点发挥不出。毒药和解药表面无异,若中毒者再服毒药则气绝身亡。

const a‌ = 1;  
const a‍ = 2;  
const a = 3;  
a‌ === 1 && a‍ === 2 && a === 3  

你可能会说:“这段代码应该是会报错的!”。但是相信我,你复制到控制台执行一下试试。注意我这里有一个 a 是正常的 a,如果你有执行过上面别的方法,注意先刷新一下窗口。

是的 const 声明的是常量,理应抛出错误:Identifier 'haha' has already been declared

实际上,我这里定义的三个 a 是不同的变量,有一个是 a, 一个是 ax, 一个是 ay,其中 x, y 是被我替换为 unicode 里不可见的字符,所以在上面的代码里看到的都是 a 的形式。

我目前正在使用 webstorm 编辑这篇文章,我也发现了这些不可见字符会在编辑器里显示出来“怪怪的”,如果你也打开这篇 markdown,你会发现:

构造变量名称(唯一标识符)的通用规则是:

  • 名称可包含字母、数字、下划线和美元符号
  • 名称必须以字母开头
  • 名称也可以 $ 和 _ 开头
  • 名称对大小写敏感(y 和 Y 是不同的变量)
  • 保留字(比如 JavaScript 的关键词)无法用作变量名称

实际上,使用中文,甚至是 emoji 表情作为变量名称都是合法的,所以这里可以使用不可见的 unicode 字符作为变量名。

当然,如果想要运行正确,我们得偷偷的把题改了,使用我们新声明的变量,虽然它们看起来一摸一样。

这种“下毒”,真是无色无味,正像软筋散一样。

总结

这边汇总了二个针对原题的解法:通过使用 Object.defineProperty 和利用变量名称的规则的方法;

以及对它的变种题目:通过对象类型转化时默认调用 valueOf 函数的机制。

这道题至少也算给我们带来了三个 JS 基础知识点,好了,你(这道题)可以毒发身亡了。

前端面试题库 (面试必备)            推荐:★★★★★

地址:前端面试题库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/419019.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录二刷 | 二叉树 | 修剪二叉搜索树

代码随想录二刷 | 二叉树 | 修剪二叉搜索树 题目描述解题思路代码实现 题目描述 669.修剪二叉搜索树 给定一个二叉搜索树,同时给定最小边界 L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>L) 。你可能需要改变树的根节点&…

立体视觉几何(一)

1.什么是立体视觉几何 立体视觉对应重建: • 对应:给定一幅图像中的点pl,找到另一幅图像中的对应点pr。 • 重建:给定对应关系(pl, pr),计算空间中相应点的3D 坐标P。 立体视觉:从图像中的投影恢复场景中点…

一台手机用4年多,国产手机从态度傲慢到跪求消费者换机

分析机构trendforce公布的数据指出,中国消费者的换机周期已延长到51个月,面对消费者对国产手机用脚投票,如今国产手机企业开始采取多方举措,祈求消费者买手机,市场的变化促使国产手机不得不改变态度。 2010年国产手机刚…

VM使用教程--SDK取图 视频笔记

本笔记均由海康机器人官网的V学院视频中记录所得,属于省流大师了[doge] 图像采集 图像采集包括1图像源,2多图采集,3输出图像,4缓存图像,5光源 1图像源 图像源包括本地图像,相机采图,SDK 本…

二维旋转公式推导+旋转椭圆的公式推导

二维旋转公式推导+旋转椭圆的公式推导 二维旋转公式推导旋转椭圆的公式推导二维旋转公式推导 x , y x,y x,y表示二维坐标系中原坐标点, x ′ , y ′ x,y x′,y′表示逆时针旋转 β \beta β之后的坐标点: x ′ = x cos ⁡ ( β ) − y sin ⁡ ( β ) y ′ = y cos ⁡ ( β )…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《基于混合博弈的配电网与多综合能源微网优化运行》

本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 这个标题涉及到配电网和多综合能源微网的优化运行,而优化的方法基于混合博弈理论。让我们逐步解读这个标题的关键部分: 基于混合…

QT+opencv源码编译

时间记录:2024/1/20 一、版本介绍 QT5.12.7cmake3.22.0opencv4.5.4 二、编译步骤 (1)下载opencv源码,然后安装,opencv的安装即对源码的解压过程,解压后的文件目录如下 (2)openc…

【C++】vector容器接口要点的补充

接口缩容 在VS编译器的模式下&#xff0c;类似于erase和insert接口的函数通常会进行缩容&#xff0c;因此&#xff0c;insert和erase行参中的迭代器可能会失效。下图中以erase为例&#xff1a; 代码如下&#xff1a; #include <iostream> #include <vector> #inclu…

Leetcode2829. k-avoiding 数组的最小总和

Every day a Leetcode 题目来源&#xff1a;2829. k-avoiding 数组的最小总和 解法1&#xff1a;贪心 哈希 从 1 开始枚举数 x&#xff0c;如果 k - x 不在哈希表里&#xff0c;说明可以插入 k-avoiding 数组&#xff0c;sum 加上 x&#xff0c;向哈希表插入 x。 当哈希表…

131. 分割回文串 - 力扣(LeetCode)

问题描述 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。 输入示例 s "aab"输出示例 [["a","a","b"],["…

分布式锁的产生以及使用

日常开发中&#xff0c;针对一些需要锁定资源的操作&#xff0c;例如商城的订单超卖问题、订单重复提交问题等。 都是为了解决在资源有限的情况限制客户端的访问&#xff0c;对应的是限流。 单节点锁问题 目前针对这种锁资源的情况采取的往往是互斥锁&#xff0c;例如 java 里…

高性能跨平台网络通信框架 HP-Socket v5.9.5

项目主页 : http://www.oschina.net/p/hp-socket开发文档 : https://www.docin.com/p-4478351216.html下载地址 : https://github.com/ldcsaa/HP-SocketQQ Group: 44636872, 663903943 v5.9.5 更新 一、主要更新 问题修复&#xff1a;由于 v5.9.4 版本升级了 KCP 导致 UDP AR…