- 浏览: 208781 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
xiaokang1582830:
这有涉及到跨域?
ajax跨域调用webservice -
337240552:
...
web.xml中<security-constraint>和四种认证类型 -
pythoner126com:
写得不错,国内对perl热情不是很高,我最近也有翻译,请多多指 ...
Perl Hash 用法 -
an_yeblack:
你好,我想问一下,一般是什么愿因导致这种错误的呢?先谢谢了!! ...
WAS7 无法在控制台启动 Node Agent -
linzixiao:
感谢分享
冻结table的行和列
简介
如果您是一名只有很少或根本没有 JavaScript 经验的开发人员,在接触 Dojo 时可能需要掌握一些必要的概念。Dojo 的一个主要问题是(在撰写本文之际),它仍然处于其婴儿期(版本 1.0 在 2008 年 2 月份才发布),并且可用的文档仍然非常有限。本文将帮助您理解 Dojo 和 Java 代码之间的联系,使您在开发应用程序时可以快速入手并掌握这个工具箱。
本文并没有介绍如何获得 Dojo 工具箱或一些必要的使用指令,因为已经有大量的资源提供了此类信息。本文主要针对从 servlet 开发转向 Dojo 的 Web 开发人员
JavaScript hash:
需要面对的主要挑战之一就是理解在调用 Dojo 函数时使用的语法,特别是 “hash” 或 JavaScript 对象。hash 被表示为使用逗号间隔的一组属性,并且使用大括号括起。清单 1 显示了一个简单的例子,它声明了一个包含 6 个属性的 hash:一个字符串、一个整数、一个布尔值、一个未定义的属性、另一个 hash 和一个函数
清单 1. 示例 JavaScript hash
注意,JavaScript 是弱类型的,因此尽管每个属性被初始化为一个与其名称相关的值,但仍然需要把 str_attr 属性设置为一个整数或布尔值(或其他任何类型)。使用 dot 操作符可以访问或设置 hash 中的每个属性(参见清单 2)。
清单 2. 访问和设置 hash 属性
myHash 的前四个属性的含义不言自明。事实上,hash 可以拥有 hash 属性,这并不奇怪。(可以将这看作类似于原语和对象的 Java 类)。这是需要理解的最后一个重要属性
函数和对象
尽管 Java 代码中有一个 java.reflection.Method 类,但它实际上只充当方法的包装器。在 JavaScript 中,该函数可以是任何可设置、引用和作为参数传递给其他函数的对象。通常,像在 Java 方法调用中声明匿名 inner 类一样,也需要在函数调用中声明新函数。
Java 方法和 JavaScript 函数之间的另一个重要区别是 JavaScript 函数可以运行在不同的上下文中。在 Java 编程中,使用 this 关键字引用所使用类的当前实例。当在 JavaScript 函数中使用时,this 引用该函数运行的上下文。如果没有指定,函数将在定义它的闭包中运行。
在最简单的情况下,闭包可以被看作是使用大括号({})包含的任意 JavaScript 代码。JavaScript 文件内部声明的函数可以使用 this 访问在文件主体中声明的任何变量,但是在 hash 内声明的函数只能使用 this 引用在 hash 内部声明的变量,除非提供其他上下文。
由于经常需要使用封闭的函数作为 Dojo 函数的参数,因此理解如何设置上下文将省去大量的调试工作。
用于指定上下文的主要 Dojo 函数是 dojo.hitch。您可能从不使用 dojo.hitch,但必须了解它是 Dojo 的关键部分,很多函数都在内部调用它。
清单 3 展示了上下文连接的工作原理(其输出显示在图 1 中):
在全局上下文(globalContextVariable)中定义一个变量,在一个 hash 上下文(enclosedVariable)中声明另一个变量。
函数 accessGlobalContext() 可以成功访问 globalContextVariable 并显示其值。
但是,enclosedFunction() 只可以访问其本地变量 enclosedVariable(注意 globalContextVariable 的值显示为 “未定义”)。
使用 dojo.hitch 将 enclosedFunction() 连接到全局上下文,这样就可以显示 globalContextVariable(注意,enclosedVariable 现在为 “未定义”,因为它不是在运行 enclosedFunction() 的上下文中声明的)。
清单 3. 闭包和上下文
图 1. 上下文连接的工作原理
声明类
为什么连接如此重要?您将在声明 Dojo 类或创建自己的部件时体验到它的重要性。Dojo 的一大功能就是能够通过使用 dojo.connect 函数和内置的 pub/sub 模型将对象 “连接” 起来。
类的声明需要三个对象:
一个惟一的类名
用于扩展函数的父类(以及模拟多个继承的 “混合” 类)
定义所有属性和函数的 hash
清单 4 展示了最简单的类声明方式,清单 5 展示了该类的实例化。
清单 4. 基本的类声明
清单 5. 基本的类实例化
如果希望声明一个 “真正的”(即有用的)Dojo 类,那么一定要理解构造函数。在 Java 代码中,您可以通过使用各种不同的签名声明多个重载的构造函数,从而支持实例化。在一个 Dojo 类中,可以声明一个 preamble、一个 constructor 和一个 postscript,但是在大多数情况下,您只需要声明一个构造函数。
a 除非混合使用了其他类来模拟多个继承,否则不需要用到 preamble,因为它允许您在 constructor 参数传递给扩展类和混合类之前对其进行处理。
b postscript 产生了 Dojo 小部件生命周期方法,但对标准 Dojo 类没有什么用处。
不一定要全部都声明,但是要将所有值传递到类的实例中,就必须将 constructor 函数声明为 minimum。如果 constructor 参数将被该类的其他方法访问,必须将它们赋值给已声明的属性。清单 6 展示了一个类,它只将其中一个 constructor 参数赋值给一个类属性,并尝试在另一个方法中引用它们。
清单 6. 赋值构造函数参数
图 2. 赋值构造函数参数的结果
复杂的属性规则
类属性可以在声明时进行初始化,但是如果使用复杂对象类型(例如 hash 或数组)初始化属性,该属性将类似于 Java 类中的公共静态变量。这意味着任何实例无论在何时更新它,修改将反映到所有其他实例中。为了避免这个问题,应当在构造函数中初始化复杂属性;然而,对于字符串、布尔值等简单属性则不需要这样做。
清单 7. 全局类属性
图 3. 类属性
覆盖方法
超类的方法可以通过使用相同的名称声明属性来扩展。这里和重载无关,因为 JavaScript 将忽略任何意外的参数并使用 null 代替任何缺失的参数。在 Java 代码中,如果要调用被覆盖的方法,就必须在超类上调用该方法(即 super().methodName(arg1, arg1);),但在 Dojo 中,将使用 inherited 方法(this.inherited(arguments);)。清单 8 展示了两个已声明的类,其中 child 扩展了 parent,覆盖了它的 helloWorld 方法,但是调用 inherited 来访问 parent 的函数
清单 8. 在 Dojo 中调用超类方法
图 4. 在 Dojo 中调用超类方法的输出
设置方法上下文
清单 9 展示了一个实例化后的 Java 类,它将字符串数组中的元素复制到一个字符串 ArrayList。显然,使用清单 10 的代码可以在 Dojo 中提供相同的功能(注意,在构造函数中实例化 targetArray,防止它变成全局性的)。不幸的是,它将导致图 5 所示的错误消息,因为在 dojo.forEach 方法调用中声明的函数创建了一个闭包,该闭包将 this 定义为引用它本身。
清单 9. 在 Java 代码中访问类的作用域变量
清单 10. 在 Dojo 中缺失上下文
简介
如果您是一名只有很少或根本没有 JavaScript 经验的开发人员,在接触 Dojo 时可能需要掌握一些必要的概念。Dojo 的一个主要问题是(在撰写本文之际),它仍然处于其婴儿期(版本 1.0 在 2008 年 2 月份才发布),并且可用的文档仍然非常有限。本文将帮助您理解 Dojo 和 Java 代码之间的联系,使您在开发应用程序时可以快速入手并掌握这个工具箱。
本文并没有介绍如何获得 Dojo 工具箱或一些必要的使用指令,因为已经有大量的资源提供了此类信息。本文主要针对从 servlet 开发转向 Dojo 的 Web 开发人员。
Ajax 资源中心请访问 Ajax 资源中心,这是有关 Ajax 编程模型信息的一站式中心,包括很多文档、教程、论坛、blog、wiki 和新闻。任何 Ajax 的新信息都能在这里找到。
JavaScript hash
需要面对的主要挑战之一就是理解在调用 Dojo 函数时使用的语法,特别是 “hash” 或 JavaScript 对象。hash 被表示为使用逗号间隔的一组属性,并且使用大括号括起。清单 1 显示了一个简单的例子,它声明了一个包含 6 个属性的 hash:一个字符串、一个整数、一个布尔值、一个未定义的属性、另一个 hash 和一个函数。
清单 1. 示例 JavaScript hash
var myHash = {
str_attr : "foo",
int_attr : 7,
bool_attr : true,
undefined_attr : null,
hash_attr : {},
func_attr : function() {}
};
注意,JavaScript 是弱类型的,因此尽管每个属性被初始化为一个与其名称相关的值,但仍然需要把 str_attr 属性设置为一个整数或布尔值(或其他任何类型)。使用 dot 操作符可以访问或设置 hash 中的每个属性(参见清单 2)。
清单 2. 访问和设置 hash 属性
// Accessing a hash attribute...
console.log(myHash.str_attr);
// Setting a hash attribute...
myHash.str_attr = "bar";
myHash 的前四个属性的含义不言自明。事实上,hash 可以拥有 hash 属性,这并不奇怪。(可以将这看作类似于原语和对象的 Java 类)。这是需要理解的最后一个重要属性。
函数和对象
尽管 Java 代码中有一个 java.reflection.Method 类,但它实际上只充当方法的包装器。在 JavaScript 中,该函数可以是任何可设置、引用和作为参数传递给其他函数的对象。通常,像在 Java 方法调用中声明匿名 inner 类一样,也需要在函数调用中声明新函数。
Java 方法和 JavaScript 函数之间的另一个重要区别是 JavaScript 函数可以运行在不同的上下文中。在 Java 编程中,使用 this 关键字引用所使用类的当前实例。当在 JavaScript 函数中使用时,this 引用该函数运行的上下文。如果没有指定,函数将在定义它的闭包中运行。
在最简单的情况下,闭包可以被看作是使用大括号({})包含的任意 JavaScript 代码。JavaScript 文件内部声明的函数可以使用 this 访问在文件主体中声明的任何变量,但是在 hash 内声明的函数只能使用 this 引用在 hash 内部声明的变量,除非提供其他上下文。
由于经常需要使用封闭的函数作为 Dojo 函数的参数,因此理解如何设置上下文将省去大量的调试工作。
用于指定上下文的主要 Dojo 函数是 dojo.hitch。您可能从不使用 dojo.hitch,但必须了解它是 Dojo 的关键部分,很多函数都在内部调用它。
清单 3 展示了上下文连接的工作原理(其输出显示在图 1 中):
在全局上下文(globalContextVariable)中定义一个变量,在一个 hash 上下文(enclosedVariable)中声明另一个变量。
函数 accessGlobalContext() 可以成功访问 globalContextVariable 并显示其值。
但是,enclosedFunction() 只可以访问其本地变量 enclosedVariable(注意 globalContextVariable 的值显示为 “未定义”)。
使用 dojo.hitch 将 enclosedFunction() 连接到全局上下文,这样就可以显示 globalContextVariable(注意,enclosedVariable 现在为 “未定义”,因为它不是在运行 enclosedFunction() 的上下文中声明的)。
清单 3. 闭包和上下文
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();
图 1. 上下文连接的工作原理
声明类
声明类的技巧尽管 myClass 是一个有效的名称,但是最好使用完全限定类名的形式声明名称,例如 com.ibm.dojo.myClass。这并不表示应当把类部署到相对路径 “./com/ibm/dojo/” 下的文件系统;它只是减少了与其他类名冲突的几率。
在最后一个属性之后绝不会出现 ,(逗号),因为一些浏览器将忽略它(FireFox),但是其他浏览器(Internet Explorer)会将它弹出。这条规则也适用于 hash 对象的声明。
为什么连接如此重要?您将在声明 Dojo 类或创建自己的部件时体验到它的重要性。Dojo 的一大功能就是能够通过使用 dojo.connect 函数和内置的 pub/sub 模型将对象 “连接” 起来。
类的声明需要三个对象:
一个惟一的类名
用于扩展函数的父类(以及模拟多个继承的 “混合” 类)
定义所有属性和函数的 hash
清单 4 展示了最简单的类声明方式,清单 5 展示了该类的实例化。
清单 4. 基本的类声明
dojo.declare(
"myClass",
null,
{}
);
清单 5. 基本的类实例化
var myClassInstance = new myClass();
如果希望声明一个 “真正的”(即有用的)Dojo 类,那么一定要理解构造函数。在 Java 代码中,您可以通过使用各种不同的签名声明多个重载的构造函数,从而支持实例化。在一个 Dojo 类中,可以声明一个 preamble、一个 constructor 和一个 postscript,但是在大多数情况下,您只需要声明一个构造函数。
除非混合使用了其他类来模拟多个继承,否则不需要用到 preamble,因为它允许您在 constructor 参数传递给扩展类和混合类之前对其进行处理。
postscript 产生了 Dojo 小部件生命周期方法,但对标准 Dojo 类没有什么用处。
不一定要全部都声明,但是要将所有值传递到类的实例中,就必须将 constructor 函数声明为 minimum。如果 constructor 参数将被该类的其他方法访问,必须将它们赋值给已声明的属性。清单 6 展示了一个类,它只将其中一个 constructor 参数赋值给一个类属性,并尝试在另一个方法中引用它们。
清单 6. 赋值构造函数参数
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();
图 2. 赋值构造函数参数的结果
复杂的属性规则
类属性可以在声明时进行初始化,但是如果使用复杂对象类型(例如 hash 或数组)初始化属性,该属性将类似于 Java 类中的公共静态变量。这意味着任何实例无论在何时更新它,修改将反映到所有其他实例中。为了避免这个问题,应当在构造函数中初始化复杂属性;然而,对于字符串、布尔值等简单属性则不需要这样做。
清单 7. 全局类属性
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);
图 3. 类属性
覆盖方法
超类的方法可以通过使用相同的名称声明属性来扩展。这里和重载无关,因为 JavaScript 将忽略任何意外的参数并使用 null 代替任何缺失的参数。在 Java 代码中,如果要调用被覆盖的方法,就必须在超类上调用该方法(即 super().methodName(arg1, arg1);),但在 Dojo 中,将使用 inherited 方法(this.inherited(arguments);)。清单 8 展示了两个已声明的类,其中 child 扩展了 parent,覆盖了它的 helloWorld 方法,但是调用 inherited 来访问 parent 的函数。
清单 8. 在 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();
图 4. 在 Dojo 中调用超类方法的输出
设置方法上下文
清单 9 展示了一个实例化后的 Java 类,它将字符串数组中的元素复制到一个字符串 ArrayList。显然,使用清单 10 的代码可以在 Dojo 中提供相同的功能(注意,在构造函数中实例化 targetArray,防止它变成全局性的)。不幸的是,它将导致图 5 所示的错误消息,因为在 dojo.forEach 方法调用中声明的函数创建了一个闭包,该闭包将 this 定义为引用它本身。
清单 9. 在 Java 代码中访问类的作用域变量
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);
}
}
}
清单 10. 在 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 will cause an error!
var myClass = new myClass(["item1","item2"]);
图 5. 在 Dojo 中缺失上下文的输出
尽管 targetArray 并不是在函数包围的上下文中定义的,但是可以将上下文定义为参数传递给 Dojo 函数。这意味着 this 关键字可以访问在该上下文中声明的任何对象(包括函数)。清单 11 显示了正确的实现(注意,增加的代码用粗体表示)。
清单 11. 在 Dojo 中设置正确的上下文:
上下文并不总是作为 Dojo 函数签名中的相同参数传递的:
在 dojo.subscribe 中,上下文是在函数声明之前传递的(参见清单 12)。
在 dojo.connect 中,应该分别提供定义 trigger 方法和 target 方法的上下文。清单 13 展示了一个例子,其中 obj1 定义 methodA 的上下文,而 obj2 定义 methodB 的上下文。对 obj1 调用 methodA 将导致对 obj2 调用 methodB
清单 12. 在 dojo.subscribe 中设置上下文
清单 13. 在 dojo.connect 中设置上下文
from :http://www.ibm.com/developerworks/cn/web/wa-dojotoolkit/
如果您是一名只有很少或根本没有 JavaScript 经验的开发人员,在接触 Dojo 时可能需要掌握一些必要的概念。Dojo 的一个主要问题是(在撰写本文之际),它仍然处于其婴儿期(版本 1.0 在 2008 年 2 月份才发布),并且可用的文档仍然非常有限。本文将帮助您理解 Dojo 和 Java 代码之间的联系,使您在开发应用程序时可以快速入手并掌握这个工具箱。
本文并没有介绍如何获得 Dojo 工具箱或一些必要的使用指令,因为已经有大量的资源提供了此类信息。本文主要针对从 servlet 开发转向 Dojo 的 Web 开发人员
JavaScript hash:
需要面对的主要挑战之一就是理解在调用 Dojo 函数时使用的语法,特别是 “hash” 或 JavaScript 对象。hash 被表示为使用逗号间隔的一组属性,并且使用大括号括起。清单 1 显示了一个简单的例子,它声明了一个包含 6 个属性的 hash:一个字符串、一个整数、一个布尔值、一个未定义的属性、另一个 hash 和一个函数
清单 1. 示例 JavaScript hash
var myHash = { str_attr : "foo", int_attr : 7, bool_attr : true, undefined_attr : null, hash_attr : {}, func_attr : function() {} };
注意,JavaScript 是弱类型的,因此尽管每个属性被初始化为一个与其名称相关的值,但仍然需要把 str_attr 属性设置为一个整数或布尔值(或其他任何类型)。使用 dot 操作符可以访问或设置 hash 中的每个属性(参见清单 2)。
清单 2. 访问和设置 hash 属性
// Accessing a hash attribute... console.log(myHash.str_attr); // Setting a hash attribute... myHash.str_attr = "bar";
myHash 的前四个属性的含义不言自明。事实上,hash 可以拥有 hash 属性,这并不奇怪。(可以将这看作类似于原语和对象的 Java 类)。这是需要理解的最后一个重要属性
函数和对象
尽管 Java 代码中有一个 java.reflection.Method 类,但它实际上只充当方法的包装器。在 JavaScript 中,该函数可以是任何可设置、引用和作为参数传递给其他函数的对象。通常,像在 Java 方法调用中声明匿名 inner 类一样,也需要在函数调用中声明新函数。
Java 方法和 JavaScript 函数之间的另一个重要区别是 JavaScript 函数可以运行在不同的上下文中。在 Java 编程中,使用 this 关键字引用所使用类的当前实例。当在 JavaScript 函数中使用时,this 引用该函数运行的上下文。如果没有指定,函数将在定义它的闭包中运行。
在最简单的情况下,闭包可以被看作是使用大括号({})包含的任意 JavaScript 代码。JavaScript 文件内部声明的函数可以使用 this 访问在文件主体中声明的任何变量,但是在 hash 内声明的函数只能使用 this 引用在 hash 内部声明的变量,除非提供其他上下文。
由于经常需要使用封闭的函数作为 Dojo 函数的参数,因此理解如何设置上下文将省去大量的调试工作。
用于指定上下文的主要 Dojo 函数是 dojo.hitch。您可能从不使用 dojo.hitch,但必须了解它是 Dojo 的关键部分,很多函数都在内部调用它。
清单 3 展示了上下文连接的工作原理(其输出显示在图 1 中):
在全局上下文(globalContextVariable)中定义一个变量,在一个 hash 上下文(enclosedVariable)中声明另一个变量。
函数 accessGlobalContext() 可以成功访问 globalContextVariable 并显示其值。
但是,enclosedFunction() 只可以访问其本地变量 enclosedVariable(注意 globalContextVariable 的值显示为 “未定义”)。
使用 dojo.hitch 将 enclosedFunction() 连接到全局上下文,这样就可以显示 globalContextVariable(注意,enclosedVariable 现在为 “未定义”,因为它不是在运行 enclosedFunction() 的上下文中声明的)。
清单 3. 闭包和上下文
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();
图 1. 上下文连接的工作原理
声明类
为什么连接如此重要?您将在声明 Dojo 类或创建自己的部件时体验到它的重要性。Dojo 的一大功能就是能够通过使用 dojo.connect 函数和内置的 pub/sub 模型将对象 “连接” 起来。
类的声明需要三个对象:
一个惟一的类名
用于扩展函数的父类(以及模拟多个继承的 “混合” 类)
定义所有属性和函数的 hash
清单 4 展示了最简单的类声明方式,清单 5 展示了该类的实例化。
清单 4. 基本的类声明
dojo.declare( "myClass", null, {} );
清单 5. 基本的类实例化
var myClassInstance = new myClass();
如果希望声明一个 “真正的”(即有用的)Dojo 类,那么一定要理解构造函数。在 Java 代码中,您可以通过使用各种不同的签名声明多个重载的构造函数,从而支持实例化。在一个 Dojo 类中,可以声明一个 preamble、一个 constructor 和一个 postscript,但是在大多数情况下,您只需要声明一个构造函数。
a 除非混合使用了其他类来模拟多个继承,否则不需要用到 preamble,因为它允许您在 constructor 参数传递给扩展类和混合类之前对其进行处理。
b postscript 产生了 Dojo 小部件生命周期方法,但对标准 Dojo 类没有什么用处。
不一定要全部都声明,但是要将所有值传递到类的实例中,就必须将 constructor 函数声明为 minimum。如果 constructor 参数将被该类的其他方法访问,必须将它们赋值给已声明的属性。清单 6 展示了一个类,它只将其中一个 constructor 参数赋值给一个类属性,并尝试在另一个方法中引用它们。
清单 6. 赋值构造函数参数
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();
图 2. 赋值构造函数参数的结果
复杂的属性规则
类属性可以在声明时进行初始化,但是如果使用复杂对象类型(例如 hash 或数组)初始化属性,该属性将类似于 Java 类中的公共静态变量。这意味着任何实例无论在何时更新它,修改将反映到所有其他实例中。为了避免这个问题,应当在构造函数中初始化复杂属性;然而,对于字符串、布尔值等简单属性则不需要这样做。
清单 7. 全局类属性
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);
图 3. 类属性
覆盖方法
超类的方法可以通过使用相同的名称声明属性来扩展。这里和重载无关,因为 JavaScript 将忽略任何意外的参数并使用 null 代替任何缺失的参数。在 Java 代码中,如果要调用被覆盖的方法,就必须在超类上调用该方法(即 super().methodName(arg1, arg1);),但在 Dojo 中,将使用 inherited 方法(this.inherited(arguments);)。清单 8 展示了两个已声明的类,其中 child 扩展了 parent,覆盖了它的 helloWorld 方法,但是调用 inherited 来访问 parent 的函数
清单 8. 在 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();
图 4. 在 Dojo 中调用超类方法的输出
设置方法上下文
清单 9 展示了一个实例化后的 Java 类,它将字符串数组中的元素复制到一个字符串 ArrayList。显然,使用清单 10 的代码可以在 Dojo 中提供相同的功能(注意,在构造函数中实例化 targetArray,防止它变成全局性的)。不幸的是,它将导致图 5 所示的错误消息,因为在 dojo.forEach 方法调用中声明的函数创建了一个闭包,该闭包将 this 定义为引用它本身。
清单 9. 在 Java 代码中访问类的作用域变量
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); } } }
清单 10. 在 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 will cause an error! var myClass = new myClass(["item1","item2"]);
简介
如果您是一名只有很少或根本没有 JavaScript 经验的开发人员,在接触 Dojo 时可能需要掌握一些必要的概念。Dojo 的一个主要问题是(在撰写本文之际),它仍然处于其婴儿期(版本 1.0 在 2008 年 2 月份才发布),并且可用的文档仍然非常有限。本文将帮助您理解 Dojo 和 Java 代码之间的联系,使您在开发应用程序时可以快速入手并掌握这个工具箱。
本文并没有介绍如何获得 Dojo 工具箱或一些必要的使用指令,因为已经有大量的资源提供了此类信息。本文主要针对从 servlet 开发转向 Dojo 的 Web 开发人员。
Ajax 资源中心请访问 Ajax 资源中心,这是有关 Ajax 编程模型信息的一站式中心,包括很多文档、教程、论坛、blog、wiki 和新闻。任何 Ajax 的新信息都能在这里找到。
JavaScript hash
需要面对的主要挑战之一就是理解在调用 Dojo 函数时使用的语法,特别是 “hash” 或 JavaScript 对象。hash 被表示为使用逗号间隔的一组属性,并且使用大括号括起。清单 1 显示了一个简单的例子,它声明了一个包含 6 个属性的 hash:一个字符串、一个整数、一个布尔值、一个未定义的属性、另一个 hash 和一个函数。
清单 1. 示例 JavaScript hash
var myHash = {
str_attr : "foo",
int_attr : 7,
bool_attr : true,
undefined_attr : null,
hash_attr : {},
func_attr : function() {}
};
注意,JavaScript 是弱类型的,因此尽管每个属性被初始化为一个与其名称相关的值,但仍然需要把 str_attr 属性设置为一个整数或布尔值(或其他任何类型)。使用 dot 操作符可以访问或设置 hash 中的每个属性(参见清单 2)。
清单 2. 访问和设置 hash 属性
// Accessing a hash attribute...
console.log(myHash.str_attr);
// Setting a hash attribute...
myHash.str_attr = "bar";
myHash 的前四个属性的含义不言自明。事实上,hash 可以拥有 hash 属性,这并不奇怪。(可以将这看作类似于原语和对象的 Java 类)。这是需要理解的最后一个重要属性。
函数和对象
尽管 Java 代码中有一个 java.reflection.Method 类,但它实际上只充当方法的包装器。在 JavaScript 中,该函数可以是任何可设置、引用和作为参数传递给其他函数的对象。通常,像在 Java 方法调用中声明匿名 inner 类一样,也需要在函数调用中声明新函数。
Java 方法和 JavaScript 函数之间的另一个重要区别是 JavaScript 函数可以运行在不同的上下文中。在 Java 编程中,使用 this 关键字引用所使用类的当前实例。当在 JavaScript 函数中使用时,this 引用该函数运行的上下文。如果没有指定,函数将在定义它的闭包中运行。
在最简单的情况下,闭包可以被看作是使用大括号({})包含的任意 JavaScript 代码。JavaScript 文件内部声明的函数可以使用 this 访问在文件主体中声明的任何变量,但是在 hash 内声明的函数只能使用 this 引用在 hash 内部声明的变量,除非提供其他上下文。
由于经常需要使用封闭的函数作为 Dojo 函数的参数,因此理解如何设置上下文将省去大量的调试工作。
用于指定上下文的主要 Dojo 函数是 dojo.hitch。您可能从不使用 dojo.hitch,但必须了解它是 Dojo 的关键部分,很多函数都在内部调用它。
清单 3 展示了上下文连接的工作原理(其输出显示在图 1 中):
在全局上下文(globalContextVariable)中定义一个变量,在一个 hash 上下文(enclosedVariable)中声明另一个变量。
函数 accessGlobalContext() 可以成功访问 globalContextVariable 并显示其值。
但是,enclosedFunction() 只可以访问其本地变量 enclosedVariable(注意 globalContextVariable 的值显示为 “未定义”)。
使用 dojo.hitch 将 enclosedFunction() 连接到全局上下文,这样就可以显示 globalContextVariable(注意,enclosedVariable 现在为 “未定义”,因为它不是在运行 enclosedFunction() 的上下文中声明的)。
清单 3. 闭包和上下文
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();
图 1. 上下文连接的工作原理
声明类
声明类的技巧尽管 myClass 是一个有效的名称,但是最好使用完全限定类名的形式声明名称,例如 com.ibm.dojo.myClass。这并不表示应当把类部署到相对路径 “./com/ibm/dojo/” 下的文件系统;它只是减少了与其他类名冲突的几率。
在最后一个属性之后绝不会出现 ,(逗号),因为一些浏览器将忽略它(FireFox),但是其他浏览器(Internet Explorer)会将它弹出。这条规则也适用于 hash 对象的声明。
为什么连接如此重要?您将在声明 Dojo 类或创建自己的部件时体验到它的重要性。Dojo 的一大功能就是能够通过使用 dojo.connect 函数和内置的 pub/sub 模型将对象 “连接” 起来。
类的声明需要三个对象:
一个惟一的类名
用于扩展函数的父类(以及模拟多个继承的 “混合” 类)
定义所有属性和函数的 hash
清单 4 展示了最简单的类声明方式,清单 5 展示了该类的实例化。
清单 4. 基本的类声明
dojo.declare(
"myClass",
null,
{}
);
清单 5. 基本的类实例化
var myClassInstance = new myClass();
如果希望声明一个 “真正的”(即有用的)Dojo 类,那么一定要理解构造函数。在 Java 代码中,您可以通过使用各种不同的签名声明多个重载的构造函数,从而支持实例化。在一个 Dojo 类中,可以声明一个 preamble、一个 constructor 和一个 postscript,但是在大多数情况下,您只需要声明一个构造函数。
除非混合使用了其他类来模拟多个继承,否则不需要用到 preamble,因为它允许您在 constructor 参数传递给扩展类和混合类之前对其进行处理。
postscript 产生了 Dojo 小部件生命周期方法,但对标准 Dojo 类没有什么用处。
不一定要全部都声明,但是要将所有值传递到类的实例中,就必须将 constructor 函数声明为 minimum。如果 constructor 参数将被该类的其他方法访问,必须将它们赋值给已声明的属性。清单 6 展示了一个类,它只将其中一个 constructor 参数赋值给一个类属性,并尝试在另一个方法中引用它们。
清单 6. 赋值构造函数参数
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();
图 2. 赋值构造函数参数的结果
复杂的属性规则
类属性可以在声明时进行初始化,但是如果使用复杂对象类型(例如 hash 或数组)初始化属性,该属性将类似于 Java 类中的公共静态变量。这意味着任何实例无论在何时更新它,修改将反映到所有其他实例中。为了避免这个问题,应当在构造函数中初始化复杂属性;然而,对于字符串、布尔值等简单属性则不需要这样做。
清单 7. 全局类属性
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);
图 3. 类属性
覆盖方法
超类的方法可以通过使用相同的名称声明属性来扩展。这里和重载无关,因为 JavaScript 将忽略任何意外的参数并使用 null 代替任何缺失的参数。在 Java 代码中,如果要调用被覆盖的方法,就必须在超类上调用该方法(即 super().methodName(arg1, arg1);),但在 Dojo 中,将使用 inherited 方法(this.inherited(arguments);)。清单 8 展示了两个已声明的类,其中 child 扩展了 parent,覆盖了它的 helloWorld 方法,但是调用 inherited 来访问 parent 的函数。
清单 8. 在 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();
图 4. 在 Dojo 中调用超类方法的输出
设置方法上下文
清单 9 展示了一个实例化后的 Java 类,它将字符串数组中的元素复制到一个字符串 ArrayList。显然,使用清单 10 的代码可以在 Dojo 中提供相同的功能(注意,在构造函数中实例化 targetArray,防止它变成全局性的)。不幸的是,它将导致图 5 所示的错误消息,因为在 dojo.forEach 方法调用中声明的函数创建了一个闭包,该闭包将 this 定义为引用它本身。
清单 9. 在 Java 代码中访问类的作用域变量
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);
}
}
}
清单 10. 在 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 will cause an error!
var myClass = new myClass(["item1","item2"]);
图 5. 在 Dojo 中缺失上下文的输出
尽管 targetArray 并不是在函数包围的上下文中定义的,但是可以将上下文定义为参数传递给 Dojo 函数。这意味着 this 关键字可以访问在该上下文中声明的任何对象(包括函数)。清单 11 显示了正确的实现(注意,增加的代码用粗体表示)。
清单 11. 在 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); }, } );
上下文并不总是作为 Dojo 函数签名中的相同参数传递的:
在 dojo.subscribe 中,上下文是在函数声明之前传递的(参见清单 12)。
在 dojo.connect 中,应该分别提供定义 trigger 方法和 target 方法的上下文。清单 13 展示了一个例子,其中 obj1 定义 methodA 的上下文,而 obj2 定义 methodB 的上下文。对 obj1 调用 methodA 将导致对 obj2 调用 methodB
清单 12. 在 dojo.subscribe 中设置上下文
dojo.declare( "myClass", null, { subscribe : function() { dojo.subscribe("publication", this, function(pub) { this.handlePublication(pub); }); }, handlePublication : function(pub) { console.log("Received: " + pub); } } );
清单 13. 在 dojo.connect 中设置上下文
dojo.connect(obj1, "methodA", obj2, "methodB");
from :http://www.ibm.com/developerworks/cn/web/wa-dojotoolkit/
发表评论
-
蛮不错的Dojo学习资源
2011-03-10 17:36 803第一章 JS中的对象模型 http://driftcloudy ... -
Dojo 中定义和继承class
2011-03-10 17:19 1531面向对象,定义Class dojo里如何定义Class: do ... -
Dojo之Array处理
2011-03-01 09:41 1254Dojo内置了很多Array处理的方法,具体有:doj ... -
Dojo的国际化dojo.i18n.getLocalization
2011-02-25 15:41 1858<script type="text/java ... -
Dojo CookBook
2011-02-23 14:46 882Dojo CookBook as following atta ... -
Dojo1.5 之 djConfig
2011-02-16 10:43 1246djConfig介绍 djConfig是Dojo的一个 ... -
Dojo中Dijit组件Widget的生命周期
2011-02-10 16:04 2185FYI:http://www.360doc.com/conte ... -
Dojo的界面控件Dijit和Dojo quick start
2011-01-28 17:00 899Dijit: http://www.iteye.com/top ... -
Dojo Hello World
2011-01-28 16:45 1185from: http://www.iteye.com/topi ... -
dojo的基本方法介绍
2011-01-25 17:41 2414一 dojo.moduleUrl(module,url) ... -
dojo的国际化处理
2011-01-04 14:40 1406转自:http://blog.csdn.net/e ...
相关推荐
最大限度地减少时间和费用开发自定义的DSL(领域特定语言在Java)要求。 日志服务器 Apache Flume.tar Flume 是一个分布式、可靠和高可用的服务,用于收集、聚合以及移动大量日志数据,使用一个简单灵活的架构,就...
最大限度地减少时间和费用开发自定义的DSL(领域特定语言在Java)要求。 日志服务器 Apache Flume.tar Flume 是一个分布式、可靠和高可用的服务,用于收集、聚合以及移动大量日志数据,使用一个简单灵活的架构,就...
最大限度地减少时间和费用开发自定义的DSL(领域特定语言在Java)要求。 日志服务器 Apache Flume.tar Flume 是一个分布式、可靠和高可用的服务,用于收集、聚合以及移动大量日志数据,使用一个简单灵活的架构,就...
最大限度地减少时间和费用开发自定义的DSL(领域特定语言在Java)要求。 日志服务器 Apache Flume.tar Flume 是一个分布式、可靠和高可用的服务,用于收集、聚合以及移动大量日志数据,使用一个简单灵活的架构,就...
最大限度地减少时间和费用开发自定义的DSL(领域特定语言在Java)要求。 日志服务器 Apache Flume.tar Flume 是一个分布式、可靠和高可用的服务,用于收集、聚合以及移动大量日志数据,使用一个简单灵活的架构,就...
最大限度地减少时间和费用开发自定义的DSL(领域特定语言在Java)要求。 日志服务器 Apache Flume.tar Flume 是一个分布式、可靠和高可用的服务,用于收集、聚合以及移动大量日志数据,使用一个简单灵活的架构,就...
最大限度地减少时间和费用开发自定义的DSL(领域特定语言在Java)要求。 日志服务器 Apache Flume.tar Flume 是一个分布式、可靠和高可用的服务,用于收集、聚合以及移动大量日志数据,使用一个简单灵活的架构,就...
最大限度地减少时间和费用开发自定义的DSL(领域特定语言在Java)要求。 日志服务器 Apache Flume.tar Flume 是一个分布式、可靠和高可用的服务,用于收集、聚合以及移动大量日志数据,使用一个简单灵活的架构,就...
最大限度地减少时间和费用开发自定义的DSL(领域特定语言在Java)要求。 日志服务器 Apache Flume.tar Flume 是一个分布式、可靠和高可用的服务,用于收集、聚合以及移动大量日志数据,使用一个简单灵活的架构,就...
最大限度地减少时间和费用开发自定义的DSL(领域特定语言在Java)要求。 日志服务器 Apache Flume.tar Flume 是一个分布式、可靠和高可用的服务,用于收集、聚合以及移动大量日志数据,使用一个简单灵活的架构,就...
Java目录监视器源程序 9个目标文件 内容索引:JAVA源码,综合应用,目录监视 用JAVA开发的一个小型的目录监视系统,系统会每5秒自动扫描一次需要监视的目录,可以用来监视目录中文件大小及文件增减数目的变化。...
最大限度地减少时间和费用开发自定义的DSL(领域特定语言在Java)要求。 日志服务器 Apache Flume.tar Flume 是一个分布式、可靠和高可用的服务,用于收集、聚合以及移动大量日志数据,使用一个简单灵活的架构,就...
最大限度地减少时间和费用开发自定义的DSL(领域特定语言在Java)要求。 日志服务器 Apache Flume.tar Flume 是一个分布式、可靠和高可用的服务,用于收集、聚合以及移动大量日志数据,使用一个简单灵活的架构,就...
最大限度地减少时间和费用开发自定义的DSL(领域特定语言在Java)要求。 日志服务器 Apache Flume.tar Flume 是一个分布式、可靠和高可用的服务,用于收集、聚合以及移动大量日志数据,使用一个简单灵活的架构,就...
Schutta和Ryan Asleson撰写,是针对Java开发者深入了解和应用Ajax技术的权威指南。Ajax(Asynchronous JavaScript and XML)是一种用于创建快速动态网页的技术,它使用JavaScript、XMLHttpRequest以及其他标准如CSS...
《Ajax+JSP网站开发从入门到精通》是一本旨在帮助初学者和进阶者掌握Web应用程序开发核心技术的教程。本书以Ajax(异步JavaScript和XML)与JSP(JavaServer Pages)为核心,通过一系列实例深入浅出地阐述了如何构建...
《掌握XPAGE》是针对LOTUS NOTES平台中的一项关键技术——XPAGE进行深入解析的入门丛书。XPAGE是一种基于Lotus Domino Designer的开发工具,用于构建Web应用程序,它类似于JSP(JavaServer Pages)在功能上提供了...
本教程针对初学者,特别是那些已经具备Java基础的开发者,通过一个简单的Demo,让你在20分钟内快速上手Struts2。 首先,了解Struts2的基本架构是非常重要的。Struts2的核心是Action类,它是业务逻辑的载体。当用户...
### Struts2.1权威指南知识点总结 ...综上所述,《Struts2.1权威指南》是一本针对Struts2.1框架的全面指南,不仅适合初学者快速入门,也能帮助有经验的开发者深入理解和运用Struts2.1的高级特性。
这个入门教程和学习笔记是针对初学者设计的,帮助他们快速理解和掌握Struts2的核心概念和实践操作。 Struts2的学习首先需要理解MVC模式。MVC模式将应用逻辑分为三个部分:模型负责业务逻辑,视图负责展示数据,而...