Javascript 数据操作工具包 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
爱意满满的作品展示区。
wm123450405

Javascript 数据操作工具包

  •  2
     
  •   wm123450405
    wm123450405 Mar 29, 2018 3833 views
    This topic created in 2950 days ago, the information mentioned may be changed or developed.

    源码:

    https://github.com/wm123450405/linqjs
    https://gitee.com/wm123450405/linqjs (国内)

    简介:

    • 对 Javascript 中原生数组、对象进行扩展, 提供了一些对数据的操作方法.
    • 包括对数组结构、树形结构、对象结构等数据进行 查询,排序,连接,合并,分组,分段,转换,遍历 等一系列功能.
    • 可以用精炼和易懂的代码实现比较复杂的操作

    案例:

    • 案例 1
    let array = [ 'zhao', 'qian', 'sun', 'li', 'zhou', 'wu', 'zheng', 'wang' ] //将上述数组按照字母长度进行排序, 字母长度一致的按照字母顺序倒序排序 console.log(array.asEnumerable().orderBy(str => str.length).thenByDescending().toArray()); //结果为 //wu,li,sun,zhou,zhao,wang,qian,zheng 
    • 案例 2
    //一些人 let magnus = { name: "Hedlund, Magnus" }, terry = { name: "Adams, Terry" }, charlotte = { name: "Weiss, Charlotte" }; //一些宠物 let barley = { name: "Barley", owner: "Adams, Terry" }, boots = { name: "Boots", owner: "Adams, Terry" }, whiskers = { name: "Whiskers", owner: "Weiss, Charlotte" }, daisy = { name: "Daisy", owner: "Hedlund, Magnus" }; //一个包含所有 人 的数组 let people = [ magnus, terry, charlotte ]; //一个包含所有 宠物 的数组 let pets = [ barley, boots, whiskers, daisy ]; //这是一个一对多关系的两个数组 //需要显示出来所有的 人-宠物 的关系信息 //传统做法是 for (let p of people) { for (let pet of pets) { if (pet.owner === p.name) { console.log(`${ p.name } - ${ pet.name }`); } } } //使用我的工具是 //思想类似数据库查询(如下语句), 连接两个数组(表), 条件为 person 的 name 与 pet 的 owner 相等 //select person.name, pet.name from `people` as person join `pets` as pet on person.name = pet.owner people.asEnumerable() .join(pets, (person, pet) =>`${ person.name} - ${ pet.name}`, person => person.name, pet => pet.owner) .forEach(res => console.log(res)); 
    • 案例 3
    //这是一个树形结构 let tree = { value: 'a', children: [ { value: 'b', //此节点为 节点 c 与 节点 f 的最小公共祖先 children: [ { value: 'c' }, { value: 'd', children: [ { value: 'e' }, { value: 'f' }, { value: 'g' }, ] } ] }, { value: 'h', } ] }; //获取一个树形的中多个节点的最小公共祖先 let root = tree.asEnumerable(node => node.children, node => node.value); console.log(root.lowestAncestor('c', 'f')); //结果是 b 

    更多用法及案例 希望大家进入文档查看 http://wm123450405.oschina.io/linqjs/#/zh-cn

    望大家多多关注 并给于意见和指导 谢谢

    19 replies    2018-04-02 16:39:17 +08:00
    wm123450405
        1
    wm123450405  
    OP
       Mar 29, 2018
    一开始,在 ES5 的时代,我觉得 js 对数组的操作实在太繁琐了. 可能正是这种繁琐才有了像 underscore 这样优秀的 js 库的出现.

    我本不是做前端出身的,我觉得其他语言对于数组或列表的操作要比 js 好用很多,提供了大量的方法和功能. 于是最早参考的 C#中的功能实现了一些方法.

    后来,ES6 发布并普及开来,js 原生数组也增加了很多好用的功能,但是这还远远不够.

    于是我又翻出了我的代码用 ES6 重写.这一次我又借鉴了另外一些语言中的部分特性,比如 php.我想我后面可能再会添加一些其他语言类似的功能,比如 Java 等.

    后来我在 stackoverflow 中看到很多人对于树形结构的操作提了很多的问题,我像我的工具包应该要可以为他们提供帮助.于是在最新的几个版本中我加入了对树形结构的一些操作.

    我想现在这个工具包应该算比较稳定了. 所以我发上来希望和大家交流交流. 也希望能学到更多的东西.
    codermagefox
        2
    codermagefox  
       Mar 29, 2018
    楼主你好,请问我能抄一个自己做实现吗?
    per
        3
    per  
       Mar 29, 2018 via iPhone
    @wm123450405 没看代码,不过你这个是在数据类型的 prototype 上修改的吗?
    wm123450405
        4
    wm123450405  
    OP
       Mar 29, 2018
    @per 是的 在 prototype 上做了扩展的
    wm123450405
        5
    wm123450405  
    OP
       Mar 29, 2018
    @codermagefox 可以啊 我也是造了一些轮子而已
    codermagefox
        6
    codermagefox  
       Mar 29, 2018   1
    @wm123450405 #5 准备看完 underscore 再来看你这个,然后自己撸个试试。感谢,已 star
    per
        7
    per  
       Mar 29, 2018 via iPhone
    @wm123450405 那我这里有个问题,比如一个数组是由一个类 A 实例化得到的,然后这个 A 也是继承于其他类,那当访问你的这个方法的时候会通过原型链一层层往上找,考虑过开销嘛?
    crs0910
        8
    crs0910  
       Mar 29, 2018   2
    wm123450405
        9
    wm123450405  
    OP
       Mar 29, 2018 via Android
    @per 不好意思 不是很明白你想表达的意思 你可以举例说明下嘛 我这里只是扩展了 Array 类 用 Array.prototype 的方式
    wm123450405
        10
    wm123450405  
    OP
       Mar 29, 2018 via Android
    @crs0910 你是让我看看 mootools 这个库吗? 如果你希望的只是类似 flatMap 这样的展开一个包含数组元素的数组 在我的库里是 selectMany
    zenxds
        11
    zenxds  
       Mar 29, 2018   1
    改原生数组的原型后患无穷,ES 标准里的一些方法名那么奇怪就是因为当年 prototype.js 的遗留才不得不改名
    wm123450405
        12
    wm123450405  
    OP
       Mar 29, 2018 via Android
    @zenxds 我的库默认只会在 Array 上注册一个 asEnumerable 方法 用来获取一个 IEnumerable 对象进行后续操作 当然也可以开启对 Array 的直接扩展 主要看你有没有用到其他有冲突的库
    per
        13
    per  
       Mar 29, 2018   1
    @wm123450405 我表达的不是很清楚,你可以看一下 MDN 上的解释。不过还是给你点个星
    wm123450405
        15
    wm123450405  
    OP
       Mar 29, 2018
    @per 感谢你提供的信息. 我想我在编写这个库的时候并没有考虑这一层面的性能问题.
    首先你分享的文章我不是特别的明白 我理解的大概含义 一般的 js 引擎会对已有的对象的属性查找进行优化 会将属性按照某种顺序排列在内存中 并生成一个身份(shape 或 structure ID) 如果修改 prototype 的话 会打乱这种顺序 导致原本可以快速查找属性的功能失效 造成性能损失
    就你一共提出的问题 我想:
    如果说因为原型链比较深导致其查找 property 比较慢的话 我想这个应该不容易避免 因为原型链的深度是受类型的继承关系的影响
    如果是因为修改 prototype 导致 js 引擎在做优化时不能达到最佳性能的话 我目前也没有更好的解决办法
    wm123450405
        16
    wm123450405  
    OP
       Mar 29, 2018 via Android
    首先感谢各位的关注 如果大家发现有什么问题或者有什么希望加入的功能 欢迎大家在此回复 或者直接在 github/gitee 上提 issue 给我
    0x4b0082
        17
    0x4b0082  
       Apr 2, 2018   1
    拒绝修改原生数据类型的库:(
    narcotics
        18
    narcotics  
       Apr 2, 2018 via Android   1
    lodash 的做法是用 _.chain 做一层包装,再实现链式操作,最后用 _.value 做"拆箱"

    总之改变原生原型不是个好实践
    wm123450405
        19
    wm123450405  
    OP
       Apr 2, 2018
    回复 楼上 2 位
    首先 我的库里目前只对原生对象扩展了 asEnumerable 一个方法. 就是尽量避免冲突
    其次 库也支持 Enumerable(source)的方式获取一个和 source.asEnumerable()一样的结果, 类似 lodash 的 chain. 再使用 toArray 等方法生成最终结果.
    当然 如果大家觉得修改原生原型的做法确实不合适 我想也我会在后面的版本中修改 /删除这种方式
    About     Help     Advertise     Blog     API     FAQ     Solana     1065 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 52ms UTC 23:16 PVG 07:16 LAX 16:16 JFK 19:16
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86