簡體   English   中英

有沒有辦法在現代瀏覽器中用javascript替換這個lodash _.chain代碼?

[英]Is there a way I can replace this lodash _.chain code with javascript in modern browsers?

我有這個使用lodash _.chain的代碼。 我想簡化代碼,而不是使用lodash並以另一種方式執行此操作。

examObjectives = _.chain(objectives)
   .where({ 'examId': exam })
   .uniq(true, 'id')
   .map(function (s): any { return { id: s.id, text: s.text, numberAndText: s.numberAndText }; })
   .value();

有人可以給我一些關於如何刪除對lodash,_.chain和代碼的依賴的建議,這可以最大限度地利用現在可以在新瀏覽器中找到的可用javascript函數。 注意我想使用內置的過濾器和map函數,而不是使用任何外部函數來創建examObjectives。

我希望有人能想出一些想法。 我對javascript不太熟悉所以歡迎有機會學習。

您可以開始定義常規函數,為方便起見,將接收器作為最后一個,例如:

var map = function(f, xs) {
  return xs.map(f)
}

var filter = function(f, xs) {
  return xs.filter(f)
}

然后,您可以使用arguments對象構建chain

var methods = {map: map, filter: filter}

var chain = function(xs) {
  return Object.keys(methods).reduce(function(acc, k) {
    acc[k] = function() {
      var as = [].slice.call(arguments)
      return methods[k].apply(this, as.concat([xs]))
    }
    return acc
  },{})
}

現在你可以這樣做:

filter(even, map(plus1, [1,2,3])) //=> [2,4]

以及:

chain([1,2,3]).map(plus1).filter(even) //=> [2,4]

如果函數是curry,你也可以表達為:

var chain = compose(filter(even), map(plus1))
chain([1,2,3]) //=> [2,4]

我把一些東西放在一起,代碼看起來像這樣:

objectives.filter(function (x) {
    return x.examId == exam;
}).reduce(function (accumulator, current) {
    if (!accumulator.some(function (x) { return x.id == current.id; })) {
        accumulator.push(current);
    }
    return accumulator;
}, []).map(function (x) {
    return {
        id: x.id,
        text: x.text,
        numberAndtext: x.numberAndText
    }
});

(“uniquifier”的靈感來自https://stackoverflow.com/a/17903018/2022183 )。

您可以通過使用如下函數提取屬性與常量值的比較來縮短此代碼:

function propertyEqualTo(prop, val) {
    return function (x) {
        return x[prop] == val;
    };
}

你的代碼將是:

return objectives.filter(propertyEqualTo('examId', exam)).reduce(function (accumulator, current) {
    if (!accumulator.some(propertyEqualTo('id', current.id)) {
        accumulator.push(current);
    }
...

你確定在這里需要uniq()調用嗎? 您正在匹配一個從一開始就應該是唯一的id 如果您能夠刪除此調用,則您的代碼應該非常短。

這取決於你真正想做的事情。

您想知道如何實現與現代瀏覽器API一起使用的lodash功能

使用本主題中提出的解決方案。

您想要刪除對lodash的依賴

如果是這種情況,我想你想要發布一個無依賴的庫。

請注意,Underscore和Lodash都在MIT許可下 ,因此您可以簡單地復制/粘貼所需的功能,並將其直接嵌入到分布式app / lib /中。

你想要好的表現

請注意,使用現代瀏覽器API並不總是獲得最佳性能的方法。 Javascript現在非常快(除非你直接操作DOM,檢查ReactJS演示文稿),使用高效設計的JS代碼通常比設計糟糕的本機代碼更快。 此外,並非所有瀏覽器API函數都使用本機代碼實現。

通過鏈接下划線語句,在每個步驟中創建一個中間數組,從而導致更高的內存消耗和垃圾收集活動。 根據您的初始數組的大小,它可能會影響您的應用程序性能,使用命令式代碼可能會更好。

在保持功能編程風格的同時處理這些中間陣列分配的現代技術是使用換能器 它現在有2個主要的JS實現:

這可能被認為是小陣列的過早優化,但實際上換能器並不是非常復雜並且不會引入那么多復雜性。 如果你想有賓至如歸的感覺,你甚至可以使用下划線 - 恍惚者 ,它提供與Underscore非常相似的API。

objectives = [{
    id: 1,
    text: 'hello',
    numberAndText: 'sdfafaadsf',
    examId: 'exam'
}, {
    id: 2,
    text: 'hello',
    numberAndText: 'sdfafaadsf',
    examId: 'exam2'
}];
var result = objectives
    .filter(function(item) {
        return item['examId'] === 'exam';
    })
    .map(function(item) {
        return {
            id: item.id,
            text: item.text,
            numberAndText: item.numberAndText
        };
    })
    .reduce(function(prev, curr) {
        var ids = prev.map(function(item) {
            return item.id;
        });
        if (ids.indexOf(curr.id) < 0) {
            prev.push(curr);
        }
        return prev;
    }, []);

使用filter map reduce,你可以通過vanilla js簡單地實現這一點

以下所有單一功能都來自mofun.js ,我寫的內容就像lodash,但是完全模塊化(沒有內部取決於方法)並且充分利用了本機方法。

// mofun.js-provided stock utility stand-alone functions:
function where(o,_,__){var t=this;return Object.keys(t).every(function(k,_,__){return o[k]===t[k];});}
function extract(o,_,__){return o[""+this];}
function extractObject(o,_,__){var o2={};this.forEach(function(t,_,__){return o2[t]=o[t];});return o2;}
function groupBy(r,s){var ret={};r.forEach(function(a,_,__){var k=a[s],b=ret[k]||(ret[k]=[]);b.push(a);});return ret;}
function obVals(o){var t=[],n=0;for(var r in o)o.hasOwnProperty(r)&&(t[n++]=o[r]);return t;}

// begin custom code:
obVals( // temp object back into array of values
  groupBy( // group array of objects into a grouped temp object of arrays
    objectives.filter(where, { 'examId': exam }) // only objects with the proper examId
  , "id") // groupBy using "id" peoperty of each object
)
.map(extract, 0) //take first value of each group's array to get unique ids among result objects
.map(extractObject, ["id", "text", "numberAndText"]) // extract some properties into a blank object

代碼與lodash完全相同,除了關於基於子屬性(而不是整個對象比較)查找唯一對象的部分,我通過對該屬性進行分組,然后從每個組中提取第一個元素來完成; 根據需要調整。

暫無
暫無

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

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