Dojo concept for javascript developer
2012-12-26 18:52
197 查看
Introduction
If you're a Java programmer coming to Dojo with little or noexperience of JavaScript, chances are you're going to struggle withsome of the concepts that enable it to work. The main concerns withDojo are that — at the time of writing — it is still
in its infancy(version 1.0 was only released in February 2008) and thedocumentation available is still somewhat limited. This articlehelps you bridge the gap from Java code to Dojo so that you can getup to speed quickly and use the toolkit when developing
yourapplications.
This article does not describe how to obtain the Dojo toolkit orthe necessary statements needed to use it, because there are manyother resources available that provide that information. Thearticle is written for Web developers who are coming to
Dojo from aservlet development background.
The JavaScripthash
One of the first challenges is to understand the syntax that isused when invoking Dojo functions, in particular the use of the"hash" or JavaScript object. A hash is expressed as a set ofattributes delimited by commas between curly braces. A simpleexample
is shown in Listing 1, declaring a hash consisting of 6attributes: a string, an integer, a boolean, an undefinedattribute, another hash, and a function.
Listing 1. Example JavaScript hash
It is important to remember that JavaScript is weakly typed, soalthough each attribute has been initialized to a value linked toits name, there is no reason why the initial
be subsequently set to an integer or boolean (or any othertype for that matter). Each attribute in the hash can be accessedor set using the dot operator (as shown in Listing 2).
Listing 2. Accessing and setting hash attributes
The first four attributes of
(This can be thought of asanalogous to Java classes referencing both primitives and objects.)It is the final attribute that is most important to understand.
Functions areobjects
Although in Java code there is a
like any other that can be set, referenced,and passed as an argument to other functions. Often it is necessaryto declare new functions in function calls in much the same way asan anonymous inner class can be declared in a Java method call.
Another important difference between Java methods and JavaScriptfunctions is that JavaScript functions can be run in differentcontexts. In Java programming the use of the keyword
the current instance of the class where it is used. When used ina JavaScript function,
function willrun in the closure that defines it unless otherwise specified.
In the simplest terms, a closure can be considered to be anyJavaScript code contained within curly braces (
any variable declared in the main body of that file, but afunction declared inside a hash can only use
hash, unless it isprovided with an alternative context to work in.
Because enclosed functions are often required as arguments to Dojofunctions, understanding how to set their context will save a lotof unnecessary debugging.
The main Dojo function that is used to assign contextis
it is important to understand that it is one of thecornerstones of Dojo, and many other functions are invoking itunder the covers.
Listing 3 shows how context hitching works (its output is shown inFigure 1):
A variable is defined at the global context (
The function
its value.
But,
the value of
Using
global context allows
undefined because it is not declared in the contextthat
Listing 3. Closures and context
Figure 1. How contect hitching works
![](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
Declaringclasses
While
does not mean that the class should be deployed to the filesystem under the relative path of "./com/ibm/dojo/"; it simplyreduces the chances of there being naming collisions with any otherclasses.
There must never be a
rulealso applies to declarations of hash objects anywhere.
The reason why this hitching is so important will become apparentas soon as you start to declare Dojo classes or to create your ownwidgets. One of the greatest powers of Dojo is the ability to"wire" objects together through the use of the
the built-in pub/sub model.
Declaring a class requires three objects:
A unique name for the class
A parent class to extend function from (plus any "mix-in" classesto simulate multiple inheritance)
A hash defining all the attributes and functions.
The simplest possible class that can be declared in shown inListing 4, and its instantiation in Listing 5.
Listing 4. Basic class declaration
Listing 5. Basic class instantiation
If you want to declare a "real" (that is, useful) Dojo class, it'simportant to understand constructors. In Java code you can declaremultiple overloaded constructors to enable the instantiation of theclass by a variety of different signatures. In
a Dojo class you candeclare a
in the majority of cases you will only need to declare aconstructor.
Unless you're mixing-in other classes to simulate multipleinheritances, you are unlikely to require
they are actually passed to the extended and mixed-inclasses.
It is not essential to declare any of them, but to pass any valuesinto an instance of the class the
a minimum. If the
a class thatassigns only one of its
Listing 6. Assigning constructor arguments
Figure 2. Output from assigning constructorarguments
![](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
Complex attributerules
Class attributes can be initialized when declared, but if theattribute is initialized with a complex object type (such as a hashor an array) that attribute becomes analogous to a public staticvariable in a Java class. This means that whenever any
instanceupdates it, the change will be reflected in all other instances. Toavoid this problem, complex attributes should be initialized in theconstructor; however, this is not necessary for simple attributessuch as strings, booleans, and so on.
Listing 7. Global class attributes
Figure 3. Class attributes
![](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
Overridingmethods
A method of a superclass can be extended by declaring an attributewith the same name. There is no concept of overloading, asJavaScript ignores any unexpected arguments and substitutes nullfor any that are missing. In Java code, to invoke the overriddenmethod
you call the method on super (that is,
8 shows two classes declared, where
its
the function of
Listing 8. Invoking superclass method in Dojo
Figure 4. Output from invoking superclass method inDojo
![](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
Setting methodcontext
Listing 9 shows a Java class that, upon instantiation, copies theelements from the supplied string array to an ArrayList of strings.It would not be unreasonable to assume that the same functionalitycan be provided in Dojo with the code in Listing
10. (Note theinstantiation of
in Figure5, because the function declared in the
to its own body.
Listing 9. Accessing class scoped variable in Javacode
Listing 10. Missing context in Dojo
Figure 5. Output from missing context in Dojo
![](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
Although
to the Dojofunction. This means the
implementation is shown inListing 11 (note the additional code in bold).
Listing 11. Setting correct context in Dojo
Context is not always passed as the same argument in a Dojofunctions signature:
In
(Listing 12).
In
an example where
and
Calling
on
Listing 12. Setting context in dojo.subscribe
Listing 13. Setting context in dojo.connect
Conclusion
JavaScript will never come naturally to developers who have becomeused to the more structured environment of Java code. Yet theimplementation of Dojo, with its class declaration capabilities,does make the leap to client-side development considerably
easier.A good understanding of context, and when and how to set it, willsave a lot of pain for the Java developer and help them confidentlyadd JavaScript to their toolbox.
If you're a Java programmer coming to Dojo with little or noexperience of JavaScript, chances are you're going to struggle withsome of the concepts that enable it to work. The main concerns withDojo are that — at the time of writing — it is still
in its infancy(version 1.0 was only released in February 2008) and thedocumentation available is still somewhat limited. This articlehelps you bridge the gap from Java code to Dojo so that you can getup to speed quickly and use the toolkit when developing
yourapplications.
This article does not describe how to obtain the Dojo toolkit orthe necessary statements needed to use it, because there are manyother resources available that provide that information. Thearticle is written for Web developers who are coming to
Dojo from aservlet development background.
The JavaScripthash
One of the first challenges is to understand the syntax that isused when invoking Dojo functions, in particular the use of the"hash" or JavaScript object. A hash is expressed as a set ofattributes delimited by commas between curly braces. A simpleexample
is shown in Listing 1, declaring a hash consisting of 6attributes: a string, an integer, a boolean, an undefinedattribute, another hash, and a function.
Listing 1. Example JavaScript hash
var myHash = { str_attr : "foo", int_attr : 7, bool_attr : true, undefined_attr : null, hash_attr : {}, func_attr : function() {} }; |
str_attrattributecannot
be subsequently set to an integer or boolean (or any othertype for that matter). Each attribute in the hash can be accessedor set using the dot operator (as shown in Listing 2).
Listing 2. Accessing and setting hash attributes
// Accessing a hash attribute... console.log(myHash.str_attr); // Setting a hash attribute... myHash.str_attr = "bar"; |
myHashshouldbe self-explanatory. The fact that a hash can have attributes thatare also hashes should be no surprise.
(This can be thought of asanalogous to Java classes referencing both primitives and objects.)It is the final attribute that is most important to understand.
Functions areobjects
Although in Java code there is a
java.reflection.Methodclass,it essentially acts as wrapper to a method. In JavaScript thefunction is an object
like any other that can be set, referenced,and passed as an argument to other functions. Often it is necessaryto declare new functions in function calls in much the same way asan anonymous inner class can be declared in a Java method call.
Another important difference between Java methods and JavaScriptfunctions is that JavaScript functions can be run in differentcontexts. In Java programming the use of the keyword
thisrefersto
the current instance of the class where it is used. When used ina JavaScript function,
thisrefersto the context in which that function is running. A
function willrun in the closure that defines it unless otherwise specified.
In the simplest terms, a closure can be considered to be anyJavaScript code contained within curly braces (
{}).A function declared inside a JavaScript file can use
thistoaccess
any variable declared in the main body of that file, but afunction declared inside a hash can only use
thistoreference variables declared inside that
hash, unless it isprovided with an alternative context to work in.
Because enclosed functions are often required as arguments to Dojofunctions, understanding how to set their context will save a lotof unnecessary debugging.
The main Dojo function that is used to assign contextis
dojo.hitch.You may never use
dojo.hitch,but
it is important to understand that it is one of thecornerstones of Dojo, and many other functions are invoking itunder the covers.
Listing 3 shows how context hitching works (its output is shown inFigure 1):
A variable is defined at the global context (
globalContextVariable)and another variable is declared in the context of a hash(
enclosedVariable).
The function
accessGlobalContext()cansuccessfully access
globalContextVariableanddisplay
its value.
But,
enclosedFunction()canonly access its local variable
enclosedVariable(notethat
the value of
globalContextVariableisdisplayed as "undefined").
Using
dojo.hitchto"hitch"
enclosedFunction()tothe
global context allows
globalContextVariabletobe displayed (note however that
enclosedVariableisnow
undefined because it is not declared in the contextthat
enclosedFunction()isrunning.
Listing 3. Closures and context
var globalContextVariable = "foo"; function accessGlobalContext() { // This will successfully output "foo"... console.log(this.globalContextVariable); }; var myHash = { enclosedVariable : "bar", enclosedFunction : function() { // Display global context variable... console.log(this.globalContextVariable); // Display enclosed context variable... console.log(this.enclosedVariable); } }; console.log("Calling accessGlobalContext()..."); accessGlobalContext(); console.log("Calling myHash.enclosedFunction()..."); myHash.enclosedFunction(); console.log("Switch the context using dojo.hitch..."); var switchContext = dojo.hitch(this, myHash.enclosedFunction); switchContext(); |
![](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
Declaringclasses
Class declaration tips
While myClassisa perfectly valid name, it is a better practice to declare namesusing a fully qualified class name style, for example,
com.ibm.dojo.myClass.This
does not mean that the class should be deployed to the filesystem under the relative path of "./com/ibm/dojo/"; it simplyreduces the chances of there being naming collisions with any otherclasses.
There must never be a
,(comma)after the last attribute because some browsers will ignore it(FireFox), but others will blow-up (Internet Explorer). This
rulealso applies to declarations of hash objects anywhere.
The reason why this hitching is so important will become apparentas soon as you start to declare Dojo classes or to create your ownwidgets. One of the greatest powers of Dojo is the ability to"wire" objects together through the use of the
dojo.connectfunctionand
the built-in pub/sub model.
Declaring a class requires three objects:
A unique name for the class
A parent class to extend function from (plus any "mix-in" classesto simulate multiple inheritance)
A hash defining all the attributes and functions.
The simplest possible class that can be declared in shown inListing 4, and its instantiation in Listing 5.
Listing 4. Basic class declaration
dojo.declare( "myClass", null, {} ); |
var myClassInstance = new myClass(); |
a Dojo class you candeclare a
preamble,a
constructor,and a
postscript,but
in the majority of cases you will only need to declare aconstructor.
Unless you're mixing-in other classes to simulate multipleinheritances, you are unlikely to require
preamble,as it allows you to manipulate your
constructorargumentsbefore
they are actually passed to the extended and mixed-inclasses.
postscriptdrivesthe Dojo widget life cycle methods, but provides no benefit to astandard Dojo class.
It is not essential to declare any of them, but to pass any valuesinto an instance of the class the
constructorfunctionmust be declared as
a minimum. If the
constructorargumentsare to be accessed by any other method of the class, they must beassigned to declared attributes. Listing 6 shows
a class thatassigns only one of its
constructorargumentsto a class attribute and then attempts to reference both in anothermethod.
Listing 6. Assigning constructor arguments
dojo.declare( "myClass", null, { arg1 : "", constructor : function(arg1, arg2) { this.arg1 = arg1; }, myMethod : function() { console.log(this.arg1 + "," + this.arg2); } } ); var myClassInstance = new myClass("foo", "bar"); myClassInstance.myMethod(); |
![](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
Complex attributerules
Class attributes can be initialized when declared, but if theattribute is initialized with a complex object type (such as a hashor an array) that attribute becomes analogous to a public staticvariable in a Java class. This means that whenever any
instanceupdates it, the change will be reflected in all other instances. Toavoid this problem, complex attributes should be initialized in theconstructor; however, this is not necessary for simple attributessuch as strings, booleans, and so on.
Listing 7. Global class attributes
dojo.declare( "myClass", null, { globalComplexArg : { val : "foo" }, localComplexArg : null, constructor : function() { this.localComplexArg = { val:"bar" }; } } ); // Create instances of myClass A and B... var A = new myClass(); var B = new myClass(); // Output A's attributes... console.log("A's global val: " + A.globalComplexArg.val); console.log("A's local val: " + A.localComplexArg.val); // Update both of A's attributes... A.globalComplexArg.val = "updatedFoo"; A.localComplexArg.val = "updatedBar"; // Update B's attributes... console.log("A's global val: " + B.globalComplexArg.val); console.log("A's local val: " + B.localComplexArg.val); |
![](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
Overridingmethods
A method of a superclass can be extended by declaring an attributewith the same name. There is no concept of overloading, asJavaScript ignores any unexpected arguments and substitutes nullfor any that are missing. In Java code, to invoke the overriddenmethod
you call the method on super (that is,
super().methodName(arg1,arg1);), but in Dojo you use the
inheritedmethod(
this.inherited(arguments);).Listing
8 shows two classes declared, where
childextends
parent,overriding
its
helloWorldmethod,but calls
inheritedtoaccess
the function of
parent.
Listing 8. Invoking superclass method in Dojo
dojo.declare( "parent", null, { helloWorld : function() { console.log("parent says 'hello world'"); } } ); dojo.declare( "child", parent, { helloWorld : function() { this.inherited(arguments); // Call superclass method... console.log("child says 'hello world'"); } } ); var child = new child(); child.helloWorld(); |
![](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
Setting methodcontext
Listing 9 shows a Java class that, upon instantiation, copies theelements from the supplied string array to an ArrayList of strings.It would not be unreasonable to assume that the same functionalitycan be provided in Dojo with the code in Listing
10. (Note theinstantiation of
targetArrayinthe constructor function to prevent it being global.)Unfortunately, it will result in the error message shown
in Figure5, because the function declared in the
dojo.forEachmethodcall creates a closure that defines
thisasreferring
to its own body.
Listing 9. Accessing class scoped variable in Javacode
import java.util.ArrayList; public class MyClass { // Declare an ArrayList of Strings... private ArrayList<String> targetArray = new ArrayList<String>(); public MyClass(String[] sourceArray) { // Copy each element of a String[] into the ArrayList... for (String val: sourceArray) { this.targetArray.add(val); } } } |
dojo.declare( "myClass", null, { targetArray: null, constructor: function(source) { // Initialise in constructor to avoid making global this.targetArray = []; // Copy each element from source into target... dojo.forEach(source, function(item) { this.targetArray[this.targetArray.length] = item; }); }, } ); // This will cause an error! var myClass = new myClass(["item1","item2"]); |
![](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
Although
targetArrayisnot defined at the context enclosed by the function, it is possibleto pass the context where it is defined as an argument
to the Dojofunction. This means the
thiskeywordcan then access any objects (including functions) that have beendeclared at that context. The correct
implementation is shown inListing 11 (note the additional code in bold).
Listing 11. Setting correct context in Dojo
dojo.declare( "myClass", null, { targetArray: null, constructor: function(source) { // Initialise in constructor to avoid making global this.targetArray = []; // Copy each element from source into target... dojo.forEach(source, function(item) { this.targetArray[this.targetArray.length] = item; }, this); }, } ); |
In
dojo.subscribethecontext is passed before the functiondeclaration
(Listing 12).
In
dojo.connectboththe context where the trigger method is defined and the contextwhere the target method is defined should be supplied. Listing 13shows
an example where
obj1isthe context where
methodAisdefined
and
obj2isthe context where
methodBisdefined.
Calling
methodAon
obj1willresult in
methodBbeinginvoked
on
obj2.
Listing 12. Setting context in dojo.subscribe
dojo.declare( "myClass", null, { subscribe : function() { dojo.subscribe("publication", this, function(pub) { this.handlePublication(pub); }); }, handlePublication : function(pub) { console.log("Received: " + pub); } } ); |
dojo.connect(obj1, "methodA", obj2, "methodB"); |
JavaScript will never come naturally to developers who have becomeused to the more structured environment of Java code. Yet theimplementation of Dojo, with its class declaration capabilities,does make the leap to client-side development considerably
easier.A good understanding of context, and when and how to set it, willsave a lot of pain for the Java developer and help them confidentlyadd JavaScript to their toolbox.
相关文章推荐
- Notes On <Professional.Javascript.For.Web.Developer> - 1
- 关于ArcGIS API for JavaScript与Dojo
- Object of Event--《Professional JavaScript for Web Developer》
- 关于ArcGIS API for JavaScript与Dojo
- ArcGIS API for JavaScript在IDEA增加dojo框架的代码提示功能
- Top 10 JavaScript traps for a C# developer
- 关于ArcGIS API for JavaScript与Dojo
- Top 10 JavaScript traps for a C# developer
- acrgis api for javaScript需要对Dojo了解多少?
- ArcGIS API for JavaScript 需要在DoJo中加载的资源
- 关于ArcGIS API for JavaScript与Dojo
- arcgis api for javascript graphiclayer dojo框架下画图图层的显示与清除
- Notes On <Professional.Javascript.For.Web.Developer> - 2
- Rules For JavaScript Library Authors
- 20160220 - JavaScript for OS X Automation 调试技巧
- ArcGIS API for javascript开发笔记(三)——解决打印输出的中文为乱码问题
- 【转】3 Essential Sublime Text Plugins for Node & JavaScript Developers
- ArcGIS.Server.9.3和ArcGIS API for JavaScript实现基本的地图功能(一)
- 设置鹰眼(ArcGIS API for JavaScript)
- ArcGis API for JavaScript学习——离线部署API