复杂的属性规则
类属性可以在声明时进行初始化,但是如果使用复杂对象类型(例如 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); |
覆盖方法
超类的方法可以通过使用相同的名称声明属性来扩展。这里和重载无关,因为 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 |
清单 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"]); |
责任编辑:小草