使 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.mzph.cn/news/636217.shtml

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

相关文章

传奇服务器搭建

传奇服务器搭建 传奇是一款非常经典的游戏,自从它推出以来就深受玩家们的喜爱。如果你也想要在自己的服务器上搭建一个传奇,那么本文将为你提供一些有用的信息。 首先,我们需要知道什么是传奇服务器。简单来说,它就是一个能够让…

线程池c++实现

线程池c实现 概述 线程池(Thread Pool)是一种并发编程的设计模式,它用于管理和重复使用线程,以提高程序的性能和资源利用率。线程池通过维护一组预先创建的线程,这些线程可以在需要时被重复使用,而不是为…

HarmonyOS鸿蒙学习基础篇 - 什么是HarmonyOS

概述 HarmonyOS是华为开发的一款面向未来的全场景分布式智慧操作系统,将逐步覆盖18N全场景终端设备; 对消费者而言 HarmonyOS用一个‘统一的软件系统’ 从根本上解决消费者面对大量智能终端体验割裂的问题,为消费者带来同意便利安全的智慧化全…

相关系数(皮尔逊相关系数和斯皮尔曼相关系数)

本文借鉴了数学建模清风老师的课件与思路,可以点击查看链接查看清风老师视频讲解:5.1 对数据进行描述性统计以及皮尔逊相关系数的计算方法_哔哩哔哩_bilibili 注:直接先看 ( 三、两个相关系数系数的比较 ) 部分&#x…

Qt事件过滤

1.相关说明 监控鼠标进入组件、出组件、点击组件、双击组件的事件,需要重写eventFilter函数 2.相关界面 3.相关代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui-&…

数据库(MySQL库表操作)

目录 1.1 SQL语句基础(SQL命令) 1.1.1 SQL的简介 1.1.2 SQL语句的分类 1.1.3 SQL语句的书写规范 1.2 数据库操作 1.2.1 查看 1.2.2 自建库 1.2.3 切换数据库 1.2.4 删库 1.3 MySQL字符集 1.3.1 MySQL字符集包括: 1.3.2 utf8 和 u…

汽车制动器行业调查:市场将继续呈现稳中向好发展态势

汽车制动器是汽车的制动装置,汽车所用的制动器几乎都是摩擦式的,可分为鼓式和盘式两大类。鼓式制动器摩擦副中的旋转元件为制动鼓,其工作表面为圆柱面;盘式制动器的旋转元件则为旋转的制动盘,以端面为工作表面。 目前市场上主流的…

JAVA和C++ SECS/GEM300开发和概念

编译SECS示例程序 1. 示例程序使用默认路径: D:\SECS 稳定版\SECS Debug\ 2. 该操作分为俩步 ① 将C#的Secs库编译成设备相同Net版本。 如.net3.5、4.0、4.5等等 ② 编译金南瓜SECS demo程序 编译C#的SecsEquip.dll 1. 找到SecsEquip项目 项目文件 使用Visua…

麒麟V10挂载iso,配置yum源

本文介绍yum 如何挂载本地镜像源 1) 拷贝镜像到本地 2) 执行以下命令: # mount -o loop 镜像路径及镜像名字 /mnt(或 media) 挂载前 挂载后 3) 进入/etc/yum.repos.d(yum.repos.d 是一个目录,该目录是分析 RPM 软件…

操作系统的一些知识

一、操作系统 1、操作系统的定义 操作系统是一个搞管理的软件。 对下,要管理硬件设备;对上,要给软件提供稳定的运行环境。 操作系统是软件、硬件、用户之间交互的媒介。 2、常见的操作系统 Windows、Linux、Mac 3、操作系统的定位 我们平…

视频剪辑教程:如何批量制作滚动字幕,提升画面质感的方法

在视频剪辑中,字幕的处理是至关重要的一环。合适的字幕不仅能提供必要的信息,还能增强画面的视觉效果。下面详解云炫AI智剪如何批量制作滚动字幕,提升画面质感的方法,助您更好地完成视频剪辑工作。 批量制作滚动字幕的方法&#x…

Mysql详细安装步骤

Linux 安装 MySQL【超详细版】 ​编辑 我叫BuGu    2023-05-11 16:48:10 发布 一、安装 MySQL 的准备工作 1. 查看系统版本 cat /etc/redhat-release2. 查看系统是否已经安装过 MySQL 查看是否安装了 MySQL rpm -qa | grep mysql查看是否有安装 mariadb,该软件与 MySQ…

逆向分析C++类的本质

面向对象的语言中,类这种语言特性是最基本也是最重要的东西。这篇博客记录下从汇编角度去理解类的本质是什么。创建一个对象的本质又是什么。 一.C语言中的结构体和C的类有啥区别 我们知道在C语言中,有语言本身自带的一些内置类型。比如int&#xff0c…

kafka(一)——简介

简介 Kafka 是一种分布式、支持分区、多副本的消息中间件,支持发布-订阅模式,多用于实时处理大量数据缓存的场景,类似于一个“缓存池”。 架构 Producer:消息生产者;Consumer:消息消费者;Brok…

SpringCloud之Nacos的学习、快速上手

1、什么是Nacos Nacos是阿里的一个开源产品,是针对微服务架构中的服务发现、配置管理、服务治理的综合型解决方案,用来实现配置中心和服务注册中心。 Nacos 快速开始 2、安装运行nacos nacos下载地址 下载地址: https://github.com/alibaba/nacos/rel…

【Linux】Linux系统的生态

Linux中安装软件 Linux中安装软件一般有三种方式: 源代码安装rpm包安装yum安装 1.源代码安装 有些软件本来就是开源的,如果不想用别人直接发布好的软件,我们就可以把源代码下载下来,在我们的环境中编译,自己安装 …

防伪技术行业研究:年复合增长率约为10%

近年来,我国各种新的防伪技术不断涌现,部分防伪技术已经达到国际先进水平,并广泛应用于产品防伪、票证防伪等领域,推动了防伪行业的持续、健康发展。 常见的产品防伪技术有:隐形分子技术、二维码防伪、揭开留底防伪、安…

「Kafka」Broker篇

「Kafka」Broker篇 主要讲解的是在 Kafka 中是怎么存储数据的,以及 Kafka 和 Zookeeper 之间如何进行数据沟通的。 Kafka Broker 总体工作流程 Zookeeper 存储的 Kafka 信息 启动 Zookeeper 客户端: [atguiguhadoop102 zookeeper-3.5.7]$ bin/zkCli.sh通…

使用 Docker 部署 的WAF: 雷池社区版

Web应用防火墙(WAF)是保护网站不受恶意攻击的关键组件。 使用 Docker 部署雷池社区版,可以大大简化安全管理工作。 一、WAF 雷池社区版简介 雷池社区版是一种流行的开源 Web 应用防火墙,它提供基本的安全保护,如防止…

多维表格产品vika多维表、Flowus、Wolai体验记录

昨天从下午6点肝到凌晨2点多体验低代码平台多维表格产品,体验了3个国内产品,vika多维表、Flowus、Wolai。 具有多维表格新型关系数据库的鼻祖是 Airtable,国内模仿产品有vika多维表、飞书多维表格等。 还有一种类型就是以在国内鼎鼎大名的N…