JavaScript中如何让 x == 1 && x == 2 && x == 3 等式成立

前言

某次面试,面试官突然问道:“如何让 x 等于 1 且让 x 等于 2 且让 x 等于 3 的等式成立?

话音刚落,笔者立马失去意识,双眼一黑,两腿一蹬,心里暗骂:什么玩意儿!

虽然当时没回答上来,但觉得这题非常有意思,便在这为大家分享下后续的解题思路:

宽松相等 == 和严格相等 === 都能用来判断两个值是否“相等”,首先,我们要明确上文提到的等于指的是哪一种,我们先看下二者的区别:

(1) 对于基础类型之间的比较,== 和 === 是有区别的:

  • (1.1) 不同类型间比较,== 比较“转化成同一类型后的值”看“值”是否相等,=== 如果类型不同,其结果就是不等
  • (1.2) 同类型比较,直接进行“值”比较,两者结果一样

(2) 对于引用类型之间的比较,== 和 === 是没有区别的,都进行“指针地址”比较

(3) 基础类型与引用类型之间的比较,== 和 === 是有区别的:

  • (3.1) 对于 ==,将引用类型转化为基础类型,进行“值”比较
  • (3.2) 因为类型不同,=== 结果为 false

“== 允许在相等比较中进行强制类型转换,而 === 不允许。”

由此可见,上文提到的等于指的宽松相等 ==,题目变为 “x == 1 && x == 2 && x == 3”。

那多种数据类型之间的相等比较又有哪些呢?笔者查阅了相关资料,如下所示:

同类型数据之间的相等比较

  • 如果 Type(x) 等于 Type(y) ES5 规范 11.9.3.1 这样定义:
  • 如果 Type(x) 是 Undefined,返回 true
  • 如果 Type(x) 是 Null,返回 true
    • 如果 Type(x) 是 Number ,则
    • 如果 x 是 NaN,返回 false
    • 如果 y 是 NaN,返回 false
    • 如果 x 与 y 的数字值相同,返回 true
    • 如果 x 为 +0y 为 -0,返回 true
    • 如果 x 为 -0y 为 +0,返回 true
  • 如果 Type(x) 是 String,则如果 x 和 y 是字符的序列完全相同(相同的长度和相同位置相同的字符),则返回 true。否则,返回 false
  • 如果 Type(x) 是 Boolean,则如果 x 和 y 都为 true 或都为 false,则返回 true。否则,返回 false
  • 如果 x 和 y 指向同一对象,则返回 true。否则,返回 false

null 和 undefined 之间的相等比较

null 和 undefined 之间的 == 也涉及隐式强制类型转换。ES5 规范 11.9.3.2-3这样定义:

  • 如果 x 为 nully 为 undefined,则结果为 true
  • 如果 x 为 undefinedy 为 null,则结果为 true

在 == 中,null 和 undefined 相等(它们也与其自身相等),除此之外其他值都不和它们两个相等。

这也就是说, 在 == 中null 和 undefined 是一回事。

var a = null;
var  b;
a == b; // true
a == null; // true
b == null; // true
a == false; // false
b == false; // false
a == ""; // false
b == ""; // false
a == 0; // false
b == 0; // false

字符串和数字之间的相等比较

ES5 规范 11.9.3.4-5这样定义:

  • 如果 Type(x) 是数字,Type(y) 是字符串,则返回 x == ToNumber(y) 的结果。
  • 如果 Type(x) 是字符串,Type(y) 是数字,则返回 ToNumber(x) == y 的结果。
var a = 42;

var b = "42";

a === b; // false

a == b; // true
复制代码

因为没有强制类型转换,所以 a === b 为 false,42 和 "42" 不相等。

根据规范,"42" 应该被强制类型转换为数字以便进行相等比较。

其他类型和布尔类型之间的相等比较

ES5 规范 11.9.3.6-7这样定义:

  • 如果 Type(x) 是布尔类型,则返回 ToNumber(x) == y 的结果;
  • 如果 Type(y) 是布尔类型,则返回 x == ToNumber(y) 的结果。

仔细分析例子,首先:

var x = true;
var y = "42";
x == y; // false

Type(x) 是布尔值,所以 ToNumber(x) 将 true 强制类型转换为 1,变成 1 == "42",二者的类型仍然不同,"42" 根据规则被强制类型转换为 42,最后变成 1 == 42,结果为 false

对象和非对象之间的相等比较

关于对象(对象 / 函数 / 数组)和标量基本类型(字符串 / 数字 / 布尔值)之间的相等比较,ES5 规范 11.9.3.8-9做如下规定:

  • 如果 Type(x) 是字符串或数字,Type(y) 是对象,则返回 x == ToPrimitive(y) 的结果;
  • 如果 Type(x) 是对象,Type(y) 是字符串或数字,则返回 ToPromitive(x) == y 的结果。

什么是 toPrimitive() 函数?

**应用场景:**在 JavaScript 中,如果想要将对象转换成基本类型时,再从基本类型转换为对应的 String 或者 Number,实质就是调用 valueOf 和 toString 方法,也就是所谓的拆箱转换。

**函数结构:**toPrimitive(input, preferedType?)

参数解释:

input 是输入的值,即要转换的对象,必选;

preferedType 是期望转换的基本类型,他可以是字符串,也可以是数字。选填,默认为 number

执行过程:

如果转换的类型是 number,会执行以下步骤:

  • 如果 input 是原始值,直接返回这个值;
  • 否则,如果 input 是对象,调用 input.valueOf(),如果结果是原始值,返回结果;
  • 否则,调用input.toString()。如果结果是原始值,返回结果;
  • 否则,抛出错误。 如果转换的类型是 string,2和3会交换执行,即先执行 toString() 方法。

valueOf 和 toString 的优先级:

  • 进行对象转换时 (alert(对象)),优先调用 toString 方法,如没有重写 toString 将调用 valueOf 方法,如果两方法都不没有重写,但按 Object 的 toString 输出。
  • 进行强转字符串类型时将优先调用 toString 方法,强转为数字时优先调用 valueOf
  • 在有运算操作符的情况下,valueOf 的优先级高于 toString

由此可知,若 x 为对象时,我们改写 x 的 valueOf 或 toString 方法可以让标题的等式成立:

const x = {
  val: 0,
  valueOf: () => {
    x.val++
    return x.val
  },
}

或者:

const x = {
  val: 0,
  toString: () => {
    x.val++
    return x.val
  },
}

给对象 x 设置一个属性 val 并赋值为 0,并修改其 valueOf、toString 方法,在 “x == 1 && x == 2 && x == 3”判断执行时,每次等式比较都会触发 valueOf、toString 方法,都会执行 val++ ,同时把最新的 val 值用于等式比较,三次等式判断时 val 值分别为 1、2、3 与等式右侧的 1、2、3 相同,从而使等式成立。

到此这篇关于JavaScript中如何让 x == 1 && x == 2 && x == 3 等式成立的文章就介绍到这了,更多相关JS 让 x == 1 && x == 2 && x == 3 成立内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JavaScript事件循环同步任务与异步任务

    目录 前言 执行栈与任务队列 执行栈 任务队列 同步任务与异步任务 同步任务 异步任务 js的执行机制 结语 前言 首先,在学习js中同步异步的问题前,需要明白,js是单线程的,为什么它得是单线程的呢?这得从它的使用场景来看了,它主要是用来让用户与页面进行交互的吧.那么假设js是多线程的,在这个线程里面,用户点击某个按钮会增加一个DOM节点,在另一个线程里面,用户点击这个按钮又会删除一个DOM节点,那么此时js就不知道该听谁的了.那同步异步的出现又是为了什么呢?假设没有异步,那么我们在向服务器请

  • JS前端面试数组扁平化手写flat函数示例

    目录 前言 题目 实现扁平化的方法 封装 flatten 1. ES6 flat 2. toString 3. 使用正则替换 4. 循环递归 4.1 循环 + concat + push 4.2 增加参数控制扁平化深度 4.3 巧用 reduce 4.4 使用 Generator 函数 5. 使用堆栈 stack 避免递归 6.while 循环+ some方法 前言 由于上半年参加了校招的技术面试, 前前后后面了20多个人了, 每次面试都会让应聘者手写一下数组扁平化flat(),但是发现居然没有

  • python处理json文件的四个常用函数

    目录 一,json.load()和json.dump只要用于读写json数据 二,json.loads和json.dumps主要用于字符串和字典之间的类型转换 三,练习 1编写一个json格式的文件 2编写python方法 一,json.load()和json.dump只要用于读写json数据 1json.load() 从文件中读取json字符串 with open('data.json','r',encoding='utf-8') as f print(json.load(f)) 2json.

  • JavaScript中如何让 x == 1 && x == 2 && x == 3 等式成立

    前言 某次面试,面试官突然问道:“如何让 x 等于 1 且让 x 等于 2 且让 x 等于 3 的等式成立?” 话音刚落,笔者立马失去意识,双眼一黑,两腿一蹬,心里暗骂:什么玩意儿! 虽然当时没回答上来,但觉得这题非常有意思,便在这为大家分享下后续的解题思路: 宽松相等 == 和严格相等 === 都能用来判断两个值是否“相等”,首先,我们要明确上文提到的等于指的是哪一种,我们先看下二者的区别: (1) 对于基础类型之间的比较,== 和 === 是有区别的: (1.1) 不同类型间比较,== 比较

  • JavaScript中立即执行函数实例详解

    前言 js立即执行函数可以让你的函数在创建后立即执行,js立即执行函数模式是一种语法,可以让你的函数在定义后立即被执行,这种模式本质上就是函数表达式(命名的或者匿名的),在创建后立即执行. ( function(){-} )()和( function (){-} () )是两种javascript立即执行函数的常见写法,最初我以为是一个括号包裹匿名函数,再在后面加个括号调用函数,最后达到函数定义后立即执行的目的,后来发现加括号的原因并非如此. 下面话不多说了,来一起看看详细的介绍吧. 通常我们声

  • JavaScript中正则表达式的概念与应用

    今天和大家分享一些关于正则表达式的知识和在javascript中的应用.正则表达式简单却又不简单,比如以前我的老师给我们讲的时候就说这个东西入门的话二三十分钟就精通了,一旦没有入门那就可几天都补不回来.于是当初就很认真的学习并研究了它.没想到正则表达式不仅代码简洁,而且在实际的操作中为前端工程师们省事了不少.总所周知,用户在浏览页面的时候,唯一和数据打交道的就是表单了,关于表单的验证,其实有很多中方法,接下来,我就会给大家分享两种,一种是普通繁琐的方法,一种是正则表达式,看看它到底能够给表单带来

  • Javascript中正则表达式的使用及基本语法

    前面的话 正则表达式在人们的印象中可能是一堆无法理解的字符,但就是这些符号却实现了字符串的高效操作.通常的情况是,问题本身并不复杂,但没有正则表达式就成了大问题.javascript中的正则表达式作为相当重要的知识,本文将介绍正则表达式的基础语法 定义 正则表达式(Regular Expression)是一门简单语言的语法规范,是强大.便捷.高效的文本处理工具,它应用在一些方法中,对字符串中的信息实现查找.替换和提取操作 javascript中的正则表达式用RegExp对象表示,有两种写法:一种

  • JavaScript中的面向对象介绍

    对象 创建 对象 构造函数 公有.私有.特权.静态成员 this.call和apply 异常处理 继承 原型 对象 在JavaScript,可以说everything is object,那么什么是对象?对象就是包含一组变量和函数的集合.在其它面向对象语言中对象是由类的实例化而来,JavaScript是基于原型的面向对象语言,没有类的概念,对象派生自现有对象的副本.JavaScript中对象可以分为两类:Function和Object. 创建对象 为了提高效率,JavaScript自带内置对象,

  • Javascript中的对象和原型(二)

    在上篇文章中JavaScript中的对象和原型(一)提到了JavaScript中对象的创建的一些基本操作,接下来讨论下继续讨论. 一 工厂模式 我们知道,要创建一个对象我们可以用如下代码: var user = new Object(); //使用new运算符创建一个对象 user.name = '念在三角湖畔'; //给对象添加属性 user.age = 22; user.address = '湖北武汉'; alert(user.name + " " +user.age);//返回

  • 深入理解javascript中的立即执行函数(function(){…})()

    javascript和其他编程语言相比比较随意,所以javascript代码中充满各种奇葩的写法,有时雾里看花,当然,能理解各型各色的写法也是对javascript语言特性更进一步的深入理解. ( function(){-} )()和( function (){-} () )是两种javascript立即执行函数的常见写法,最初我以为是一个括号包裹匿名函数,再在后面加个括号调用函数,最后达到函数定义后立即执行的目的,后来发现加括号的原因并非如此.要理解立即执行函数,需要先理解一些函数的基本概念.

  • JavaScript中的类(Class)详细介绍

    在JavaScript中,可以使用类(Class)来实现面向对象编程(Object Oriented Programming).不过,JavaScript中的类与Java中的有所不同,其相应的定义和使用也不一样. JavaScript中类的定义 在JavaScript中,所有从同一个原型对象(prototype)处衍生出来的对象组成了一个类:也就是说,JavaScript中的类是一个对象集合的概念,如果两个对象它们的prototype相同,那么它们就属于同一个类:JavaScript中的类甚至都

  • JavaScript中数组添加值和访问值常见问题

    通过本文给大家介绍关于数组方面的一些小问题,或许对大家有点帮助,本文写的不好,还请各位大侠见谅. 1. // var arr = [,,]; // arr["bbb"]="nor "; // arr[-]="nor "; // console.log(arr); >> [, , , bbb: "nor ", -: "nor "] // console.log(arr.bbb) >>

  • javascript中typeof的使用示例

    复制代码 代码如下: <html> <head> <title>javascript中typeof的使用</title> <script> //1.基本类型 var x = 123; var y = "abc"; var z = true; //alert(typeof x);//number //alert(typeof y);//string //alert(typeof z);//boolean //2.引用类型,类型是

随机推荐