Javascript ‘this’ scoping

The keyword ‘this’ refers to the context in which a given function is running.

Default context

If a function belongs to an object, it is generally called using the dot notation:

var obj = {
  func: function() {
    alert(this === obj); // alerts 'true'
  }
};

obj.func(); // run 'func' in the context of 'obj'

Therefore, by calling obj.func(), we are saying: “Run ‘func’ in the context of ‘obj’, such that the ‘this’ keyword in ‘func’ refers to ‘obj'”

This kind of behavior allows us to do things like this:

var obj = {
  name: 'Joe',
  func: function() {
    alert(this.name); // 'this' is referring to obj, so obj.name gives us 'Joe'
  }
};
obj.func(); // func runs in the context of obj

So far so good, right?

Context coercion

In javascript, we have the power to tell any function to run in the context of absolutely any object we want…not just the one it belongs to, using the magic ‘apply’ and ‘call’ functions:

var obj = {
  name: 'Joe',
  func: function() {
    alert(this.name);
  }
};

var obj2 = {
  name: 'Mike'
};

var obj3 = {
  name: 'Bill'
};

obj.func.apply(obj2); // run 'func' in the context of 'obj2', alerts "Mike"
obj.func.call(obj3); // run 'func' in the context of 'obj3', alerts "Bill"
Both the ‘call’ and ‘apply’ functions give us the ability to specify context. The two are a bit different in that if you wanted to pass arguments to the called function, using ‘apply’ you would pass the arguments as an array while with ‘call’ you would pass individual arguments:
var obj = {
  name: 'Joe',
  func: function(age, weight) {
    alert(this.name+" with age of "+age+" and height of "+weight);
  }
};

var obj2 = {
  name: 'Mike'
};

var obj3 = {
  name: 'Bill'
};

obj.func.apply(obj2, [23, 155]); // run 'func' in the context of 'obj2', alerts "Mike"
obj.func.call(obj3, 43, 176); // run 'func' in the context of 'obj3', alerts "Bill"

So, to review:

  1. Functions that belong to objects can be called using dot notation and run in the context of those objects
  2. Any function can be coerced to run in the context of any other object using the ‘call’ and ‘apply’ methods
  3. Just a reminder, the context of a function is whatever the ‘this’ keyword refers to

Anonymous functions

An anonymous function is one that does not belong to any object. In other words, you can’t call it using dot notation (e.g. someObj.yourFunc() ). Anonymous functions, unless coerced via the ‘call’ or ‘apply’ methods, run in the context of the global scope (usually the ‘window’ object).

var obj = {
  func: function() {
    var anonFunc = function() {
      alert(this === obj); // alerts 'false'
      alert(this === window); // alerts 'true', running in the context of the global object
    };
    anonFunc(); // run anonFunc in...well...no context specified...
  }
};

obj.func(); // run 'func' in the context of 'obj'

So how can we refer to ‘obj’ from the anonFunc? One way is to change the code like so:

var obj = {
  func: function() {
    var anonFunc = function() {
      alert(this === obj); // alerts 'false'
      alert(this === window); // alerts 'true', running in the context of the global object
    };
    anonFunc.call(this); // run anonFunc in the context of 'this', where 'this' is 'obj'
  }
};

obj.func(); // run 'func' in the context of 'obj'

However, a much more common way of fixing this issue is by assigning a variable ‘self’ to the target ‘this’, then just using the ‘self’ variable everywhere.

var obj = {
  func: function() {
    var self = this;
    var anonFunc = function() {
      alert(self === obj); // alerts 'true', since 'self' is set to the 'this' that is the 'obj'
      alert(self === window); // alerts 'false'
    };
    anonFunc(); // run anonFunc in the context of 'this', where 'this' is 'obj'
  }
};

obj.func(); // run 'func' in the context of 'obj'

Here is a more practical example:

var obj = {
  name: "John Doe",
  id: "82384349",
  func: function() {
    var self = this;
    $.get('ajax/getAge', {id: self.id}).done(function(data) {
      alert(self.name+" is "+data+" years old" );
    });
  }
};

obj.func(); // run 'func' in the context of 'obj'

Notice how I declared ‘self’ at the top of the ‘func’ function and then used it everywhere. This has the advantage of making our code less error-prone. Also, if you run your javascript through a minimizer, the ‘self’ variable will be compressed and you will end up with a slightly smaller file then you would if you used ‘this’ everywhere (which does not compress, since it is a keyword in javascript).

Happy Hacking!

Generating a parser

An important feature of Anzo on the Web is the ability to specify custom equations, similar to the ones you see in Excel, to do various analytics.  The language is similar to what you see in Excel, except the values are specified by RDF paths, rather than regions.  The editor has the formula editing region at the top, a place to select value fields on the bottom-left and a function selector on the bottom-right:

formulaEditor

For fast validation of formulas, I needed to build a parser for the language that would run in the browser (in javascript).  To do so, I used the awesome LALR(1) parser and lexical analyzer generator for JavaScript, which is itself written in javascript.

The installed version can be found here: JS/CC

To create a parser, you need to tell it about the language you want to parse.  You do this using aBackus-Naur-Form-based meta language , and it generates the javascript parser for you!  A good way to get started is to study the Calculator example, which can be loaded by clicking on the dropdown at the top, selecting it and clicking the ‘load’ button.

Lazy Loading in Angular

AngularJS does not yet have a way to load objects asynchronously, but you can use RequireJS to do it yourself. First, you need to wrap all controllers, factories, etc with AMD modules. They should look something like this:
define([
    // your dependencies
], function () {
    return ["myController", ["$scope", function($scope) {
       $scope.data = { label: "my data" };
    }]];
});
When initializing your application, do something like this:
var compileProvider,
        controllerProvider,
        filterProvider,
        provide;

    // create your application module and store references to the compileProvider, controllerProvider, filterProvider, and provider
    var module = angular.module('myApp', [], function ($compileProvider, $controllerProvider, $filterProvider, $provide) {
        compileProvider = $compileProvider;
        controllerProvider = $controllerProvider;
        filterProvider = $filterProvider;
        provide = $provide;
    });

     var lazyAngular = {
            registerFactoryProvider: function(factory) {
                provide.factory.apply(null, factory);
            },
            registerFilterProvider: function(filter) {
                filterProvider.register.apply(null, filter);
            },
            registerDirective  : function (directive) {
                compileProvider.directive.apply(null, directive);
            },
            registerController : function (controller) {
                controllerProvider.register.apply(null, controller);
            }
        };

    // Now, register a factory you can use to register lazily loaded controllers, directives, filters and factories
    module.factory("lazyAngular", function () {
        return lazyAngular ;
    });
    // Note that you can also reference the lazyAngular object directly, without dependency injection if you wish.
You can now load things asynchronously, for example:
// Make sure that you have lazyAngular in the current context (load it with dependency injection).
// Note that I have also seen developers put the registration methods in a global namespace, to easily reference the registration capability from everywhere without worrying about dependency injection.
// How you reference the lazyAngular object is up to you.
require(["myController"], function(myCtrl) {
    lazyAngular.registerController (myCtrl); // register the lazily loaded controller

   // you can now use this lazy loaded controller
});

Layout System in Anzo on the Web

I have been adding a great deal of layout capability to Anzo on the Web. Here are some screenshots with some samples of the kinds of things we can now do with this new system. The really cool thing is that the application you in these screenshots can be thrown together by non-programmers to visualize all kinds of data.

Generate a Form from any JSON for quick and easy editing

I just wrote a JSON form generator that generates a form given any JSON string. With this utility you can:
  • Edit values in any object
  • Add new attributes to objects and arrays
  • Add/remove arrays and objects
  • Specify a custom template to use whenever a new object is created to increase productivity
The application can then give you the results of the form back in JSON.

Example:

Given this:
  
{
   name:"Rouben",
   company:"Cambridge Semantics",
   profile:"http://www.cambridgesemantics.com/people/about/rmeschian",
   "works with":[
      {
         name:"Sean Martin",
         profile:"http://www.cambridgesemantics.com/people/about/sean"
      },
      {
         name:"Simon Martin",
         profile:"http://www.cambridgesemantics.com/people/about/simon"
      },
      {
         name:"Ben Szekely",
         profile:"http://www.cambridgesemantics.com/people/about/ben"
      }
   ]
}
The generated form looks like this: I’ll make it prettier if I find the time. Until then I hope you find it useful.
This is a utility I wrote that comes in handy every now and then, so I thought I would share it with you. It allows you to replaces all the end of line characters in the given text with whatever you define. I often use this to format text for the web by replacing EOLs with break elements. For example, suppose we have this string:
"foo
bar
zoo"
We can use this utility to replace the EOLs with “, ” to get:
"foo, bar, zoo"
Replace EOL characters with:

Openanzo’s javascript RDF library – resource bean

Openanzo has a powerful RDF javascript library in the org.openanzo.js project. In previous posts I talked about some of the low level API available to create, store and find RDF statements. In this tutorial I’ll talk about a simple object called anzo.rdf.GraphResource which takes a graph and resource and creates a bean with familiar getters and setters to allow you to easily modify the properties of that resource.
  
 dojo.require("anzo.rdf.NamedGraph");
 dojo.require("anzo.rdf.GraphResource");

 // register namespaces to make this example simpler
 anzo.rdf.registerNamespace("ex", "http://www.example.org/");
 anzo.rdf.registerNamespace("foaf", "http://xmlns.com/foaf/0.1/");

 // 1. build a sample graph with some data in it
 var graph = new anzo.rdf.NamedGraph('http://graph_1');
 graph.add('ex:me', "foaf:firstName", "Rouben");
 graph.add('ex:me', "foaf:surname", "Meschian");
 graph.add('ex:me', "foaf:knows", "ex:sean");

 // 2. create a bean and specify which properties you want to create methods for
 var bean = new anzo.rdf.GraphResource('ex:me', graph, [ "foaf:firstName", "foaf:surname" ]);
 bean.getFirstName(); // returns a single literal "Rouben"
 bean.setSurname("Smith"); // sets my surname to "Smith"

 // 3. add additional properties whenever you want
 bean.createPropertyMethods(["foaf:knows"]);
 bean.addKnows("ex:ben");
 bean.getKnows(); // returns an array with Sean and Ben's URIs

Openanzo’s javascript RDF library – client quad store

Openanzo has a powerful RDF javascript library in the org.openanzo.js project. The library has a highly optimized quad store. A quadstore stores RDF statements that have namedGraphUri values (in addition to the standard subject, predicate and object values).

anzo.rdf.QuadStore

  
   dojo.require("anzo.rdf.QuadStore"); // reference the object

   // register namespace
   anzo.rdf.registerNamespace("ex", "http://www.example.org/"); 

   var store = new anzo.rdf.QuadStore();
   store.add("ex:subj", "ex:pred", "dog", "ex:graph1");
   store.isEmpty(); // returns false
   store.size(); // returns 1
   store.find("ex:subj"); // returns an array with a single statement in it
We can use anzo.rdf.NamedGraphs as proxies to the quadstore. Once a NamedGraph has been created with the store, all statements are stored in the underlying quadstore. In this way the NamedGraph becomes a convenient way to add triples to a graph which then get passed to the quadstore as quads (with the name of the graph being the fourth value in the statement).
  
  var store = new anzo.rdf.QuadStore();
  
  var graph1 = new anzo.rdf.NamedGraph("ex:graph1", store);
  graph1.add("http://www.example.org/subj1", "ex:pred1", "dog");
   
  var graph2 = new anzo.rdf.NamedGraph("ex:graph2", store);
  graph2.add("ex:subj2", "ex:pred2", "cat");

  graph1.contains(null, null, "dog");  // true
  graph2.contains(null, null, "cat");  // true
  store.contains(null, null, "dog");    // true
  store.contains(null, null, "cat");    // true
Performance Numbers
In this test I loaded up the quadstore with 100,000 quads. I then ran a number of timed calls to the find method with a pattern from the first of the 100,000 statements that were added, a pattern from the middle of that set and a pattern from the very end. Then, I added an additional 100 quads and timed that. I then removed those 100 and timed that. Here are my results:
  
----------------------------------------------
added: 100000 statements to the store
----------------------------------------------
find(s, p, o, c)
Elapsed time calling find (s, p, o, c) on first added statement pattern: 0 milliseconds. Num stmts found: 0
Elapsed time calling find (s, p, o, c) on middle added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 0
Elapsed time calling find (s, p, o, c) on last added statement pattern: 0 milliseconds. Num stmts found: 0
----------------------------------------------
find(?, p, o, c)
Elapsed time calling find (?, p, o, c) on first added statement pattern: 0 milliseconds. Num stmts found: 1
Elapsed time calling find (?, p, o, c) on middle added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 1
Elapsed time calling find (?, p, o, c) on last added statement pattern: 0 milliseconds. Num stmts found: 1
----------------------------------------------
find(s, ?, o, c)
Elapsed time calling find (s, ?, o, c) on first added statement pattern: 0 milliseconds. Num stmts found: 1
Elapsed time calling find (s, ?, o, c) on middle added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 1
Elapsed time calling find (s, ?, o, c) on last added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 1
----------------------------------------------
find(s, p, ?, c)
Elapsed time calling find (s, p, ?, c) on first added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 100
Elapsed time calling find (s, p, ?, c) on middle added statement pattern: 0.6666666666666666 milliseconds. Num stmts found: 100
Elapsed time calling find (s, p, ?, c) on last added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 100
----------------------------------------------
find(s, p, o, ?)
Elapsed time calling find (s, p, o, ?) on first added statement pattern: 0 milliseconds. Num stmts found: 1
Elapsed time calling find (s, p, o, ?) on middle added statement pattern: 0 milliseconds. Num stmts found: 1
Elapsed time calling find (s, p, o, ?) on last added statement pattern: 0 milliseconds. Num stmts found: 1
----------------------------------------------
find(?, ?, o, c)
Elapsed time calling find (?, ?, o, c) on first added statement pattern: 0 milliseconds. Num stmts found: 1
Elapsed time calling find (?, ?, o, c) on middle added statement pattern: 0 milliseconds. Num stmts found: 1
Elapsed time calling find (?, ?, o, c) on last added statement pattern: 0 milliseconds. Num stmts found: 1
----------------------------------------------
find(s, ?, ?, c)
Elapsed time calling find (s, ?, ?, c) on first added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 100
Elapsed time calling find (s, ?, ?, c) on middle added statement pattern: 0.6666666666666666 milliseconds. Num stmts found: 100
Elapsed time calling find (s, ?, ?, c) on last added statement pattern: 0.6666666666666666 milliseconds. Num stmts found: 100
----------------------------------------------
find(s, p, ?, ?)
Elapsed time calling find (s, p, ?, ?) on first added statement pattern: 0 milliseconds. Num stmts found: 100
Elapsed time calling find (s, p, ?, ?) on middle added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 100
Elapsed time calling find (s, p, ?, ?) on last added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 100
----------------------------------------------
find(?, p, ?, c)
Elapsed time calling find (?, p, ?, c) on first added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 100
Elapsed time calling find (?, p, ?, c) on middle added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 100
Elapsed time calling find (?, p, ?, c) on last added statement pattern: 0.6666666666666666 milliseconds. Num stmts found: 100
----------------------------------------------
find(s, ?, o, ?)
Elapsed time calling find (s, ?, o, ?) on first added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 1
Elapsed time calling find (s, ?, o, ?) on middle added statement pattern: 0 milliseconds. Num stmts found: 1
Elapsed time calling find (s, ?, o, ?) on last added statement pattern: 0 milliseconds. Num stmts found: 1
----------------------------------------------
find(?, p, o, ?)
Elapsed time calling find (?, p, o, ?) on first added statement pattern: 0 milliseconds. Num stmts found: 1
Elapsed time calling find (?, p, o, ?) on middle added statement pattern: 0 milliseconds. Num stmts found: 1
Elapsed time calling find (?, p, o, ?) on last added statement pattern: 0 milliseconds. Num stmts found: 1
----------------------------------------------
find(?, ?, ?, c)
Elapsed time calling find (?, ?, ?, c) on first added statement pattern: 7 milliseconds. Num stmts found: 1000
Elapsed time calling find (?, ?, ?, c) on middle added statement pattern: 7.333333333333333 milliseconds. Num stmts found: 1000
Elapsed time calling find (?, ?, ?, c) on last added statement pattern: 8 milliseconds. Num stmts found: 1000
----------------------------------------------
find(?, ?, o, ?)
Elapsed time calling find (?, ?, o, ?) on first added statement pattern: 0 milliseconds. Num stmts found: 1
Elapsed time calling find (?, ?, o, ?) on middle added statement pattern: 0 milliseconds. Num stmts found: 1
Elapsed time calling find (?, ?, o, ?) on last added statement pattern: 0 milliseconds. Num stmts found: 1
----------------------------------------------
find(?, p, ?, ?)
Elapsed time calling find (?, p, ?, ?) on first added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 100
Elapsed time calling find (?, p, ?, ?) on middle added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 100
Elapsed time calling find (?, p, ?, ?) on last added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 100
----------------------------------------------
find(s, ?, ?, ?)
Elapsed time calling find (s, ?, ?, ?) on first added statement pattern: 0 milliseconds. Num stmts found: 100
Elapsed time calling find (s, ?, ?, ?) on middle added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 100
Elapsed time calling find (s, ?, ?, ?) on last added statement pattern: 0.3333333333333333 milliseconds. Num stmts found: 100
----------------------------------------------
find(?, ?, ?, ?)
Elapsed time calling find (?, ?, ?, ?): 350 milliseconds. Num stmts found: 100000
----------------------------------------------
adding num stmts: 100
Elapsed time adding statements: 11.333333333333334 milliseconds.
----------------------------------------------
removing num stmts: 100
Elapsed time removing statements: 0 milliseconds.

Openanzo’s javascript RDF library – parsers and serializers

Openanzo has a powerful RDF javascript library which has RDF parsing and serialization capabilities.

anzo.rdf.parser.TabulatorParser

An RDF/XML parser ported from Tabulator.
  
var graph = new anzo.rdf.NamedGraph(); // graph into which triples are placed
anzo.rdf.parser.TabulatorParser.parse(rdfXMLString, graph); // parse

anzo.rdf.parser.NTripleParser

An RDF N-Triples parser.
  
var graph = new anzo.rdf.NamedGraph(); // the graph into which the parsed data is placed
anzo.rdf.parser.NTripleParser.parse(nTripleString, graph); // run the parser on the given N-Triple string

anzo.rdf.serializer.NTripleSerializer

An RDF N-Triples serializer.
  
var graph = new anzo.rdf.NamedGraph(); // the graph we want to serialize
// we add a bunch of statements to graph via the add() method
var nTripleString = anzo.rdf.serializer.NTripleSerializer.serialize(graph); // serialize the graph to N-Triples

Openanzo’s javascript RDF library – the basics

What most people don’t know is that openanzo has a powerful RDF javascript library. The library can be used as is, but of course it’s designed to work seamlessly with the rest of the openanzo stack. The RDF library is located in the org.openanzo.js project in src/main/resources/docroot/anzo/rdf

Statements, Resources, Literals …

Every RDF library has to have these basics. Here is the inheritance hierarchy:
  • anzo.rdf.Value – base class for all rdf nodes
    • anzo.rdf.Resource – base class for all rdf resources
      • anzo.rdf.URI – equals, toString, serialize, getNamespace, getLocalName
      • anzo.rdf.BNode – equals, toString, serialize
    • anzo.rdf.Literal – equals, toString, serialize, getNativeValue

anzo.rdf.URI

A javascript object representing a URI.
  
   var uri = anzo.createURI("http://www.example.org/foo");
   uri.serialize(); // "<http://www.example.org/foo>"
   uri.getNamespace(); // "http://www.example.org/"
   uri.getLocalName(); // "foo"
We can use short prefixes if we register the namespace:
  
   anzo.rdf.registerNamespace("ex", "http://www.example.org/");
   var uri = anzo.createURI("ex:foo");

anzo.rdf.BNode

Blank nodes are supported by all parts of the library.
  
   var bnode = anzo.createBNode("324453142134353214");
   bnode.toString(); // "324453142134353214"
   bnode.serialize(); //  "_:324453142134353214"

anzo.rdf.Literal

An anzo.rdf.Literal is the object that holds a value like a string, number, boolean, etc.
Creating a literal:
  
      var lit1= anzo.createLiteral("dog");
      lit1.toString(); // "dog"
      lit1.serialize(); // "dog"

      var lit2 = anzo.createLiteral("dog", "en"); // we can specify the language of the literal as the second argument
      lit2.toString(); // "dog"
      lit2.serialize(); // "dog"@en
Creating a typed literal:
  
      var lit3 = anzo.createTypedLiteral(5, "http://www.w3.org/2001/XMLSchema#int");
      lit3.toString(); // "5"
      lit3.serialize(); // "5"^^<http://www.w3.org/2001/XMLSchema#int>
      lit3.getNativeValue(); // returns a javascript number 5
      lit3.datatype; // returns http://www.w3.org/2001/XMLSchema#int as an anzo.rdf.URI
The getNativeValue method allows you to get a native javascript object from any literal. This makes rendering and editing rdf data with widgets from common libraries such as YUI, dojo and jquery very easy. Here is a table showing the mappings between the literal and the type of javascript value you can expect when calling getNativeValue:
XSD DatatypeJavascript Type
http://www.w3.org/2001/XMLSchema#dateTimeDate
http://www.w3.org/2001/XMLSchema#dateDate
http://www.w3.org/2001/XMLSchema#timeDate
http://www.w3.org/2001/XMLSchema#gYearMonthDate
http://www.w3.org/2001/XMLSchema#gYearDate
http://www.w3.org/2001/XMLSchema#gMonthDayDate
http://www.w3.org/2001/XMLSchema#gDayDate
http://www.w3.org/2001/XMLSchema#gMonthDate
http://www.w3.org/2001/XMLSchema#stringString
http://www.w3.org/2001/XMLSchema#booleanBoolean
http://www.w3.org/2001/XMLSchema#decimalNumber
http://www.w3.org/2001/XMLSchema#doubleNumber
http://www.w3.org/2001/XMLSchema#integerNumber
http://www.w3.org/2001/XMLSchema#longNumber
http://www.w3.org/2001/XMLSchema#shortNumber
http://www.w3.org/2001/XMLSchema#byteNumber
http://www.w3.org/2001/XMLSchema#nonPositiveIntegerNumber
http://www.w3.org/2001/XMLSchema#negativeIntegerNumber
http://www.w3.org/2001/XMLSchema#nonnegativeIntegerNumber
http://www.w3.org/2001/XMLSchema#positiveIntegerNumber
http://www.w3.org/2001/XMLSchema#unsignedLongNumber
http://www.w3.org/2001/XMLSchema#unsignedIntNumber
http://www.w3.org/2001/XMLSchema#unsignedShortNumber
http://www.w3.org/2001/XMLSchema#unsignedByteNumber
All the restString

Example of rendering an xsd:date literal in a dojo widget:
  
  var date = new Date(1216330344703); // Thu Jul 17 21:32:24.703 UTC 2008
  var dateLit = anzo.createTypedLiteral(date, "http://www.w3.org/2001/XMLSchema#date");
  dojoWidget.attr('value', dateLit.getNativeValue()); // this renders the literal value in the widget
The serialize method serializes the rdf node into a string that can then easily be deserialized by calling anzo.rdf.getValue(serializedString). This serialization can be used in constructing a SPARQL query:
  
var query = "select ?x where { ?x " + uri.serialize() + " "+lit.serialize() + " }";
// the query will look something like this: select ?x where { ?x <http://www.example.org/age> "5"^^<http://www.w3.org/2001/XMLSchema#int> }

anzo.rdf.Statement

A statement in this library can be used as either a triple or a quad.
  
   var triple = anzo.createStatement("ex:foo", "ex:bar", "dog");
   var quad = anzo.createStatement("ex:foo", "ex:bar", "dog", "ex:graph");

Graphs

anzo.rdf.NamedGraph

An in memory RDF graph. While intended to be used as a named graph, this graph could also be used as just a regular graph with no name.
  
    anzo.rdf.registerNamespace("ex", "http://www.example.org/");

    var graph = new anzo.rdf.NamedGraph("ex:mygraph"); // the graph name URI is optional
    graph.add("ex:foo", "ex:title", "dog");
    graph.find("ex:foo", null, "dog"); // returns an array with a single statement in it
    graph.contains(null, "ex:title"); // true
    graph.size(); // 1
    graph.clear(); // removes all statements - same as calling remove();
Note that in the graph methods allow you to pass native javascript objects. The library will try to guess what you meant and create the proper rdf nodes for you underneath. Be very careful using this feature as the guessed types may not be exactly what you want. The library has a number of other features including a quad store, parsers, etc that I will cover in future tutorials. -Happy hacking Openanzo is an opensource project distributed under the Eclipse Public License.