
Research
Two Malicious Rust Crates Impersonate Popular Logger to Steal Wallet Keys
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
The on-change package is a utility for watching changes in JavaScript objects and arrays. It allows you to execute a callback function whenever a change is detected, making it useful for state management, debugging, and reactive programming.
Watch for changes in objects
This feature allows you to watch for changes in an object's properties. When a property changes, the callback function is triggered, providing the path of the changed property, the new value, and the previous value.
const onChange = require('on-change');
const object = {
foo: 'bar'
};
const watchedObject = onChange(object, function (path, value, previousValue) {
console.log('Object changed:', path, value, previousValue);
});
watchedObject.foo = 'baz'; // Console: Object changed: foo baz bar
Watch for changes in arrays
This feature allows you to watch for changes in arrays. The callback function is triggered whenever the array is modified, such as when elements are added or removed.
const onChange = require('on-change');
const array = [1, 2, 3];
const watchedArray = onChange(array, function (path, value, previousValue) {
console.log('Array changed:', path, value, previousValue);
});
watchedArray.push(4); // Console: Array changed: 3 4 undefined
Nested property change detection
This feature allows you to detect changes in nested properties of objects. The callback function provides the full path to the changed property, making it easy to track changes deep within an object structure.
const onChange = require('on-change');
const nestedObject = {
level1: {
level2: {
foo: 'bar'
}
}
};
const watchedNestedObject = onChange(nestedObject, function (path, value, previousValue) {
console.log('Nested object changed:', path, value, previousValue);
});
watchedNestedObject.level1.level2.foo = 'baz'; // Console: Nested object changed: level1.level2.foo baz bar
The proxy-compare package provides utilities for creating proxies that can detect changes in objects and arrays. It is similar to on-change in that it uses JavaScript proxies to track changes, but it focuses more on efficient comparison and change detection for use in state management libraries.
Immer is a package that allows you to work with immutable state by using a proxy-based approach to detect changes and produce new state objects. While on-change focuses on detecting changes and triggering callbacks, Immer is more about immutability and producing new state from changes.
MobX is a state management library that uses observable objects to automatically track changes and update the UI. It provides more comprehensive state management features compared to on-change, which is more lightweight and focused on change detection.
Watch an object or array for changes
It works recursively, so it will even detect if you modify a deep property like obj.a.b[0].c = true
.
Uses the Proxy
API.
npm install on-change
import onChange from 'on-change';
const object = {
foo: false,
a: {
b: [
{
c: false
}
]
}
};
let index = 0;
const watchedObject = onChange(object, function (path, value, previousValue, applyData) {
console.log('Object changed:', ++index);
console.log('this:', this);
console.log('path:', path);
console.log('value:', value);
console.log('previousValue:', previousValue);
console.log('applyData:', applyData);
});
watchedObject.foo = true;
//=> 'Object changed: 1'
//=> 'this: {
// foo: true,
// a: {
// b: [
// {
// c: false
// }
// ]
// }
// }'
//=> 'path: "foo"'
//=> 'value: true'
//=> 'previousValue: false'
//=> 'applyData: undefined'
watchedObject.a.b[0].c = true;
//=> 'Object changed: 2'
//=> 'this: {
// foo: true,
// a: {
// b: [
// {
// c: true
// }
// ]
// }
// }'
//=> 'path: "a.b.0.c"'
//=> 'value: true'
//=> 'previousValue: false'
//=> 'applyData: undefined'
watchedObject.a.b.push(3);
//=> 'Object changed: 3'
//=> 'this: {
// foo: true,
// a: {
// b: [
// {
// c: true
// },
// 3
// ]
// }
// }'
//=> 'path: "a.b"'
//=> 'value: [{c: true}, 3]'
//=> 'previousValue: [{c: true}]'
//=> 'applyData: {
// name: "push",
// args: [3],
// result: 2,
// }'
// Access the original object
onChange.target(watchedObject).foo = false;
// Callback isn't called
// Unsubscribe
onChange.unsubscribe(watchedObject);
watchedObject.foo = 'bar';
// Callback isn't called
Returns a version of object
that is watched. It's the exact same object, just with some Proxy
traps.
Type: object
Object to watch for changes.
Type: Function
Function that gets called anytime the object changes.
The function receives four arguments:
c
in the above example would return a.b.0.c
.WeakSets
and WeakMaps
will return undefined
.The context (this) is set to the original object passed to onChange
(with Proxy).
Type: object
Options for altering the behavior of onChange.
Type: boolean
Default: false
Deep changes will not trigger the callback. Only changes to the immediate properties of the original object.
Type: Function
Default: Object.is
The function receives two arguments to be compared for equality. Should return true
if the two values are determined to be equal. Useful if you only need a more loose form of equality.
Type: boolean
Default: false
Setting properties as Symbol
won't trigger the callback.
Type: Array<string | symbol>
Default: undefined
Setting properties in this array won't trigger the callback.
Type: boolean
Default: false
Setting properties with an underscore as the first character won't trigger the callback.
Type: boolean
Default: false
The path will be provided as an array of keys instead of a delimited string. Recommended when working with Sets, Maps, or property keys that are Symbols.
Type: boolean
Default: false
Ignore changes to objects that become detached from the watched object.
Type: boolean|string[]
Default: false
Trigger callbacks for each change within specified method calls or all method calls.
Type: Function
The function receives the same arguments and context as the onChange callback. The function is called whenever a change is attempted. Returning true will allow the change to be made and the onChange callback to execute, returning anything else will prevent the change from being made and the onChange callback will not trigger.
Returns the original unwatched object.
Type: object
Object that is already being watched for changes.
Cancels all future callbacks on a watched object and returns the original unwatched object.
Type: object
Object that is already being watched for changes.
I had some code that was like:
const foo = {
a: 0,
b: 0
};
// …
foo.a = 3;
save(foo);
// …
foo.b = 7;
save(foo);
// …
foo.a = 10;
save(foo);
Now it can be simplified to:
const foo = onChange({
a: 0,
b: 0
}, () => save(foo));
// …
foo.a = 3;
// …
foo.b = 7;
// …
foo.a = 10;
Proxy
too)array[-1]
(Uses Proxy
too)Proxy
too)Proxy
too)FAQs
Watch an object or array for changes
The npm package on-change receives a total of 407,825 weekly downloads. As such, on-change popularity was classified as popular.
We found that on-change demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
Research
A malicious package uses a QR code as steganography in an innovative technique.
Research
/Security News
Socket identified 80 fake candidates targeting engineering roles, including suspected North Korean operators, exposing the new reality of hiring as a security function.