使用异或简化逻辑判断

认识异或

我们平时比较常用 且 &&, 或 ||, 非 !, 你可听说过 异或 ^?

true ^ true // false
true ^ false // true
false ^ true // true
false ^ false // false
1
2
3
4

简单来讲, 就是相同为 false, 不同为 true, 就是异或.

反过来, 相同为 true, 不同为 false, 就是同或, 只不过异或再取非就可以拿到同或, 所以我们就不需要同或再专门占用一个计算符号了.

现在你认识异或了, 也可能之前就认识了, 那么, 你会用异或吗? 或者说, 哪里可以用到异或呢?

实战练习 1

有个用户信息库, 可以存储用户字段 `姓名 name` 和字段 `手机号 phone`
现在我们需要一个方法来校验用户信息是否存储合理, 通过参数来标记字段是否应该存在
如果应该存在的没有存在, 或者不应该存在的存在了, 即为不合理, 反之, 就是合理

`isInfoSafe(name, phone)`

已知方法 `has(字段名)` 来判断当前字段是否存在, 如 `has('name')`
1
2
3
4
5
6
7

一般来说, 我们可以通过 if / else 表达式很容易实现

function isInfoSafe(name, phone) {
    if (name && phone) {
        return has('name') && has('phone')
    } else if (name) {
        return has('name') && !has('phone')
    } else if (phone) {
        return has('phone') && !has('phone')
    } else {
        return !has('phone') && !has('phone')
    }
}
1
2
3
4
5
6
7
8
9
10
11

那么你想过通过异或来实现吗

function isInfoSafe(name, phone) {
    return !(name ^ has('name')) && !(phone ^ has('phone'))
}
1
2
3

能感受到异或的魅力吗

实战练习 2

当然, 有时候通过异或不总是那么容易, 并且我们也不能够直观的感受到是否容易, 是否适合使用异或

有个用户信息库, 可以存储用户姓名 `字段 name` 和手机号 `字段 phone`
现在我们需要一个方法来判断用户必要的信息是否存在, 通过参数来标记字段是否为必要的信息

`isInfoFull(name, phone)`

已知方法 `has(字段名)` 来判断当前字段是否存在, 如 `has('name')`

如果没有信息字段为必要的, 直接返回 true
1
2
3
4
5
6
7
8

一般来说, 我们可以通过 if / else 表达式很容易实现

function isInfoFull(name, phone) {
    if (name && phone) {
        return has('name') && has('phone')
    } else if (name) {
        return has('name') // <---
    } else if (phone) {
        return has('phone') // <---
    } else {
        return true; // <---
    }
}
1
2
3
4
5
6
7
8
9
10
11

现在怎么通过异或来实现呢?

function isInfoFull(name, phone) {
    return (!(name ^ false) || !(name ^ has('name'))) &&
        (!(phone ^ false) || !(phone ^ has('phone')));
}
1
2
3
4

实战练习 3

如果实战练习 2 中, 多了一个字段 年龄 age, 你能想象 if / else 会变得多复杂吗

function isInfoFull(name, phone, age) {
    if (name && phone && age) {
        return has('name') && has('phone') && has('age') // <---
    } else if (name && phone) {
        return has('name') && has('phone') // <---
    } else if (name && age) {
        return has('name') && has('age') // <---
    } else if (phone && age) {
        return has('phone') && has('age') // <---
    } else if (name) {
        return has('name')
    } else if (phone) {
        return has('phone')
    } else if (age) {
        return has('age') // <---
    } else {
        return true;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

但是异或却很轻松

function isInfoFull(name, phone, age) {
    return (!(name ^ false) || !(name ^ has('name'))) &&
        (!(phone ^ false) || !(phone ^ has('phone'))) &&
        (!(age ^ false) || !(age ^ has('age')));
}
1
2
3
4
5

总结

我们不是在纠结使用异或 运算符 还是使用 if / else 逻辑表达式,

而是提供了一个全新的思路, 让你的多维度判断抽离出来

function resultByCondition(condition, result) {
    return (!(condition ^ false) || !(condition ^ result()))
}

function isInfoFull(name, phone, age) {
    return resultByCondition(name, () => has('name')) &&
        resultByCondition(phone, () => has('phone'))
        resultByCondition(age, () => has('age'));
}
1
2
3
4
5
6
7
8
9

现在, 你的 resultByCondition 方法, 也可以用 if / else 逻辑表达式实现

然而 isInfoFull() 已经可以轻松实现扩展了