Socket
Socket
Sign inDemoInstall

mobservable

Package Overview
Dependencies
Maintainers
1
Versions
79
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mobservable - npm Package Compare versions

Comparing version 0.0.6 to 0.1.0

dist/mobservable.js

41

mobservable.d.ts
declare module "mobservable" {
interface Lambda {
(): void;
(): void;
}
interface IProperty<T, S> {
(): T;
(value: T): S;
subscribe(callback: (newValue: T, oldValue: T) => void): Lambda;
interface IObservableValue<T, S> {
(): T;
(value: T): S;
subscribe(callback: (newValue: T, oldValue: T) => void): Lambda;
}
function property<T, S>(value?: T | {(): T;}, scope?: S): IProperty<T, S>;
function guard<T>(func: () => T, onInvalidate: Lambda): [T, Lambda];
function batch(action: Lambda): void;
function onReady(listener: Lambda): Lambda;
function onceReady(listener: Lambda): void;
function defineProperty<T>(object: Object, name: string, initialValue?: T): void;
interface MobservableStatic {
<T,S>(value?:T|{():T}, scope?:S):IObservableValue<T,S>;
value<T,S>(value?:T|{():T}, scope?:S):IObservableValue<T,S>;
watch<T>(func:()=>T, onInvalidate:Lambda):[T,Lambda];
array<T>(values?:T[]): IObservableArray<T>;
batch(action:Lambda);
onReady(listener:Lambda):Lambda;
onceReady(listener:Lambda);
defineProperty<T>(object:Object, name:string, initialValue?:T);
}
interface IObservableArray<T> extends Array<T> {
[n: number]: T;
length: number;
spliceWithArray(index:number, deleteCount?:number, newItems?:T[]):T[];
observe(listener:()=>void, fireImmediately:boolean):Lambda;
clear(): T[];
replace(newItems:T[]);
values(): T[];
}
export = MobservableStatic;
}

@@ -11,19 +11,31 @@ /// <reference path="./typings/node-0.10.d.ts" />

export interface Lambda {
interface Lambda {
():void;
}
export interface IProperty<T,S> {
interface IObservableValue<T,S> {
():T;
(value:T):S;
subscribe(callback:(newValue:T, oldValue:T)=>void):Lambda;
observe(callback:(newValue:T, oldValue:T)=>void):Lambda;
}
export function property<T,S>(value?:T|{():T}, scope?:S):IProperty<T,S> {
var prop:Property<T,S> = null;
interface MobservableStatic {
<T,S>(value?:T|{():T}, scope?:S):IObservableValue<T,S>;
value<T,S>(value?:T|{():T}, scope?:S):IObservableValue<T,S>;
watch<T>(func:()=>T, onInvalidate:Lambda):[T,Lambda];
array<T>(values?:T[]): ObservableArray<T>;
batch(action:Lambda);
onReady(listener:Lambda):Lambda;
onceReady(listener:Lambda);
defineProperty<T>(object:Object, name:string, initialValue?:T);
}
function observableValue<T,S>(value?:T|{():T}, scope?:S):IObservableValue<T,S> {
var prop:ObservableValue<T,S> = null;
if (typeof value === "function")
prop = new ComputedProperty(<()=>T>value, scope);
prop = new ComputedObservable(<()=>T>value, scope);
else
prop = new Property(<T>value, scope);
prop = new ObservableValue(<T>value, scope);

@@ -36,10 +48,16 @@ var propFunc = function(value?:T):T|S {

};
(<any>propFunc).subscribe = prop.subscribe.bind(prop);
(<any>propFunc).observe = prop.observe.bind(prop);
(<any>propFunc).prop = prop;
(<any>propFunc).toString = function() { return prop.toString(); };
return <IProperty<T,S>> propFunc;
return <IObservableValue<T,S>> propFunc;
}
export function guard<T>(func:()=>T, onInvalidate:Lambda):[T,Lambda] {
var mobservableStatic:MobservableStatic = <MobservableStatic> function<T,S>(value?:T|{():T}, scope?:S):IObservableValue<T,S> {
return observableValue(value,scope);
};
mobservableStatic.value = observableValue;
mobservableStatic.watch = function watch<T>(func:()=>T, onInvalidate:Lambda):[T,Lambda] {
var dnode = new DNode();

@@ -62,16 +80,20 @@ var retVal:T;

export function batch(action:Lambda) {
mobservableStatic.array = function array<T>(values?:T[]): ObservableArray<T> {
return new ObservableArray(values);
}
mobservableStatic.batch = function batch(action:Lambda) {
Scheduler.batch(action);
}
export function onReady(listener:Lambda):Lambda {
mobservableStatic.onReady = function onReady(listener:Lambda):Lambda {
return Scheduler.onReady(listener);
}
export function onceReady(listener:Lambda) {
mobservableStatic.onceReady = function onceReady(listener:Lambda) {
Scheduler.onceReady(listener);
}
export function defineProperty<T>(object:Object, name:string, initialValue?:T) {
var _property = property(initialValue, object);
mobservableStatic.defineProperty = function defineProperty<T>(object:Object, name:string, initialValue?:T) {
var _property = mobservableStatic.value(initialValue, object);
Object.defineProperty(object, name, {

@@ -89,3 +111,3 @@ get: function() {

class Property<T,S> {
class ObservableValue<T,S> {
protected events = new events.EventEmitter();

@@ -101,2 +123,3 @@ protected dependencyState:DNode = new DNode();

var oldValue = this._value;
// Optimization: intruce a state that signals ready without an initial dirty, for non-computed values
this.dependencyState.markStale();

@@ -116,3 +139,3 @@ this._value = value;

subscribe(listener:(newValue:T, oldValue:T)=>void, fireImmediately=false):Lambda {
observe(listener:(newValue:T, oldValue:T)=>void, fireImmediately=false):Lambda {
var current = this.get(); // make sure the values are initialized

@@ -129,7 +152,7 @@ if (fireImmediately)

toString() {
return `Property[${this._value}]`;
return `Observable[${this._value}]`;
}
}
class ComputedProperty<U,S> extends Property<U,S> {
class ComputedObservable<U,S> extends ObservableValue<U,S> {
private initialized = false;

@@ -140,3 +163,3 @@

if (!func)
throw new Error("ComputedProperty requires a function");
throw new Error("ComputedObservable requires a function");

@@ -158,3 +181,3 @@ this.dependencyState.compute = this.compute.bind(this);

set(_:U):S {
throw new Error("Computed cannot retrieve a new value!");
throw new Error("ComputedObservable cannot retrieve a new value!");
}

@@ -177,6 +200,227 @@

toString() {
return `ComputedProperty[${this.func.toString()}]`;
return `ComputedObservable[${this.func.toString()}]`;
}
}
/*
TODO: mention clearly that ObservableArray is not sparse, that is,
no wild index assignments with index >(!) length are allowed (that is, won't be observed)
*/
class ObservableArray<T> implements Array<T> {
[n: number]: T;
length: number;
private _supressLengthNotification: boolean;
private _values: T[];
private dependencyState:DNode;
private events;
constructor(initialValues?:T[]) {
// make for .. in / Object.keys behave like an array:
Object.defineProperty(this, "length", {
enumerable: false,
get: function() {
this.dependencyState.notifyObserved();
return this._values.length;
},
set: function(newLength) {
var currentLength = this._values.length;
if (this._supressLengthNotification === true || newLength != currentLength) // distinguish between internal and external updates
return;
// grow
if (newLength > currentLength)
this.spliceWithArray(currentLength, 0, new Array<T>(newLength - currentLength));
// shrink
else if (newLength < currentLength)
this.splice(newLength -1, currentLength - newLength);
this.notifyObserved();
}
});
Object.defineProperty(this, "dependencyState", { enumerable: false, value: new DNode() });
Object.defineProperty(this, "_values", { enumerable: false, value: [] });
Object.defineProperty(this, "events", { enumerable: false, value: new events.EventEmitter() });
if (initialValues && initialValues.length)
this.spliceWithArray(0, 0, initialValues);
else
this.createNewStubEntry(0);
}
// and adds / removes the necessary numeric properties to this object
// does not alter this._values itself
private updateLength(oldLength:number, delta:number) {
if (delta < 0) {
for(var i = oldLength - 1 - delta; i < oldLength; i++)
delete this[i];
}
else if (delta > 0) {
for (var i = 0; i < delta; i++)
this.createNewEntry(oldLength + i);
}
else
return;
this.createNewStubEntry(oldLength + delta);
}
private createNewEntry(index: number) {
Object.defineProperty(this, "" + index, {
enumerable: true,
configurable: true,
set: (value) => {
if (this._values[index] !== value) {
this._values[index] = value;
this.notifyChildUpdate(index);
}
},
get: () => {
this.dependencyState.notifyObserved();
return this._values[index];
}
})
}
private createNewStubEntry(index: number) {
Object.defineProperty(this, "" + index, {
enumerable: false,
configurable: true,
set: (value) => this.push(value),
get: () => undefined
});
}
spliceWithArray(index:number, deleteCount?:number, newItems?:T[]):T[] {
var length = this._values.length;
// yay, splice can deal with strange indexes
if (index > length)
index = length;
else if (index < 0)
index = Math.max(0, length - index);
// too few arguments?
if (index === undefined)
return;
if (deleteCount === undefined)
deleteCount = length - index;
if (newItems === undefined)
newItems = [];
var lengthDelta = newItems.length - deleteCount;
var res:T[] = Array.prototype.splice.apply(this._values, [<any>index, deleteCount].concat(newItems));
this.updateLength(length, lengthDelta); // create or remove new entries
this.notifySplice(index, res, newItems);
return res;
}
private notifyChildUpdate(index:number) {
this.notifyChanged();
// TODO: update Array.observe listeners
}
private notifySplice(index:number, deleted:T[], added:T[]) {
this.notifyChanged();
// TODO: update Array.observe listeners
}
private notifyChanged() {
this.dependencyState.markStale();
this.dependencyState.markReady(true);
this.events.emit('change');
}
// TODO: eS7 event params
observe(listener:()=>void, fireImmediately=false):Lambda {
if (fireImmediately)
listener();
this.events.addListener('change', listener);
return () => {
this.events.removeListener('change', listener);
};
}
clear(): T[] {
return this.splice(0);
}
replace(newItems:T[]) {
return this.spliceWithArray(0, this._values.length, newItems);
}
values(): T[] {
return this.slice(0);
}
/*
ES7 goodies
*/
// TODO: observe(callaback) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/observe
// https://github.com/arv/ecmascript-object-observe
// TODO: unobserve(callback)
/*
functions that do alter the internal structure of the array, from lib.es6.d.ts
*/
splice(index:number, deleteCount?:number, ...newItems:T[]):T[] {
return this.spliceWithArray(index, deleteCount, newItems);
}
push(...items: T[]): number {
// don't use the property internally
this.spliceWithArray(this._values.length, 0, items);
return this._values.length;
}
pop(): T {
return this.splice(this._values.length, 1)[0];
}
shift(): T {
return this.splice(0, 1)[0]
}
unshift(...items: T[]): number {
this.spliceWithArray(0, 0, items);
return this._values.length;
}
/*
functions that do not alter the array, from lib.es6.d.ts
*/
toString():string { return this.wrapReadFunction<string>("toString", arguments); }
toLocaleString():string { return this.wrapReadFunction<string>("toLocaleString", arguments); }
concat<U extends T[]>(...items: U[]): T[] { return this.wrapReadFunction<T[]>("concat", arguments); }
join(separator?: string): string { return this.wrapReadFunction<string>("join", arguments); }
reverse():T[] { return this.wrapReadFunction<T[]>("reverse", arguments); }
slice(start?: number, end?: number): T[] { return this.wrapReadFunction<T[]>("slice", arguments); }
sort(compareFn?: (a: T, b: T) => number): T[] { return this.wrapReadFunction<T[]>("sort", arguments); }
indexOf(searchElement: T, fromIndex?: number): number { return this.wrapReadFunction<number>("indexOf", arguments); }
lastIndexOf(searchElement: T, fromIndex?: number): number { return this.wrapReadFunction<number>("lastIndexOf", arguments); }
every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean { return this.wrapReadFunction<boolean>("every", arguments); }
some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean { return this.wrapReadFunction<boolean>("some", arguments); }
forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void { return this.wrapReadFunction<void>("forEach", arguments); }
map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[] { return this.wrapReadFunction<U[]>("map", arguments); }
filter(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): T[] { return this.wrapReadFunction<T[]>("filter", arguments); }
reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U { return this.wrapReadFunction<U>("reduce", arguments); }
reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U { return this.wrapReadFunction<U>("reduceRight", arguments); }
private wrapReadFunction<U>(funcName:string, args:IArguments):U {
var baseFunc = Array.prototype[funcName];
// generate a new function that wraps arround the Array.prototype, and replace our own definition
ObservableArray.prototype[funcName] = function() {
this.dependencyState.notifyObserved();
return baseFunc.apply(this._values, arguments);
}
return this[funcName].apply(this, args);
}
}
//TODO: trick type system
//ObservableArray.prototype = []; // makes, observableArray instanceof Array === true, but not typeof or Array.isArray..
//y.__proto__ = Array.prototype
//x.prototype.toString = function(){ return "[object Array]" }
//even monky patch Array.isArray?
enum DNodeState {

@@ -201,3 +445,2 @@ STALE, // One or more depencies have changed, current value is stale

addObserver(node:DNode) {
// optimization: replace with length, see: https://jsperf.com/array-push-vs-unshift-vs-direct-assignment/2
this.observers[this.observers.length] = node;

@@ -261,2 +504,3 @@ }

// optimization: replace this check with an 'unstableDependenciesCounter'.
areAllDependenciesAreStable() {

@@ -330,9 +574,13 @@ var obs = this.observing, l = obs.length;

this.observing = DNode.trackingStack.pop();
if (this.hasObservingChanged()) {
// optimization, smart compare two lists before removing / deleting / finding cycles
for(var l = this.prevObserving.length, i=0; i<l; i++)
this.prevObserving[i].removeObserver(this);
for(var l = this.observing.length, i=0; i<l; i++)
this.observing[i].addObserver(this);
this.findCycle(this);
var changes = quickDiff(this.observing, this.prevObserving);
var added = changes[0];
var removed = changes[1];
for(var i = 0, l = removed.length; i < l; i++)
removed[i].removeObserver(this);
for(var i = 0, l = added.length; i < l; i++) {
added[i].addObserver(this);
added[i].findCycle(this);
}

@@ -345,4 +593,10 @@ }

var ts = DNode.trackingStack, l = ts.length;
if (l)
ts[l-1][ts[l-1].length] = this;
if (l) {
var cs = ts[l -1], csl = cs.length;
// this last item added check is an optimization especially for array loops,
// because an array.length read with subsequent reads from the array
// might trigger many observed events, while just checking the last added item is cheap
if (cs[csl -1] !== this && cs[csl -2] !== this)
cs[csl] = this;
}
}

@@ -427,1 +681,75 @@

}
/**
* Given a new and an old list, tries to determine which items are added or removed
* in linear time. The algorithm is heuristic and does not give the optimal results in all cases.
* (For example, [a,b] -> [b, a] yiels [[b,a],[a,b]])
* its basic assumptions is that the difference between base and current are a few splices.
*
* returns a tuple<addedItems, removedItems>
* @type {T[]}
*/
function quickDiff<T>(current:T[], base:T[]):[T[],T[]] {
if (!base.length)
return [current, []];
if (!current.length)
return [[], base];
var added:T[] = [];
var removed:T[] = [];
var currentIndex = 0,
currentSearch = 0,
currentLength = current.length,
currentExhausted = false,
baseIndex = 0,
baseSearch = 0,
baseLength = base.length,
isSearching = false,
baseExhausted = false;
while (!baseExhausted && !currentExhausted) {
if (!isSearching) {
// within rang and still the same
if (currentIndex < currentLength && baseIndex < baseLength && current[currentIndex] === base[baseIndex]) {
currentIndex++;
baseIndex++;
// early exit; ends where equal
if (currentIndex === currentLength && baseIndex === baseLength)
return [added, removed];
continue;
}
currentSearch = currentIndex;
baseSearch = baseIndex;
isSearching = true;
}
baseSearch += 1;
currentSearch += 1;
if (baseSearch >= baseLength)
baseExhausted = true;
if (currentSearch >= currentLength)
currentExhausted = true;
if (!currentExhausted && current[currentSearch] === base[baseIndex]) {
// items where added
added.push.apply(added, current.slice(currentIndex, currentSearch));
currentIndex = currentSearch +1;
baseIndex ++;
isSearching = false;
}
else if (!baseExhausted && base[baseSearch] === current[currentIndex]) {
// items where removed
removed.push.apply(removed, base.slice(baseIndex, baseSearch));
baseIndex = baseSearch +1;
currentIndex ++;
isSearching = false;
}
}
added.push.apply(added, current.slice(currentIndex));
removed.push.apply(removed, base.slice(baseIndex));
return [added, removed];
}
(<any>mobservableStatic).quickDiff = quickDiff; // For testing purposes only
export = mobservableStatic;
{
"name": "mobservable",
"version": "0.0.6",
"version": "0.1.0",
"description": "Changes are coming! Small library for creating observable properties en functions",
"main": "mobservable.js",
"main": "dist/mobservable.js",
"scripts": {
"test": "node_modules/.bin/nodeunit test/",
"prepublish": "node_modules/typescript-require/node_modules/typescript/bin/tsc -m commonjs -t ES5 mobservable.ts"
"test": "grunt test",
"prepublish": "grunt build"
},

@@ -21,6 +21,8 @@ "repository": {

"devDependencies": {
"nodeunit": "^0.9.1",
"grunt": "^0.4.5",
"grunt-contrib-nodeunit": "^0.4.1",
"grunt-ts": "^4.0.1",
"nscript": "^0.1.5",
"typescript-require": "^0.2.8"
"typescript": "^1.4.1"
}
}

@@ -5,39 +5,73 @@ # MOBservable

MOBservable is simple observable implementation, based on the ideas of observables in bigger frameworks like `knockout`, `ember` etc, but this one does not have 'strings attached'. Furthermore it should fit well in any typescript project.
MOBservable is light-weight stand alone observable implementation, based on the ideas of observables in bigger frameworks like `knockout`, `ember`, but this time without 'strings attached'. Furthermore it should fit well in any typescript project.
# Properties
# Observable values
The `mobservable.property` method takes a value or function and creates an observable value from it.
This way properties that listen that observe each other can be created. A quick example:
The `mobservable.value(valueToObserve)` method (or just its shorthand: `mobservable(valueToObserve)`) takes a value or function and creates an observable value from it. A quick example:
```typescript
import mobservable = require('mobservable');
var property = mobservable.property;
var vat = property(0.20);
var vat = mobservable(0.20);
var order = {};
order.price = property(10),
order.priceWithVat = property(() => order.price() * (1+vat()));
order.price = mobservable(10),
order.priceWithVat = mobservable(() => order.price() * (1 + vat()));
order.priceWithVat.subscribe((price) => console.log("New price: " + price));
order.priceWithVat.observe((price) => console.log("New price: " + price));
order.price(20);
// Prints: New price: 24
order.price(10);
// Prints: New price: 10
vat(0.10);
// Prints: New price: 22
```
### mobservable.property(value, scope?)
## mobservable.value(value, scope?):IObservableValue
Constructs a new `Property`, value can either be a string, number, boolean or function that takes no arguments and returns a value. In the body of the function, references to other properties will be tracked, and on change, the function will be re-evaluated. The returned value is an `IProperty` function/object.
Constructs a new observable value. The value can be everything that is not a function, or a function that takes no arguments and returns a value. In the body of the function, references to other properties will be tracked, and on change, the function will be re-evaluated. The returned value is an `IProperty` function/object. Passing an array or object into the `value` method will only observe the reference, not the contents of the objects itself. To observe the contents of an array, use `mobservable.array`, to observe the contents of an object, just make sure its (relevant) properties are observable values themselves.
Optionally accepts a scope parameter, which will be returned by the setter for chaining, and which will used as scope for calculated properties.
The method optionally accepts a scope parameter, which will be returned by the setter for chaining, and which will be used as scope for calculated properties, for example:
### mobservable.defineProperty(object, name, value)
```javascript
var value = mobservable.value;
function OrderLine(price, amount) {
this.price = value(price);
this.amount = value(amount);
this.total = value(function() {
return this.price() * this.amount();
}, this)
}
```
## mobservable.array(initialValues?):ObservableArray
**Note: ES5 environments only**
Constructs an array like, observable structure. An observable array is a thin abstraction over native arrays that adds observable properties. The only noticable difference between built-in arrays is that these arrays cannot be sparse, that is, values assigned to an index larger than `length` are not oberved (nor any other property that is assigned to a non-numeric index). In practice, this should harldy be an issue. Example:
```javascript
var numbers = mobservable.array([1,2,3]);
var sum = mobservable.value(function() {
return numbers.reduce(function(a, b) { return a + b }, 0);
});
sum.observe(function(s) { console.log(s); });
numbers[3] = 4;
// prints 10
numbers.push(5,6);
// prints 21
numbers.unshift(10)
// prints 31
```
## mobservable.defineProperty(object, name, value)
**Note: ES5 environments only**
Defines a property using ES5 getters and setters. This is useful in constructor functions, and allows for direct assignment / reading from observables:
```javascript
var vat = property(0.2);
var vat = mobservable.value(0.2);
var Order = function() {

@@ -71,15 +105,15 @@ mobservable.defineProperty(this, 'price', 20);

### mobservable.guard(func, onInvalidate)
## mobservable.watch(func, onInvalidate)
`guard` invokes `func` and returns a tuple consisting of the return value of `func` and an unsubscriber. `guard` will track which observables `func` was observing, but it will *not* recalculate `func` if necessary, instead, it will fire the `onInvalidate` callback to notify that the output of `func` can no longer be trusted.
`watch` invokes `func` and returns a tuple consisting of the return value of `func` and an unsubscriber. `watch` will track which observables `func` was observing, but it will *not* recalculate `func` if necessary, instead, it will fire the `onInvalidate` callback to notify that the output of `func` can no longer be trusted.
The `onInvalidate` function will be called only once, after that, the guard has finished. To abort a guard, use the returned unsubscriber.
The `onInvalidate` function will be called only once, after that, the watch has finished. To abort a watch, use the returned unsubscriber.
Guard is useful in functions where you want to have `func` observable, but func is actually invoked as side effect or part of a bigger change flow or where unnecessary recalculations of `func` or either pointless or expensive.
`Watch` is useful in functions where you want to have a function that responds to change, but where the function is actually invoked as side effect or part of a bigger change flow or where unnecessary recalculations of `func` or either pointless or expensive, for example in React component render methods
### mobservable.batch(workerFunction)
## mobservable.batch(workerFunction)
Batch postpones the updates of computed properties until the (synchronous) `workerFunction` has completed. This is useful if you want to apply a bunch of different updates throughout your model before needing the updated computed values, for example while refreshing a value from the database.
### mobservable.onReady(listener) / mobservable.onceReady(listener)
## mobservable.onReady(listener) / mobservable.onceReady(listener)

@@ -90,14 +124,42 @@ The listener is invoked each time the complete model has become stable. The listener is always invoked asynchronously, so that even without `batch` the listener is only invoked after a bunch of changes have been applied

### IProperty()
## `IObservableValue` objects
Returns the current value of the property
### IObservableValue()
### IProperty(value)
If an IObservableValue object is called without arguments, the current value of the observer is returned
Sets a new value to the property. Returns the scope with which this property was created for chaining.
### IObservableValue(newValue)
### IProperty.subscribe(listener,fireImmediately=false)
If an IObservable object is called with arguments, the current value is updated. All current observers will be updated as well.
### IObservableValue.observe(listener,fireImmediately=false)
Registers a new listener to change events. Listener should be a function, its first argument will be the new value, and second argument the old value.
Returns a function that upon invocation unsubscribes the listener from the property.
## `ObservableArray`
An `ObservableArray` is an array-like structure with all the typical behavior of arrays, so you can freely assign new values to (non-sparse) indexes, alter the length, call array functions like `map`, `filter`, `shift` etc. etc. All the ES5 features are in there. Additionally available methods:
### ObservableArray.clear()
Removes all elements from the array and returns the removed elements. Shorthand for `ObservableArray.splice(0)`
### ObservableArray.replace(newItemsArray)
Replaces all the items in the array with `newItemsArray`, and returns the old items.
### ObservableArray.spliceWithArray(index, deleteCount, newItemsArray)
Similar to `Array.splice`, but instead of accepting a variable amount of arguments, the third argument should be an array containing the new arguments.
### ObservableArray.observe(callback)
Register a callback that will be triggered every time the array is altered. A method to unregister the callback is returned.
In the near feature this will adhere to the ES7 specs for Array.observe so this class can be used as ES7 array shim.
### ObservableArray.values()
Returns all the values of this ObservableArray as native, non-observable, javascript array. The returned array is a shallow copy.

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc