简体   繁体   English

有没有办法在现代浏览器中用javascript替换这个lodash _.chain代码?

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

I have this code which use a lodash _.chain. 我有这个使用lodash _.chain的代码。 I would like to simplify the code, not use lodash and do this in another way. 我想简化代码,而不是使用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();

Can someone give me some advice on how I could remove the dependency on lodash, the _.chain and code this making maximum use of the available javascript functions that can now be found in new browsers. 有人可以给我一些关于如何删除对lodash,_.chain和代码的依赖的建议,这可以最大限度地利用现在可以在新浏览器中找到的可用javascript函数。 Note I would like to use the built in filter and map functions and not use any external functions to create the examObjectives. 注意我想使用内置的过滤器和map函数,而不是使用任何外部函数来创建examObjectives。

I hope someone can come up with some ideas. 我希望有人能想出一些想法。 I am not so familiar with javascript so welcome the chance to learn. 我对javascript不太熟悉所以欢迎有机会学习。

You can start defining regular functions, that take the receiver last for convenience, for example: 您可以开始定义常规函数,为方便起见,将接收器作为最后一个,例如:

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

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

Then you can build chain using the arguments object: 然后,您可以使用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
  },{})
}

Now you can do: 现在你可以这样做:

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

As well as: 以及:

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

And if the functions were curried, you can also express it as: 如果函数是curry,你也可以表达为:

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

I put some stuff together, and the code looks like this: 我把一些东西放在一起,代码看起来像这样:

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" inspired by https://stackoverflow.com/a/17903018/2022183 ). (“uniquifier”的灵感来自https://stackoverflow.com/a/17903018/2022183 )。

You can shorten this code by extracting the comparison of a property to a constant value with a function like this: 您可以通过使用如下函数提取属性与常量值的比较来缩短此代码:

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

and your code will read: 你的代码将是:

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

Are you sure that you need the uniq() call here anyways? 你确定在这里需要uniq()调用吗? You are matching for an id which should be unique right from the start. 您正在匹配一个从一开始就应该是唯一的id If you were able to remove this call your code whould be very short. 如果您能够删除此调用,则您的代码应该非常短。

It depends on what you really want to do. 这取决于你真正想做的事情。

You want to know how to implement lodash features you use with modern browser API's 您想知道如何实现与现代浏览器API一起使用的lodash功能

Use the proposed solutions in this topic. 使用本主题中提出的解决方案。

You want to remove the dependency to lodash 您想要删除对lodash的依赖

If this is the case, I guess you want that to publish a dependency-free library. 如果是这种情况,我想你想要发布一个无依赖的库。

Note that Underscore and Lodash are both under MIT license and so you can simply copy/paste the functions you need and directly embed it into your distributed app / lib / whatever. 请注意,Underscore和Lodash都在MIT许可下 ,因此您可以简单地复制/粘贴所需的功能,并将其直接嵌入到分布式app / lib /中。

You want good performances 你想要好的表现

Just be aware that using modern browser API's is not always the way to achieve the best performances. 请注意,使用现代浏览器API并不总是获得最佳性能的方法。 Javascript is now very fast (unless you manipulate directly the DOM, check ReactJS presentations) , and it is often faster to use efficiently designed JS code than badly designed native code. Javascript现在非常快(除非你直接操作DOM,检查ReactJS演示文稿),使用高效设计的JS代码通常比设计糟糕的本机代码更快。 Also not all browser API functions are implemented with native code. 此外,并非所有浏览器API函数都使用本机代码实现。

By chaining underscore statements, at each step you create an intermediate array, leading to higher memory consumption and garbage collection activity. 通过链接下划线语句,在每个步骤中创建一个中间数组,从而导致更高的内存消耗和垃圾收集活动。 According to the size of your initial array, it may affect your app performances and it could be better to use imperative code. 根据您的初始数组的大小,它可能会影响您的应用程序性能,使用命令式代码可能会更好。

A modern technique to handle these intermediate array allocations while keeping a functional programming style is to use transducers . 在保持功能编程风格的同时处理这些中间阵列分配的现代技术是使用换能器 It seels there are 2 main JS implementations for now: 它现在有2个主要的JS实现:

This may be considered as a premature optimization for small arrays, but actually transducers are not very complicated and does not introduce that much complexity. 这可能被认为是小阵列的过早优化,但实际上换能器并不是非常复杂并且不会引入那么多复杂性。 If you want to feel at home you can even use underscore-tranceducers which offers an API very similar to Underscore. 如果你想有宾至如归的感觉,你甚至可以使用下划线 - 恍惚者 ,它提供与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;
    }, []);

with filter map reduce, you can simple achieve this by vanilla js 使用filter map reduce,你可以通过vanilla js简单地实现这一点

All of the following one-trick functions were taken from mofun.js , something i wrote to be like lodash, but completely modular (no internal depends between methods) and that took full advantage of native methods. 以下所有单一功能都来自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

the code remains much the same as lodash, except for the part about finding unique objects based on a sub-property (instead of whole object compares), which i accomplished by grouping by that property, then plucking the first element from each group; 代码与lodash完全相同,除了关于基于子属性(而不是整个对象比较)查找唯一对象的部分,我通过对该属性进行分组,然后从每个组中提取第一个元素来完成; adjust as needed. 根据需要调整。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在现代浏览器中实现lodash _.remove函数? - How can I implement the lodash _.remove function in modern browsers? 我可以在使用JavaScript的现代浏览器中使用或打开“插入”插入符号吗? - Can I use or turn on the 'insert' caret in modern browsers using javascript? 在现代浏览器中是否可以使用安全的Java代码 - Is Secure Javascript Code Possible in Modern Browsers 我如何在JavaScript中构建一个过滤链,以lodash的包装风格? - How can I build, in JavaScript a filter chain, in the style of lodash's wrap? 如何在现代浏览器中全局监听获取完成? - How can I globally listen for fetch completion in modern browsers? 为什么我不能连接这一系列的lodash电话? - Why can't I chain this series of lodash calls? 在现代浏览器中,JavaScript 书签是否有任何安全限制? - In modern browsers, is there any security limitation for JavaScript bookmarklets? 使用Javascript优化现代浏览器(Chrome)的计时器 - Optimising timers for modern browsers (Chrome) in Javascript 如果我只需要支持IE10及更高版本(和其他现代浏览器),则HTML选项卡是最好的方法 - HTML Tabs the best way if I only have to support IE10 and above (and other modern browsers) 我们如何在现代Web浏览器中使用es6模块而不转换代码 - How can we use es6 modules in modern web browsers without transpiling the code
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM