我做梦都想不到😵,我被if(x)摆了一道!
读本文,可以收获什么?
字数:2494 花费时间:5min
if(x)中的x为各种类型的数据或者值的时候会发生什么?x为各种数据类型、表达式、特殊值、位运算、函数等值的时,这些在if语句都充当了什么,实现了什么?
总结== === ≠三种情况特殊值的比较,如下图所示:
作为一个程序员的我们,相信我们写代码用的最多逻辑应该就是if语句了吧,其实我们真的了解if(x)究竟发生了什么?其实很简单,我们可能都知道中文有这样一个模板:"如果是什么,就会做什么
",也就是说符合条件的某件事,才会去做某件事。同样的道理if(x)的意思就是如果符合x条件,我们就可以执行if语句块的代码了
。而我们JavaScript中的哪个数据类型是涉及是否意思的?当然是Boolean类型啦,其实if内的x非布尔值都会做一次Boolean类型的转换的
。
1 x为一个值时
1.1 x为字符串:
x为一个空字符串时,这是一个假值,if语句会转换为false。
if ("") {
console.log("Hello World!");
}
console.log(Boolean(""));// false
x为一个非空字符串是,这是一个真值。if语句会转换为true。
if (!"") {
console.log("Hello World!");// Hello World!
}
console.log(Boolean(!""));// true
x为一个空格字符串,这是一个真值。if语句会转换为true。否则会转换为false
if (" ") {
console.log("Hello World!");// Hello World!
}
console.log(Boolean(" "));// true
if (!" ") {
console.log("Hello World!");
}
console.log(Boolean(!" "));// false
x为一个字符串,这是一个真值。if语句会转换为true。否则会转换为false
if ("JavaScript") {
console.log("Hello World!");// Hello World!
}
console.log(Boolean("JavaScript"));// true
if (!"JavaScript") {
console.log("Hello World!");
}
console.log(Boolean(!"JavaScript"));// false
1.2 x为数字
x为一个数字0时,这是一个假值,if语句会转换为false。x为一个数字!0时,这是一个真值,if语句会转换为true。
if (0) {
console.log("Hello World")
}
console.log(Boolean(0));// fasle
if (!0) {
console.log("Hello World");// Hello World
}
console.log(Boolean(!0));// true
if (1) {
console.log("Hello World") // Hello World
}
console.log(Boolean(1));// true
if (!1) {
console.log("Hello World")
}
console.log(Boolean(!1));// false
if (-0) {
console.log("Hello World")
}
console.log(Boolean(-0));// fasle
if (!-0) {
console.log("Hello World");// Hello World
}
console.log(Boolean(!-0));// true
1.3 x为数组
x为一个空数组,这是一个真值,if语句会转换为true。
if ([]) {
console.log("Hello World");// Hello World
}
console.log(Boolean([]));// true
if (![]) {
console.log("Hello World");
}
console.log(Boolean(![]));// false
x为一个嵌套空数组时,这是一个真值,if语句会转换为true。否则是假值。if语句会转换为false
if ([[]]) {
console.log("Hello World");// Hello World
}
console.log(Boolean([[]]));// true
if (![[]]) {
console.log("Hello World");
}
console.log(Boolean(![[]]));// false
x为一个有空字符串的数组时,这是一个真值,if语句会转换为true。否则是假值。if语句会转换为false。
if ([""]) {
console.log("Hello World");// Hello World
}
console.log(Boolean([""]));// true
if (![""]) {
console.log("Hello World");
}
console.log(Boolean(![""]));// false
x为一个有数字0的数组时,这是一个真值,if语句会转换为true。否则是假值。if语句会转换为false。
if ([0]) {
console.log("Hello World");// Hello World
}
console.log(Boolean([0]));// true
if (![0]) {
console.log("Hello World");
}
console.log(Boolean(![0]));// false
1.4 x为对象:
if ({}) {
console.log("Hello World") // Hello World
}
console.log(Boolean({}));// true
2 x为特殊值时
if (null) {
console.log("Hello World");
}
console.log(Boolean(null));// false
if (undefined) {
console.log("Hello World");
}
console.log(Boolean(undefined));// false
if (NaN) {
console.log("Hello World");
}
console.log(Boolean(NaN));// false
3 x为位运算时
if (true | false) {
// 按位或,只要有一个成立就为true
console.log("Hello World");
}
console.log(Boolean(true | false));// true
4 x为表达式时
比较的相方首先调用ToPrimitive(内部函数,不能自行调用)转换为原始值,如果出现非字符串,就根据ToNumber规则将双方强制转换为数字来进行比较。
const a = [42];
const b = ["43"];
console.log(a < b);// true
5 x为等式时
5.1 一个等号(=)
=: 一个等号代表的是赋值,即使x的值为a=2,也就是说变量的声明操作放在if判断位置上了,其实它还是一个变量并不是一个操作。
let a;
if (a = 2) {
console.log("条件成立!");// 条件成立!
}
console.log(a);// 2
let a;
if (a = 2) {
console.log("条件成立!");// 条件成立!
}
console.log(typeof (a = 2));// number
console.log(Boolean(a = 2));// true
let a;
if (a = 2 && (a = 3)) {
console.log("条件成立!");// 条件成立!
}
console.log(typeof (a = 2 && (a = 3)));// number;
5.2 两个等号(==)
==:宽松相等
,我们可能都会这样想,==检查值是否相等,听起来蛮有道理,但不准确,真正的含义是==允许相等比较重进行强制类型转换
。
对于==符号尽量遵守两个原则:
如果两边的值中有true或者false,千万不要使用==
;
如果两边的值中有[]、""、0,尽量不要使用==
。
-
两个值类型相同,则执行严格相等变量。
🍟 都是字符串类型:
const a = ""; const b = "12"; console.log(a == b);// false
🍟 都是NaN类型:全称为not a number,理解为不是一个数值。
JavaScript的规定, NaN表示的是非数字, 那么这个非数字可以是不同的数字,因此 NaN 不等于 NaN。
const a = NaN; const b = NaN; console.log(a == b);// false
🍟 都是Symbol类型:Symbol命名的属性都是独 一无二的,
可以唯一标识变量值
,不受是否相同变量值。const a = Symbol("1"); const b = Symbol("1"); console.log(a == b);// false
🍟 都是对象类型。对象的比较是
内存地址
,因为对象是存储在堆中,当堆中有对象时,它会相对应内存中有一个存储的地址,在栈中其存储了其在堆中数据的地址
,当调用数据时,去堆中调取对应堆中的数据的地址获取出来。也就是相同对象比较的是内存地址,变量不一样存储位置不一样。const a = { a: 1 }; const b = {}; console.log(a == b);// false
const a = {}; const b = {}; console.log(a == b);// false console.log(Boolean(a));// true
-
两个值类型不相同。
🍟 一个值是null,一个是undefind。
const a = undefined; const b = null; console.log(a == b);// true
🍟 一个值是数字,一个值是字符串。字符串强制转换为数字在比较。
const a = 12; const b = "12"; console.log(a == b);// true
🍟 一个值是布尔值,一个是其他类型的值。这种做法是不安全,不建议去使用,在开发中尽量不要这样使用。
console.log("0" == false);// true console.log("" == false);// true console.log(0 == false);// true console.log([] == false);// true
🍟 一个值是对象,一个值是字符串或数字。对象与非对象的比较,
对象会被强制转换原始值
(通过内部函数 ToPrimitive自动执行,这个是内部函数不能直接调用)再比较。const a = {}; const b = ""; console.log(a == b);// false
5.3 三个等号(===)
===: 严格相等
,我们可能都会这样想,===检查值和类型是否相等,听起来蛮有道理,但不准确,真正的含义是===不允许相等比较重进行强制类型转换
,也就是不做任何处理变量是什么就是什么。
const a = 0;
const b = "0";
console.log(a === b);// false
6 x为&&、||操作时
||和&&首先会对第一个操作数(a和c)执行条件判断,如果其不是布尔值(如上例)就先进行ToBoolean强制类型转换,然后再执行条件判断。
🍟 对于||来说,如果条件判断结果为true就返回第一个操作数(a和c)的值,如果为false就返回第二个操作数(b)的值。
const a = 12;
const b = "abc";
const c = null;
if (a || b) {
console.log("a||b");// a||b
}
console.log(typeof (a || b));// number
console.log(Boolean(a || b));// true
console.log(a || b);// 12
const b = "abc";
const c = null;
if (c || b) {
console.log("c||b");// c||b
}
console.log(typeof (c || b));// string
console.log(Boolean(c || b));// true
console.log(c || b);// abc
🍟 &&则相反,如果条件判断结果为true就返回第二个操作数(b)的值
,如果为false就返回第一个操作数(a和c)的值。
const a = 12;
const b = "abc";
if (a && b) {
console.log("a&&b");// a&&b
}
console.log(typeof (a && b));// string
console.log(Boolean(a && b));// true
console.log(a && b);// abc
const b = "abc";
const c = null;
if (c && b) {
console.log("c&&b");
}
console.log(typeof (c && b));// object
console.log(Boolean(c && b));// false
console.log(c && b);// null
7 x为函数判断时
-
typeof与instanceof的区别:
🍟 typeof:
返回值是一个字符串
,用来说明变量的数据类型。一般只能返回如下几个结果:number、string、function、object、undefined,对于Array、Null等特殊对象typeof一律返回object,这正是typeof的局限性。console.log(typeof undefined == 'undefined');// true console.log(typeof null);// object
🍟instanceof:
返回值为布尔值
,用来测试一个对象在其原型链中是否存在一个构造函数的prototype属性。用于判断一个变量是否某个对象的实例。,注意地,instanceof只能用来判断对象和函数,不能用来判断字符串和数字等。const arr = new Array() if (arr instanceof Array) { console.log("arr instanceof Array");// arr instanceof Array } if (arr instanceof Object) { // 因为Array是Object的子类 console.log("arr instanceof Object");// arr instanceof Array } console.log(typeof (arr instanceof Array));// boolean
🍟
typeof
和instanceof
都有一定的弊端,并不能满足所有场景的需求。如果需要通用检测数据类型,可以使用Object.prototype.toString.call()
方法:Object.prototype.toString.call({});// "[object Object]" Object.prototype.toString.call([]); // "[object Array]" Object.prototype.toString.call(666); // "[object Number]" Object.prototype.toString.call("xxx"); // "[object String]"
注意,该方法返回的是一个格式为"[object Object]"
的字符串。
-
indexof与includes区别:
🍟 indexof:
返回的是所含元素的下标
,注意地,此函数是无法判断是否有NaN元素const str = "130212"; if (str.indexOf("0")) { console.log("str中存在0!") } console.log(str.indexOf("0"));// 2
🍟 includes:
返回的是布尔值
,代表是否存在此元素。const str = "130212"; if (str.includes("0")) { console.log("str中存在0!") } console.log(str.includes("0"));// true
转载自:https://juejin.cn/post/7154647954840616996