obj.mjs provides tools for manipulating JS objects in weird ways.
- #
function assign - #
function patch - #
function memGet - #
function MixStruct - #
function MixStructLax - #Undocumented
import * as o from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.85/obj.mjs'Links: source; test/example.
Signature: (tar, src) => tar.
Similar to Object.assign. Differences:
- Much faster.
- Exactly two parameters, not variadic.
- Sanity-checked:
Similar to #patch but doesn't check for inherited and non-enumerable properties. Simpler, dumber, faster.
Links: source; test/example.
Signature: (tar, src) => tar.
Similar to Object.assign. Differences:
- Much faster.
- Takes only two args.
- Sanity-checked:
When overriding inherited and non-enumerable properties is desirable, use #assign.
Links: source; test/example.
Takes a class and hacks its prototype, converting all non-inherited getters to lazy/memoizing versions of themselves that only execute once. The resulting value replaces the getter. Inherited getters are unaffected.
import * as o from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.85/obj.mjs'
class StructLax extends o.MixStruct(l.Emp) {}
class Bucket {
static {o.memGet(this)}
get one() {return new StructLax()}
get two() {return new StructLax()}
}
const ref = new Bucket()
// Bucket {}
ref.one.three = 30
ref
// Bucket { one: Struct { three: 30 } }
ref.two.four = 40
ref
// Bucket { one: Struct { three: 30 }, two: Struct { four: 40 } }Links: source; test/example.
Mixin for classes representing a "struct" / "model" / "record". Also see #MixStructLax. Features:
- Supports explicit specs with validation / transformation functions.
- Can be instantiated or mutated from any r (any dict-like object); each field is validated by the user-defined spec.
- Assigns and checks all declared fields when instantiating via
new. Ignores undeclared fields. - Supports partial updates via the associated function
structMut(not a method), which assigns and validates known fields provided in the input. - Supports deep mutation: when updating a struct, automatically detects sub-structs and mutates them, and invokes
.muton any object that implements this method. - Uses regular JS fields. Does not use getters / setters, proxies, private fields, non-enumerable fields, symbols, or anything else "strange". Declared fields are simply assigned via
=.
Performance characteristics:
- The cost of constructing or mutating depends only on declared fields, not on provided fields.
- When the number of declared fields is similar to the number of provided fields, this tends to be slightly slower than
Object.assignor #assign. - When the number of declared fields is significantly smaller than the number of provided fields, this tends to be faster than the aforementioned assignment functions.
import * as l from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.85/lang.mjs'
import * as o from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.85/obj.mjs'
class Person extends o.MixStruct(l.Emp) {
static spec = {
id: l.reqFin,
name: l.reqStr,
}
}
// Fails the type check.
new Person({id: 10})
/* Uncaught TypeError: invalid property "name" */
// Fails the type check.
new Person({name: `Mira`})
/* Uncaught TypeError: invalid property "id" */
// Satisfies the type check.
new Person({id: 10, name: `Mira`})
/* Person {id: 10, name: "Mira"} */
// Ignores undeclared fields.
new Person({id: 10, name: `Mira`, slug: `mira`, gender: `female`})
/* Person {id: 10, name: "Mira"} */Links: source; test/example.
Mixin for classes representing a "struct" / "model" / "record". Similar to #MixStruct, with additional support for undeclared fields.
Differences from #MixStruct:
- When instantiating via
newor mutating viastructMut, in addition to assigning and validating all declared fields, this also copies any undeclared fields present in the source data. - Has slightly worse performance.
import * as l from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.85/lang.mjs'
import * as o from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.85/obj.mjs'
class Person extends o.MixStructLax(l.Emp) {
static spec = {
id: l.reqFin,
name: l.reqStr,
}
}
// Fails the type check.
new Person({id: 10})
/* Uncaught TypeError: invalid property "name" */
// Fails the type check.
new Person({name: `Mira`})
/* Uncaught TypeError: invalid property "id" */
// Satisfies the type check.
new Person({id: 10, name: `Mira`})
/* Person {id: 10, name: "Mira"} */
// Assigns undeclared fields in addition to declared fields.
new Person({id: 10, name: `Mira`, slug: `mira`, gender: `female`})
/* Person {id: 10, name: "Mira", slug: "mira", gender: "female"} */The following APIs are exported but undocumented. Check obj.mjs.
function isObjKeyfunction reqObjKeyfunction isMutfunction reqMutfunction pubfunction privfunction finalfunction getterfunction setterfunction getSetclass DynVarclass TypedDynVarclass Cacheclass WeakCacheclass Mixinclass MemGetconst MAINfunction MixMainclass MixinMainconst SPECfunction isStructfunction structSpecfunction structConstructfunction structMutclass MixinStructclass MixinStructLaxfunction MixStructMutclass MixinStructMutclass StructSpecclass StructSpecLaxclass FieldSpecfunction mutatedfunction deinitfunction descIn