npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@marvintau/jpl

v0.1.4

Published

| 语句覆盖率 | 分支覆盖率 | 函数覆盖率 | 代码行覆盖率 | | -----------|----------|-----------|-------| | ![Statements](https://img.shields.io/badge/Coverage-76.91%25-red.svg) | ![Branches](https://img.shields.io/badge/Coverage-67.26%25-red.svg) | ![Functions](https://img.shiel

Downloads

5

Readme

| 语句覆盖率 | 分支覆盖率 | 函数覆盖率 | 代码行覆盖率 | | -----------|----------|-----------|-------| | Statements | Branches | Functions | Lines |

Chuā - 欻

简介

「欻」是一个对JavaScript内建的数据结构(Array和Plain Object)进行操作的一套函数集合。在大部分场合下我们的数据比较简单,没有很复杂的结构和行为,就像JSON表示的那样。我们不需要建立一个像LokiJS那样的内存数据库,也不需要像immutable.js那样用HAMT实现的persistent数据结构。我们只需要使用JavaScript自带的Object``表示记录,以及Array`来表示列表就可以了。

安装

$ npm i --save @marvintau/chua

记录 (Record)

在Python中有Dict类型,在JS中对应的类型是万能的Object。然而JS中Object有太多广泛的含义,它可以是一个存放数据的字典,也可以是一个Prototype,也可以是用一个Prototype创建出来的类(prototype和类的概念还有很大区别),也可以是用一个类创建出的对象,所以我们需要加以区分。我们只想利用Plain Object来存放数据。

所谓的"Plain Object"是指通过Object LiteralObject.create({})创建的Object实例。

所谓的「记录」可以是任意Plain Object,但是以下方法会向它添加一些属性。

  • __children: 是一个Array,其中将会保存作为当前Record孩子的其它Record。树形结构就是靠它实现的。__children只有在执行向Record添加孩子的时候才会创建。
  • __path: 是一个Array,保存从最外层Array通向当前Record所经过的所有Record的children的索引。我们可能需要单独引用Record时可能会涉及到对它所在的原始数据结构进行操作。这时就可以通过__path来找到对应的Record,具体的方法会在下面的API中介绍。

设计数据结构的思路

Q: 为什么不继承Object创建一个新的Record类?

因为在JS中继承的概念比较费解。从面向对象的角度来看JS中所有的类都继承自Object,更具体地来说,就是扩展了Object.prototype。然而作为prototype的对象本身就是一个Object,这导致了对Object类的继承无论如何都会修改Object本身的定义,这也是一般的面向对象思路在Object这里都会变得很奇怪。因此你会发现很多针对Object的方法都是静态方法,例如entries。所以为了避免麻烦,我们既不定义一个Record类来扩展Object,也不创建一个Record类并将Object作为其中一个属性,而是提供了一系列操作Object的函数,来实现我们想要的功能。

Q: 为什么__children__path都是enumerable的?将它们定义为non-enumerable并使得它们不出现在for .. in循环中难道不更好吗?

这样是会好一些,因为在逻辑上__children__path并不应该作为「记录」的一部分。然而将它们设置为non-enumerable会带来一些问题,最主要的问题是序列化。大部分前后端通信的库都封装了JSON的stringify/parse的方法,使得发送方可以直接传入对象,而接收方得到的则是经过parse的对象。然而问题是non-enumerable的属性不会被序列化,因此默认情况下接收方会丢失__children__path的信息,除非我们在发送之前将它们重新定义为enumerable。显然这带来了更多的麻烦和需要考量的因素。

get

用法:

get(array, {path, indexColumn, withList})

其中

  • array: 包含所有数据的数组
  • path: 从根结点(array)到所要寻找的数据的路径。
    • 当path是一个array of integer时,将通过每一级record.__children的index来寻找。
    • 当path是一个array of string时,则通过每一级record.__children中,某一字段匹配path中的值来寻找。此时需要给定indexColumn,也就是字段名,否则会报错。
  • indexColumn: 当path是array of string时所提供的作为索引的字段名。
  • withList: 如果withList的值为true,则返回值中将包含list,详见返回值的说明

返回:

{record, sublings, list}

其中

  • record: 要找的那个Record
  • sublings: 要找的Record所在的__children
  • list: 如果withList参数值为true,那么list中将包含从arrayrecord之间所有经过的record

在实现类似「自动完成」或者「提示」一类的功能时,你可能需要知道你要找的Record的其它同辈记录,sublings就是为了完成这个目的添加进来的。

add

add(array, recs, {path, column, adIndex})

其中:

  • recs: 待插入的Record,或者包含RecordArray
  • array: 包含所有数据的数组
  • path: 从根结点(array)到所要寻找的数据的路径。
    • 当path是一个array of integer时,将通过每一级record.__children的index来寻找。
    • 当path是一个array of string时,则通过每一级record.__children中,某一字段匹配path中的值来寻找。此时需要给定column,也就是字段名,否则会报错。
  • column: 当path是array of string时所提供的字段名。
  • atIndex: 添加记录的位置。如果atIndex是一个整数,则按照Array.splice的第一个参数向array或记录的__children添加记录,否则按Array.push向后添加。

返回:

addget的参数很类似,因为add本身就用到了get。如果path指向了一个Record,那么会向这个Record__children添加。如果path为空,或者没有第三个options的选项,那么会直接添加到array中。

示例:

const array = [{num: 0, name: 'asd'}, {num: 1, name:'dsda'}];
add(array, {num:2, name:'bsd'});
console.log(array);

const array = [{num: 0, name: 'asd'}, {num: 1, name:'dsda'}];
add(array, {num:2, name:'bsd'}, {path=[0]});
console.log(array);

set

set(array, kvs, {path, column, adIndex})

其中:

  • array: 包含被操作数据的数组
  • kvs: 包含

del

sort

flat

group