使 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 基础知识点,好了,你(这道题)可以毒发身亡了。

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

地址:前端面试题库

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

redis远程连接不上解决办法

问题描述: redis远程服务端运行在192.168.3.90计算机上,客户端计算机(ip:192.168.3.110)通过redsi-cli.exe客户端工具连接时,没有反应,连接不上。 如图所示: 解决步骤: 步骤一&…

UE5 植物生长材质_树根像目标缠绕(记录备忘)

需要在三维软件中将树根缠绕物体的形态预先做好,将管状树根uv方形排布,模型默认材质为渐变上黑下白,导入引擎,注意制作树根尖端需要将左侧Masked数值由0.333修改为0

Java根据模板文件生成excel文件,同时将excel文件转换成图片

需求 需要将指定数据导出成表格样式的图片&#xff0c;如图 业务拆解 定义一个导出模板将得到的数据填入模板中&#xff0c;生成excel文件将ecxel文件转换成png格式的图片 代码实现 需要引入的依赖 <dependency><groupId>cn.hutool</groupId><artif…

6、梯度提升XGBoost(eXtreme Gradient Boosting)

XGBoost梯度提升 结构化数据最精确的建模技术。 在本节课中,我们将学习如何使用梯度增强来构建和优化模型。这种方法在Kaggle的许多竞争中占据主导地位,并在各种数据集上获得了最先进的结果。 本课程所需数据集夸克网盘下载链接:https://pan.quark.cn/s/9b4e9a1246b2 提取码…

JavaScript之ES6新特性02

模板字符串 模板字符串&#xff08;template string&#xff09;是增强版的字符串&#xff0c;用反引号&#xff08;&#xff09;标识。它可以当作普通字符串使用&#xff0c;也可以用来定义多行字符串&#xff0c;或者在字符串中嵌入变量 。 模版字符串特点 内容中可以直接…

【机器学习】调配师:咖啡的完美预测

有一天&#xff0c;小明带着一脸期待找到了你这位数据分析大师。他掏出手机&#xff0c;屏幕上展示着一份详尽的Excel表格。“看&#xff0c;这是我咖啡店过去一年的数据。”他滑动着屏幕&#xff0c;“每个月的销售量、广告投入&#xff0c;还有当月的气温&#xff0c;我都记录…

【C++提高编程(二)】

一、STL初识 1.1、STL的诞生 长久以来&#xff0c;软件界一直希望建立一种可重复利用的东西 C的面向对象和泛型编程思想&#xff0c;目的就是复用性的提升 大多情况下&#xff0c;数据结构和算法都未能有一套标准,导致被迫从事大量重复工作 为了建立数据结构和算法的一套标…

如何自学Python:一份详细的指南

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;有感而谈⛺️稳中求进&#xff0c;晒太阳 引言 Python是一种广泛使用的高级编程语言&#xff0c;以其简洁明了的语法和强大的功能而受到许多程序员的喜爱。无论是数据分析、网络开发&#…

【教程】React-Native代码规范与加固详解

引言 React Native 是一种跨平台的移动应用开发框架&#xff0c;由 Facebook 推出。它可以让我们使用 JavaScript 和 React 语法编写原生应用&#xff0c;大大提高了移动应用的开发效率。但是&#xff0c;对于开发人员来说&#xff0c;代码规范和安全性也是非常重要的问题。本…

C++ memmove 学习

memmove&#xff0c;将num字节的值从源指向的位置复制到目标指向的内存块。 允许目标和源有重叠。 当目标区域与源区域没有重叠则和memcpy函数功能相同。 宽字符版本是wmemmove&#xff0c;安全版本加_s&#xff1b; #include "stdafx.h" #include<iostream&g…

Eureka使用详解

介绍主要特点主要功能与常用服务注册中心的比较Eureka与Zookeeper的区别和联系Eureka与Nacos的区别与联系Eureka与Consul的区别与联系 安装部署Eureka与CAP理论Eureka实现实时上下线Eureka常用注解Eureka架构模式 介绍 Eureka是一个基于REST的服务&#xff0c;主要用于AWS云中…

rem布局

1.0 rem基础 1.1 em单位(了解) 结论1&#xff1a;1em默认字体大小是16像素 结论2: em这个单位会默认参考父元素字体大小为基准 <head><style>/* 结论1: 1em默认字体大小是16像素结论2: em这个单位会默认参考父元素字体大小为基准*//* html {如果根元素默认字体…

面试2024.1.20

简单介绍下你做的项目。 这个神领物流项目是一个前后端分离的项目&#xff0c;前段他有3个客户端&#xff08;用户端为微信小程序、司机端和快递员端为app&#xff09;一个管理端&#xff08;pc&#xff09;&#xff0c;后端用的技术栈用的是SpringAlibabaCloud、数据库用的是M…

ABC337 A-G

Toyota Programming Contest 2024#1&#xff08;AtCoder Beginner Contest 337&#xff09; - AtCoder 手速五题之后看FG&#xff0c;一看榜G过的比F多...两题都有思路然后先开写了F像是大模拟写了一堆bug&#xff0c;赛后对拍调bug调完疯狂re&#xff0c;发现是对数组双倍操作…

Django开发_14_后台管理及分页器

一、后台管理 &#xff08;一&#xff09;登录 http://127.0.0.1:8000/admin/ &#xff08;二&#xff09;创建超级用户 manage.py createsuperuser &#xff08;三&#xff09;注册模型 admin.py&#xff1a; models [model1&#xff0c;model2&#xff0c;model3 ]ad…

VScode新增设备实现无感接入(不需要输入密码)

VScode远程开发接入设备&#xff0c;默认是需要输入密码的&#xff0c;但是日常开发中刷新就需要重新输入密码&#xff0c;很烦人。配置ssh的RSA密钥后会&#xff0c;就可以直接系统级别验证接入&#xff0c;对开发人员来说验证步骤就透明了&#xff0c;实现无感接入&#xff0…

Object.prototype.toString.call个人理解

文章目录 这段代码的常见用处参考文献&#xff1a; 拆分理解1、Object.prototype.toString小问题参考文献&#xff1a; 2、call函数的作用参考文献 3、继续深入一些&#xff08;这部分内容是个人理解&#xff0c;没有明确文献支撑&#xff09; 这段代码的常见用处 Object.prot…

力扣645.错误的集合

一点一点地刷&#xff0c;慢慢攻克力扣&#xff01;&#xff01; 王子公主请看题 集合 s 包含从 1 到 n 的整数。不幸的是&#xff0c;因为数据错误&#xff0c;导致集合里面某一个数字复制了成了集合里面的另外一个数字的值&#xff0c;导致集合 丢失了一个数字 并且 有一个数…

el-upload中的before-upload不生效

我们先来看看官方对before-upload的定义 before-upload是在上传文件时触发&#xff0c;不是添加文件时触发&#xff0c;添加文件时触发 on-change。 所以如果我们要在添加文件时&#xff0c;对文件的大小和后缀等等进行判断&#xff0c;可以用 on-change 方法来实现。 checkSu…

​WordPress顶部管理工具栏怎么添加一二级自定义菜单?

默认情况下&#xff0c;WordPress前端和后台页面顶部都有一个“管理工具栏”&#xff0c;左侧一般就是站点名称、评论、新建&#xff0c;右侧就是您好&#xff0c;用户名称和头像。那么我们是否可以在这个管理工具栏中添加一些一二级自定义菜单呢&#xff1f; 其实&#xff0c…