javascript计算器
国家管理具有挑战性。 通过确保我们不在状态中存储任何冗余信息,我们可以减少挑战。 我什么意思 假设在我们的程序中,我们需要弄清楚是否将允许人们进入我们的酒吧。 我们可以通过检查某人的几个属性来确定这一点:我们可以查看他或她的年龄(年龄在21岁或以上的任何人都可以进入酒吧),或者可以查看他或她是否是该酒吧的雇员(全部禁止酒吧员工进入,不论年龄大小)。 现在,我们可以将所有这些信息存储在我们的状态对象中:
const state = {
name:"Joe" ,
age: 15 ,
employee: false ,
allowedIn: false
};
这里的问题是, allowedIn
可以很容易地从age
和employee
得出,这意味着该信息在技术上是多余的。 这是最成问题的,因为它为我们的国家提供了自相矛盾的机会。
介绍选择器
我们可以使用选择器来解决此问题。 选择器是将状态作为属性并返回派生状态值的函数。 让我们看看是否可以创建一个选择器来替换我们的allowedIn
属性。
const state = {
name : "Joe" ,
age : 15 ,
employee : false
};
const allowedIn = state => state.age >= 21 || state.employee;
现在我们看到,如果我们需要确定是否允许该人进入我们的酒吧,我们可以简单地使用调用allowedIn(state)
的布尔结果!
使用可组合选择器进一步深入
现在,如果我们有一些更复杂的要求怎么办? 也许我们需要根据是否允许他们进入酒吧以及他们是否友好来做出一个名为highFiveThem
的决定。 首先,让我们假装一个新的状态对象,其中包括它们是否友好。
const state = {
name : "Judy" ,
age : 22 ,
employee : false ,
isFriendly : true
};
我们的决策不再只是基于状态对象,而是基于另一个选择器的结果。 这是我们开始使用高阶函数从其他选择器组成选择器的地方。 让我们看一下这在实践中是如何工作的,然后我们可以窥视一下。
const state = {
name : "Judy" ,
age : 22 ,
employee : false ,
isFriendly : true
};
const allowedIn = state => state.age >= 21 || state.employee;
const isFriendly = state => state.isFriendly;
const highFiveThem = createSelector(
allowedIn,
isFriendly,
(allowedIn, isFriendly) => allowedIn && isFriendly;
)
highFiveThem(state);
// true
本质上,这将计算allowedIn(state)
和isFriendly(state)
选择器的结果,并将这些输入传递给传递给createSelector
的最终函数。
在学术上,让我们看一下这个高阶函数如何工作。
const createSelector = ( ...funcs ) => {
const last = funcs.pop();
return state => {
const inputs = funcs.map( func => func(state));
return last(...inputs);
};
};
工作原理:
- 该
createSelector
函数接受任何数目的funcs
。 - 我们创建一个名为
last
的变量来存储传递给createSelector
的最后一个函数,因为它将是使用所有先前函数的结果的变量。 - 我们返回一个函数(我们的新选择器!)。
- 每当执行该函数时,我们都会映射所有输入函数,以根据传递的
state
确定其结果。 - 给定所有先前函数的结果,我们返回
last
函数的值。
很整洁吧?
关于效率的思考
许多选择器库(例如,针对Redux的Reselect)都包含用于记住选择器结果的附加功能。 这是因为如果选择器的输入没有发生根本变化,则重新计算选择器的效率很低。 在此处映射我们的记忆功能有点超出范围,但是请记住,由于这种优化,使用其中一个库可能会有所益处(与滚动您自己的选择器解决方案相比)。
谢谢!
翻译自: https://hackernoon.com/calculating-derived-state-in-javascript-using-selectors-7f6ce06ac247
javascript计算器