// Rhino
var foo = (function () {
var x = 10; // "private"
return function () {
print(x);
};
})();
foo(); // 10
foo.__parent__.x = 20;
foo(); // 20
有时,在JavaScript里通过在变量前加下划线来达到“private”和“protected”数据的目的(但与Python相比,这里只是命名规范):
var _myPrivateData = 'testString';
对于括号括住执行上下文是经常使用,但对于真正的辅助数据,则和对象没有直接关联,只是方便从外部的API抽象出来:
复制代码 代码如下:
(function () {
// 初始化上下文
})();
多重继承
多继承是代码重用改进的一个很方便的语法糖(如果我们一次能继承一个类,为什么不能一次继承10个?)。 然而由于多重继承有一些不足,才导致在实现中没有流行起来。
ECMAScript不支持多继承(即只有一个对象,可以用来作为一个直接原型),虽然其祖先自编程语言有这样的能力。 但在某些实现中(如SpiderMonkey)使用__noSuchMethod__可以用于管理调度和委托来替代原型链。
Mixins
Mixins是代码重用的一种便捷方式。 Mixins已建议作为多重继承的替代品。 这些独立的元素都可以与任何对象进行混合来扩展它们的功能(因此对象也可以混合多个Mixins)。 ECMA-262-3规范没有定义“Mixins”的概念,但根据Mixins定义以及ECMAScript拥有动态可变对象,所以使用Mixins简单地扩充特性是没有障碍的。
典型的例子:
复制代码 代码如下:
// helper for augmentation
Object.extend = function (destination, source) {
for (property in source) if (source.hasOwnProperty(property)) {
destination[property] = source[property];
}
return destination;
};
var X = {a: 10, b: 20};
var Y = {c: 30, d: 40};
Object.extend(X, Y); // mix Y into X
alert([X.a, X.b, X.c, X.d]); 10, 20, 30, 40
请注意,我采取在ECMA-262-3中被提及过的引号中的这些定义(“mixin”,“mix”),在规范里并没有这样的概念,而且不是mix而是常用的通过新特性去扩展对象。(Ruby中mixins的概念是官方定义的,mixin创建了一个包含模块的一个引用来代替简单复制该模块的所有属性到另外一个模块上——事实上是:为委托创建一个额外的对象(原型))。
Traits
Traits和mixins的概念相似,但它有很多功能(根据定义,因为可以应用mixins所以不能包含状态,因为它有可能导致命名冲突)。 根据ECMAScript说明Traits和mixins遵循同样的原则,所以该规范没有定义“Traits”的概念。
接口
在一些OOP中实现的接口和mixins及traits类似。然而,与mixins及traits相比,接口强制实现类必须实现其方法签名的行为。
接口完全可以被视为抽象类。不过与抽象类相比(抽象类里的方法可以只实现一部分,另外一部分依然定义为签名),继承只能是单继承基类,但可以继承多个接口,节约这个原因,可以接口(多个混合)可以看做是多继承的替代方案。
ECMA-262-3标准既没有定义“接口”的概念,也没有定义“抽象类”的概念。 然而,作为模仿,它是可以由“空”的方法(或空方法中抛出异常,告诉开发人员这个方法需要被实现)的对象来实现。
对象组合
对象组合也是一个动态代码重用技术之一。 对象组合不同于高灵活性的继承,它实现了一个动态可变的委托。而这,也是基于委托原型的基本。 除了动态可变原型,该对象可以为委托聚合对象(创建一个组合作为结果——聚合 ),并进一步发送消息到对象上,委托到该委托上。这可以两个以上的委托,因为它的动态特性决定着它可以在运行时改变。
已经提到的__noSuchMethod__例子是这样,但也让我们展示了如何明确地使用委托:
例如:
复制代码 代码如下: