Watch.js Object Observer
Watch.js is a compact, browser-compatible JavaScript library designed to implement the Observer design pattern, allowing developers to monitor changes to JavaScript objects and their attributes without altering existing development methodologies. It enables watching single attributes, multiple attributes, or all attributes of an object, invoking a callback function upon detected mutations. The library, last updated around 9 years ago (with version 1.2.0 mentioned in its README but 0.0.0 on npm), primarily operates by polluting the global scope, exposing `watch` and `unwatch` functions, and a `WatchJS` object. While simple to integrate via a direct script inclusion, its reliance on global scope and direct object mutation for reactivity is largely superseded by modern JavaScript features like Proxies and reactive frameworks. It is considered abandoned, with no active maintenance or updates.
Common errors
-
ReferenceError: watch is not defined
cause The Watch.js script was not correctly loaded or executed before attempting to call the 'watch' function.fixEnsure the watch.js file is included via a <script> tag in your HTML, placed before any code that attempts to use 'watch' or 'unwatch', e.g., <script src="path/to/watch.js"></script>. -
Unexpected behavior: watcher not firing for attribute change.
cause Another watcher might have set `WatchJS.noMore = true;` or the object change is not being deeply observed as intended, or the 'level' parameter for deep watching is not set.fixCheck if `WatchJS.noMore` is inadvertently set to `true` in a preceding watcher. For deep observation, ensure the correct 'level' parameter is passed to the `watch` function, or consider the library's limitations with deeply nested or dynamically added properties. -
TypeError: Cannot set property '<property>' of undefined
cause Attempting to watch an object that is null, undefined, or not a plain JavaScript object.fixEnsure the first argument passed to the 'watch' function is a valid, instantiated JavaScript object before attempting to observe it.
Warnings
- breaking Watch.js is an abandoned library and has not been updated in approximately 9 years. It relies on modifying global object prototypes to detect changes, which can lead to conflicts and unexpected behavior with other libraries or modern JavaScript features. There are no plans for future updates or security patches.
- gotcha The library pollutes the global scope by exposing 'watch', 'unwatch', and 'WatchJS' as global variables (e.g., window.watch). This can lead to naming collisions and make it difficult to integrate into modular JavaScript environments.
- gotcha Watch.js uses deprecated browser mechanisms for object observation and may have 'some bugs with older browsers' as stated in its original README. It does not leverage modern browser APIs like MutationObserver for DOM changes, focusing solely on plain JavaScript objects.
- gotcha The `WatchJS.noMore = true` flag is a global state mechanism intended to prevent recursive watcher calls. Incorrect usage or failure to understand its lifecycle can lead to watchers not firing when expected or unexpected side effects across different parts of your application.
Install
-
npm install watchjs -
yarn add watchjs -
pnpm add watchjs
Imports
- watch
import { watch } from 'watchjs';<script src="path/to/watch.js"></script> // Then access as `window.watch` or simply `watch` if in global scope
- unwatch
import { unwatch } from 'watchjs';<script src="path/to/watch.js"></script> // Then access as `window.unwatch` or simply `unwatch` if in global scope
- WatchJS
import { WatchJS } from 'watchjs';<script src="path/to/watch.js"></script> // Then access as `window.WatchJS` or simply `WatchJS` if in global scope
Quickstart
// Include Watch.js via a script tag in your HTML:
// <script src="https://raw.githubusercontent.com/melanke/Watch.JS/master/src/watch.js"></script>
// defining our object however we like
var myObject = {
attribute1: "initial value",
attribute2: 123
};
// defining a 'watcher' for a specific attribute
watch(myObject, "attribute1", function(prop, action, newValue, oldValue){
console.log(`Attribute '${prop}' changed from '${oldValue}' to '${newValue}'. Action: ${action}`);
});
// defining a 'watcher' for all attributes on the object
watch(myObject, function(){
console.log("Any attribute of myObject changed!");
});
// when changing the attribute, its watcher will be invoked
myObject.attribute1 = "new value";
// changing another attribute will invoke the general object watcher
myObject.attribute2 = 456;