簡體   English   中英

'createSelector'如何在'reselect'庫中接受輸入參數?

[英]How 'createSelector' is accepting input parameter in 'reselect' library?

我從重新選擇庫中獲取了以下代碼。

當使用exampleState調用subtotalSelector ,它將調用接受輸入參數exampleState的函數createSelector

我的問題是關於createSelector如何接受exampleState和其他使用它的函數? 我不理解該參數的隱式注入。

import { createSelector } from 'reselect'

const shopItemsSelector = state => state.shop.items
const taxPercentSelector = state => state.shop.taxPercent

const subtotalSelector = createSelector(
  shopItemsSelector,
  items => items.reduce((acc, item) => acc + item.value, 0)
)

const taxSelector = createSelector(
  subtotalSelector,
  taxPercentSelector,
  (subtotal, taxPercent) => subtotal * (taxPercent / 100)
)

export const totalSelector = createSelector(
  subtotalSelector,
  taxSelector,
  (subtotal, tax) => ({ total: subtotal + tax })
)

let exampleState = {
  shop: {
    taxPercent: 8,
    items: [
      { name: 'apple', value: 1.20 },
      { name: 'orange', value: 0.95 },
    ]
  }
}

console.log(subtotalSelector(exampleState)) // 2.15

通過替換輸入參數, subtotalSelector解釋更多。

subtotalSelector = createSelector(
  state => state.shop.items,
  items => items.reduce((acc, item) => acc + item.value, 0)
)

subtotalSelector({
  shop: {
    taxPercent: 8,
    items: [
      { name: 'apple', value: 1.20 },
      { name: 'orange', value: 0.95 },
    ]
  }
});

我沒有找到更好的方法來剖析此重新選擇的庫代碼 ,而是在函數內部添加console.log 以下代碼是從reselect庫本身復制的。 您可以在此處找到JSBin版本。

在控制台輸出的底部,您可以看到exampleState實際上是代碼中使用的arguments變量。 這是一個JavaScript 構造

 function defaultEqualityCheck(a, b) { return a === b } function areArgumentsShallowlyEqual(equalityCheck, prev, next) { if (prev === null || next === null || prev.length !== next.length) { return false } // Do this in a for loop (and not a `forEach` or an `every`) so we can determine equality as fast as possible. const length = prev.length for (let i = 0; i < length; i++) { if (!equalityCheck(prev[i], next[i])) { return false } } return true } function defaultMemoize(func, equalityCheck = defaultEqualityCheck) { let lastArgs = null let lastResult = null console.log("Entering defaultMemoize"); console.log("###INPUT### defaultMemoize argument func type: " + typeof func); // we reference arguments instead of spreading them for performance reasons return function () { if (!areArgumentsShallowlyEqual(equalityCheck, lastArgs, arguments)) { // apply arguments instead of spreading for performance. lastResult = func.apply(null, arguments) } lastArgs = arguments return lastResult } } function getDependencies(funcs) { const dependencies = Array.isArray(funcs[0]) ? funcs[0] : funcs if (!dependencies.every(dep => typeof dep === 'function')) { const dependencyTypes = dependencies.map( dep => typeof dep ).join(', ') throw new Error( 'Selector creators expect all input-selectors to be functions, ' + `instead received the following types: [${dependencyTypes}]` ) } return dependencies } function createSelectorCreator(memoize, ...memoizeOptions) { console.log("Entering createSelectorCreator"); console.log("#INPUT# argument memoize name: " + memoize.name); console.log("#INPUT# argument memoize options: "); console.log(memoizeOptions); return (...funcs) => { let recomputations = 0 const resultFunc = funcs.pop() const dependencies = getDependencies(funcs) console.log("##INPUT## argument funcs: "); console.log(resultFunc); const memoizedResultFunc = memoize( function () { recomputations++ // apply arguments instead of spreading for performance. return resultFunc.apply(null, arguments) }, ...memoizeOptions ) console.log("memoizedResultFunc: " + typeof memoizedResultFunc); // If a selector is called with the exact same arguments we don't need to traverse our dependencies again. const selector = defaultMemoize(function () { const params = [] const length = dependencies.length if (arguments != null) { console.log("***INPUT*** arguments: "); console.log(arguments); } for (let i = 0; i < length; i++) { // apply arguments instead of spreading and mutate a local list of params for performance. params.push(dependencies[i].apply(null, arguments)) } // apply arguments instead of spreading for performance. return memoizedResultFunc.apply(null, params) }) selector.resultFunc = resultFunc selector.recomputations = () => recomputations selector.resetRecomputations = () => recomputations = 0 return selector } } const createSelector = createSelectorCreator(defaultMemoize) function createStructuredSelector(selectors, selectorCreator = createSelector) { if (typeof selectors !== 'object') { throw new Error( 'createStructuredSelector expects first argument to be an object ' + `where each property is a selector, instead received a ${typeof selectors}` ) } const objectKeys = Object.keys(selectors) return selectorCreator( objectKeys.map(key => selectors[key]), (...values) => { return values.reduce((composition, value, index) => { composition[objectKeys[index]] = value return composition }, {}) } ) } const shopItemsSelector = state => state.shop.items const taxPercentSelector = state => state.shop.taxPercent const subtotalSelector = createSelector( shopItemsSelector, items => items.reduce((acc, item) => acc + item.value, 0) ) const taxSelector = createSelector( subtotalSelector, taxPercentSelector, (subtotal, taxPercent) => subtotal * (taxPercent / 100) ) const totalSelector = createSelector( subtotalSelector, taxSelector, (subtotal, tax) => ({ total: subtotal + tax }) ) let exampleState = { shop: { taxPercent: 8, items: [ { name: 'apple', value: 1.20 }, { name: 'orange', value: 0.95 }, ] } } console.log(subtotalSelector(exampleState))// 2.15 //console.log(taxSelector(exampleState))// 0.172 //console.log(totalSelector(exampleState))// { total: 2.322 } 

以下代碼顯示了與上述類似的功能組成示例。

 function firstFunction() { console.log(arguments); } function secondFunction() { console.log(arguments); } function thirdFunction() { console.log(arguments); } function fourthFunction() { console.log(arguments); return function() { return function(x) { console.log(arguments); }; } } const higherOrderFunction = fourthFunction(thirdFunction); console.log("High Order Function"); console.log(higherOrderFunction); const highestOrderFunction = higherOrderFunction(firstFunction, secondFunction); console.log("Highest Order Function"); console.log(highestOrderFunction); highestOrderFunction(10); 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM