Traps

From Vexi

Jump to: navigation, search

Traps are a javascript extension and a key component of Vexi, they are a way of intercepting execution. They are commonly used for creating event listeners and internal manipulation of properties for widgets.

Contents

Overview

Traps are placed on properties on objects and come in two types.

  • Read traps
Read traps are executed when a property is read
  • Write traps
Write traps are executed when a property is written to

Traps are placed using the special '++=' operator.

Read Traps

A read trap is placed by using the ++= operator with a function that takes no arguments. The cascade keyword in read traps gets the value from the object, or from the previously added traps.

var obj = {a:1};
vexi.log.info("a: " + obj.a);

obj.a ++= function(){ return cascade * 2; }
vexi.log.info("a: " + obj.a);

obj.a ++= function(){ return cascade * 3; }
vexi.log.info("a: " + obj.a);

This will output:

a: 1
a: 2
a: 6

Write Traps

A write trap is placed by using the ++= operator with a function that takes one argument. The cascade keyword in write traps puts the value to the object, or triggers any previously added traps.

var obj = {b:1};
vexi.log.info("b: " + obj.b);

obj.b ++= function(v){ cascade = v * 2; }
vexi.log.info("b: " + obj.b);

obj.b = 1;
vexi.log.info("b: " + obj.b);

This will output:

b: 1
b: 1
b: 2

Uses

Here are some of the more common uses of traps.

Event listeners

Write traps that don't modify a value are the way to do event listening in Vexi.

awidget.color ++= function(v) { /*do something*/; cascade = v; }

Compare this to how the same is achieved in other languages.

Get/Set

Traps obviate the need for get and set methods (in all cases?). In some languages it is considered bad practise to read properties on objects directly, even if no action is required. The reason being that at some later date you may wish to change the behaviour so something happens, but you do not want to/are not able to change every location where the property is accessed. Hence we have get and set methods.

For example later we decide that the color red is not an acceptable value for our property.

thisbox.color ++= function(v) {
   if (v=="red") throw "red not allowed!"
}

All client code is unaffected (lets assume it handles exceptions).

Cloning

When combined with vexi.clone() traps can be used to extend objects directly. Traditionally inheritance will allow you extends a class of objects (prototypes and java classes achieve this), but in some it is more elegant than inheritance to use cloning.

It is necessary to understand what vexi.clone() does. It creates a wrapper around an object which you can place traps on. The original object is not modified at all when these traps are placed.

What this means is that we can modify the behaviour of the clone, but still reuse what we want from the original 'clonee'. If the clonee is modified the clone will also reflect these modifications (except where the behaviour is overridden with traps).

For a toy example

// prices of different items
var catalog = { sword: 50, shield: 15, bow:20 };

So somewhere later the original object is passed into a constructor

var newWizardstore = function(catalog) {
   var ourcatalog = vexi.clone(catalog);
   ourcatalog.wand ++= new function() { return 100; }
   var r = {};
   r.price = function(item){ return ourcatalog[item]; }
}

var wizardsRUs = newWizardstore();
wizardsRUs.price("sword");   // 50
wizardsRUs.price("wand");    // 100

// supplier creates a global sale on swords
catalog.sword = 45;
wizardsRUs.price("sword");   // 45
Personal tools
wiki information