使 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 === 1 a === 2 a === 3 为 true 的几种“下毒“方法
前言 这算得上是近些年的前端网红题了,曾经对这种网红题非常抵触,认为非常没有意义。 看到了不少人有做分享,有各种各样的方案,有涉及到 JS 非常基础的知识点,也不得不感叹解题者的脑洞之大。 但是,拿来…...

Canny边缘检测 双阈值检测理解
问题引入 我们用一个实际例子来引入问题 import cv2 import numpy as npimgcv2.imread("test.png",cv2.IMREAD_GRAYSCALE) # 修改图像大小 show cv2.resize(img,(500,500))v1cv2.Canny(show,120,250) v2cv2.Canny(show,50,100)# 连接图像 res np.hstack((v1,v2)…...

自动化测试:5分钟了解Selenium以及如何提升自动化测试的效果
在快节奏的技术世界里,自动化测试已经成为确保 Web 应用程序质量和性能的重要手段。自动化测试不仅加快了测试过程,还提高了测试的重复性和准确性。Selenium,作为领先的自动化测试工具之一,为测试人员提供了强大的功能来模拟用户在…...

【MySQL】——关系数据库标准语言SQL(大纲)
🎃个人专栏: 🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客 🐳Java基础:Java基础_IT闫的博客-CSDN博客 🐋c语言:c语言_IT闫的博客-CSDN博客 🐟MySQL:…...

力扣hot100 最长有效括号 动态规划
Problem: 32. 最长有效括号 文章目录 思路Code 思路 👨🏫 参考题解 Code ⏰ 时间复杂度: O ( n ) O(n) O(n) 🌎 空间复杂度: O ( n ) O(n) O(n) class Solution {public int longestValidParentheses(String s){int n s.length();…...
@RequestBody注解基础
RequestBody RequestBody注解一般与post方法使用。 一个请求中只能存在一个RequestBody注解。 RequestBody 用于接收前端传递给后端的json字符串中的数据。(处理json格式的数据) 语法格式: (RequestBody Map map) (RequestBody Object obje…...

前端基础面试题大全
一、Vue 文章目录 一、Vue1、vue 修改数据页面不重新渲染**数组/对象的响应式 ,vue 里面是怎么处理的?** 2、生命周期Vue 生命周期都有哪些?父子组件生命周期执行顺序 3、watch 和 computed 的区别4、组件通信(组件间传值…...

第一讲_HarmonyOS应用开发环境准备
HarmonyOS应用开发环境准备 1. 知识储备2. 环境搭建2.1 安装node.js2.2 配置node.js2.3 安装命令行工具2.4 安装DevEco Studio2.5 配置DevEco Studio 1. 知识储备 HarmonyOS提供了一套UI开发框架,即方舟开发框架(ArkUI框架)。方舟开发框架可…...
一、可行性研究报告模板(软件工程)
一、可行性研究报告 1.引言 1.1编写目的 1.2项目背景 1.3定义 1.4参考资料 2.可行性研究的前提 2.1要求 2.2目标 2.3条件、假定和限制 2.4可行性研究方法 2.5决定可行性的主要因素 3.对现有系统的分析 3.1处理流程…...

DBA技术栈MongoDB:简介
1.1 什么是MongoDB? MongoDB是一个可扩展、开源、表结构自由、用C语言编写且面向文档的数据库,旨在为Web应用程序提供高性能、高可用性且易扩展的数据存储解决方案。 MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当…...

贪心算法 ——硬币兑换、区间调度、
硬币兑换: from book:挑战程序设计竞赛 思路:优先使用大面额兑换即可 package mainimport "fmt"func main() {results : []int{}//记录每一种数额的张数A : 620B : A//备份cnts : 0 //记录至少需要多少张nums : []int{1, 5, 10, 5…...

【已解决】namespace “Ui“没有成员 xxx
先说笔者遇到的问题,我创建一个QWidget ui文件,然后编辑的七七八八后,想要用.h与.cpp调用其,编译通过,结果报了这个错误,本方法不是普适性,但是确实解决了这个鸟问题。 问题来源 搭建ui后&…...

Spring Bean 生命周期的执行流程?
一、问题解析 Spring 生命周期全过程大致分为五个阶段:创建前准备阶段、创建实例阶段、依赖注入阶段、容器缓存阶段和销毁实例阶段。 这张是 Spring Bean 生命周期完整流程图,其中对每个阶段的具体操作做了详细介绍: (把这张图按…...

Android-三方框架的源码
ARouter Arouter的整体思路是moduelA通过中间人ARouter把路由信息的存到仓库WareHouse;moduleB发起路由时,再通过中间人ARouter从仓库WareHouse取出路由信息,这要就实现了没有依赖的两者之间的跳转与通信。其中涉及Activity的跳转、服务prov…...

AI嵌入式K210项目(15)-安全散列算法加速器
文章目录 前言一、什么是SHA256?实验原理 二、K210的安全散列算法加速器三、实验过程总结 前言 K210内置了丰富的加速器,包括神经网络处理器 (KPU),AES(高级加密加速器),APU 麦克风阵列语音数据加速计算处理器,现场可…...

Docker Consul详解与部署示例
目录 Consul构成 Docker Consul 概述 Raft算法 服务注册与发现 健康检查 Key/Value存储 多数据中心 部署模式 consul-template守护进程 registrator容器 consul服务部署(192.168.41.31) 环境准备 搭建Consul服务 查看集群信息 registrato…...

内网安全管理系统(保密管理系统)
在当今信息化的时代,企业的内网已经成为其核心资产的重要组成部分。 随着企业的快速发展和信息化程度的提升,内网安全问题日益凸显,如何保障内网的安全和机密信息的保密性,已经成为企业亟待解决的问题。 内网安全管理系统(保密管…...

.NetCore Flurl.Http 4.0.0 以上管理客户端
参考原文地址:Managing Clients - Flurl 管理客户端 Flurl.Http 构建在堆栈之上System.Net.Http。如果您熟悉HttpClient,那么您可能听说过这个建议:不要为每个请求创建一个新客户端;重复使用它们,否则将面临后…...
openssl3.2 - 官方demo学习 - smime - smenc.c
文章目录 openssl3.2 - 官方demo学习 - smime - smenc.c概述笔记END openssl3.2 - 官方demo学习 - smime - smenc.c 概述 读取X509证书, 用PKCS7加密明文(证书 明文 3DES_CBC), 保存为MIME格式的密文 openssl API的命名含义 BIO_new_file “new” a “file”, return a “…...

【EI会议征稿通知】第四届工业制造与结构材料国际学术会议(IMSM 2024)
第四届工业制造与结构材料国际学术会议(IMSM 2024) 2024 4th International Conference on Industrial Manufacturing and Structural Materials(IMSM 2024) 第四届工业制造与结构材料国际学术会议(IMSM 2024&#x…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...