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

objutil

v2.17.4

Published

Javascript Object util with deep traverse, support ES6 tree shaking methods: get/set/unset/remove object path, visit, assign(extend), merge, remove, defaults, pick, filter, forEach, map, some, every, isEqual. Customize the APIs into one file.

Downloads

122

Readme

objutil

Javascript Object util methods with deep traverse, with ES6 tree shaking methods: get/set/unset/remove object path, visit, assign(extend), merge, remove, defaults, pick, filter, isEqual. Customize the APIs into one file.

Build Status npm

Why?

Compared with Array, javascript missing the Object utils, think Array.prototype.filter, Array.prototype.map conterpart of Object

Unlike lodash, objutil only provide methods for Object, like Object.pick, Object.defaults, Object.get etc, small and customizable

Features

  1. Small, dynamically generate API using tree shaking to select only the methods you want, remove unused code for size optimization

lodash, _.assign and _.defaults: 31KB VS objutil version: 0.7KB!

  1. Deep by default: all methods is deeply operation, like below:
pick(
    { a:2, b:{c:3, e:5}, d:4 },  //src object
    { b:{c:1}, d:1 }   // selection
)
// => { b:{c:3}, d:4 }

How?

If you don't need dynamically generate API, all methods is out of box, nothing needed.

If you need generate API for yourself, do below:

  1. Install rollup: npm install -g rollup

  2. Select the API by below command line:

rollup -c --api assign,defaults
rollup -c --api 'isPrimitive as isP, isIterable as isT'
// then use objutil.isP as `isPrimitive`, etc.

Or add below line in your npm scripts of package.json:

scripts: {
  ...
  "objutil": "rollup -c ./node_modules/objutil/rollup.config.js --api assign,pick"
}

This will tree shake the lib, leave only objutil.assign, objutil.defaults methods

Install

  • NPM
npm install objutil
  • Browser
<script src="https://unpkg.com/objutil"></script>

Quick Start:

Think below initial vars:

var a = {
  x:1,
  y:{
    w:1,
    z:2
  }
}

var b= {
  y:{
    z:10,
    u:'name'
  }
}

Use with objutil:

var {merge, remove} = require('objutil')
merge(a,b)
remove(a,b)

API

visit( obj, fn )

Visit each obj node (key:value pair), with fn({val, key, path, col})

val & key is current value and key pair

path is the current object path for the key,

col is the current collection object

[] indicate the root path, ['a', 'b'] is the path of node x:1 in { a: { b: {x:1} } }

visit( {a:2, b:{c:3}}, (v) => console.log(v.key, v.val, v.path) )

// prints
a 2 []
b {c:3} []
c 3 ['b']

get( obj, pathArray, isThrow )

Get object value from pathArray. When not found, throw error if isThrow is true, else return [undefined, 1]

The result, if NOT isThrow, is the form: [data, errorCode], errorCode===1, indicate: not found.

If path exists, return [data], indicate no error.

If isThrow, return data when found, return Error('NotFound') when not found.

get( a, ['y', 'z'] )

//result is
[2]

//throw error when not found
get(a, ['x', 'y'], true)

//return with error code
get(a, ['x', 'y'])
[undefined, 1]

got( obj, propArray, defaultValue )

Search each path in propArray, return first value found, or defaultValue if none found.

Where you can use get, you can use got, which also give you fallback into different path and defaultValue.

got( {prop: {value: 1}}, ['prop1', 'prop2'], 3 )

//result is
3

got( {prop: {value: 1}}, 'prop.value' )

//result is
1

set( obj, pathArray, value, descriptor )

Set object value from pathArray. When there's non-object in the path, throw error, return the final object

Set pathArray in obj to value, when the path not exist or all the intermediate is object.

When descriptor is object, will modify the prop according Object.defineProperty

When found non-object value in intermediate, throw Error('cannot set non-object path')

set( {}, ['y', 'z'], 23 )

//result is
{ y: { z: 23 } }

// but below will return Error object
set( { y:1 }, ['y', 'z'], 23 )
//result is
Error('cannot set non-object path')

set( {}, 'a', 2, {e:0, w:0, c:1} )

{a:2}  // a is configurable, but not enumerable and writable

OR:

set( {}, 'a', 2, {configurable:false, enumerable:false, writable:false} )

OR SAME AS ABOVE:

set( {}, 'a', 2, {} )

{a:2}  // a is not configurable, enumerable and writable

ensure( obj, pathArray, defaultValue )

Like set, but only set when pathArray not exists

Set pathArray in obj to defaultValue, only when path not exists.

Return undefined if path exists, and do nothing, else return obj

obj = ensure( {}, ['y', 'z'], 1 )

//result is
obj = { y: { z: 1 } }

ret = ensure( obj, ['y', 'z'], 2 )
// ret===undefined
// obj==={ y: { z: 1 } }
// obj unchanged

unset( obj, pathArray )

Unset object value from pathArray. When there's non-object in the path, return undefined, or true/false as result

unset( {prop: {value: 1}}, 'prop.value' )

//result is
true

assign( obj, ...args )

Shallow assign args properties into obj, from left to right order.

Roughly equal to lodash.assign and Object.assign

assign( a, b, {w:3} )

//result=>
{
  x:1,
  y:{
    z:10,
    u:'name'
  },
  w:3
}

merge( obj, ...args )

Deeply merge args properties into obj, from left to right order.

Roughly equal to lodash.merge

merge( a, b, {y:{v:3}} )

//result=>
{
  x:1,
  y:{
    v:3,
    w:1,
    z:10,
    u:'name'
  }
}

defaults( obj, ...args )

deeply merge args key/val into obj, left to right, only when it's not existing in obj

Roughly equal to lodash.defaultsDeep (deeply lodash.defaults)

defaults( {}, {a:1}, {a:2, b:5 } )

//result=>
{
  a:1,
  b:5
}

remove( obj, removeObj, [force] )

Deeply delete removeObj(if force or key has a truthy value) from obj, optionally set to newValue if present

remove( a, { y:{z:true} } )

//result=>
{
  x:1,
  y:{
    w:1
  }
}

pick( obj, pickObject, force)

Like remove, but return the reversed new object(not mutate obj). Deeply keep from pickObject (if force or key has a truthy value) from obj

If obj is primitive types, then always return {}

pick( a, {x:true, y:{z:true} } )

//result=>
{
  x:1,
  y:{
    z:2
  }
}

filter( obj, predicate)

return array of key path(dot notation) that passed predicate

predicate: fn({val, key, path, col}) -> true/false

expect(lib.filter({a:1, b:{c:2, d:3}, e:4}, function(v) {
  return v.path=='' && v.val % 2
})).deep.eql(['a'])

isEqual( objA, objB )

deeply compare objA and objB for equality

isEqual( {a:1, b:2}, {a:1, b:2 } )

//result=> true

forEach( obj, callback )

callback: fn(value, key, obj) -> false?, return false will exit iteration

forEach( {a:1, b:2}, function(val, key){ console.log(val, key) } )

// 1, 'a'
// 2, 'b'

map( obj, callback )

callback: fn(value, key, obj) -> val, return array of val

Like Array.prototype.map does for Object

map( {a:1, b:2}, (val, key)=>key+val )

['a1', 'b2']

some( obj, callback )

callback: fn(value, key, obj) -> true/false, return true/false

Like Array.prototype.some does for Object

some( {a:1, b:2}, (val, key)=>val>1 )

true

every( obj, callback )

callback: fn(value, key, obj) -> true/false, return true/false

Like Array.prototype.every does for Object

every( {a:1, b:2}, (val, key)=>val>1 )

false

deepIt( a, b, callback )

Iterate b with deeply sync props of a, and callback(objA, objB, key)

deepIt( a, b, function(objA,objB,key){
    objA[key] = objB[key]
} )
// ---> same result of assign(a,b)

MIT