功能继承的问题在于,如果你想创建许多实例,那么它会很慢,因为每次都必须声明这些函数。
原型继承的问题在于没有办法真正拥有私有变量。
是否有可能将这两者结合在一起并获得两全其美?以下是我使用原型和单例模式组合的尝试:
var Animal = (function () {
var secret = "My Secret";
var _Animal = function (type) {
this.type = type;
}
_Animal.prototype = {
some_property: 123,
getSecret: function () {
return secret;
}
};
return _Animal;
}());
var cat = new Animal("cat");
cat.some_property; // 123
cat.type; // "cat"
cat.getSecret(); // "My Secret"
使用这种模式有什么缺点吗?安全?效率?是否有类似的模式已存在?
答案 0 :(得分:2)
你的模式很完美。
这里有一些你想要记住的事情 首先,在最外层闭包中创建的函数和变量的行为类似于其他语言中的私有静态方法/成员(除了在语法上实际调用它们之外)。
如果使用原型范例,当然不可能创建私有静态方法/成员 您可以通过将它们附加到内部构造函数,然后将其返回到外部作用域来进一步创建公共静态成员/方法:
var Class = (function () {
var private_static = function () {},
public_static = function () {},
Class = function () {
var private_method = function () { private_static(); };
this.method = function () { private_method(); };
};
Class.static = public_static;
return Class;
}());
Class.static(); // calls `public_static`
var instance = new Class();
instance.method();
// calls instance's `private_method()`, which in turn calls the shared `private_static();`
请记住,如果您打算以这种方式使用“静态”函数,那么他们绝对无法访问实例的内部状态,因此,如果您确实使用它们,则需要传递它们需要的任何东西,你必须收集return语句(或从里面修改对象属性/数组元素)。
此外,从任何实例的内部来看,给定上面的代码,public_static
和Class.static();
都是调用公共函数的完全有效的方法,因为它实际上不是静态的,而只是一个函数一个闭包,它也恰好被添加为另一个对象的属性,该对象也在实例的范围链中。
作为额外奖励:
即使恶意代码DID开始攻击你的公共静态方法(Class.static
),希望劫持你的内部,Class.static
属性的任何更改都不会影响所附的public_static
函数,所以通过调用内部版本,你的实例仍然是黑客安全的,只要让人们远离私人的东西...
如果另一个模块依赖于一个实例,并且该实例的公共方法已被篡改,而另一个模块只是信任它所给予的一切......嗯,该模块的创建者感到羞耻 - 但至少你的东西是安全
Hooray用于复制其他语言的功能,仅使用闭包。
答案 1 :(得分:1)
是否有可能将功能性和原型继承结合在一起并获得两全其美的效果?
是。 And you should do it。您不必将that
初始化为{}
,而是使用Object.create
从一些原型对象继承,其中放置了所有非特权方法。但是,从这样的“类”继承并不简单,即使使用工厂,您很快就会得到看起来更像pseudo-classical approach的代码。
我尝试使用原型和单例模式相结合。是否有类似的模式已存在?
好的,但这与上面有什么不同?实际上,这被称为“揭示原型模式”,是Module Pattern和原型模式的组合。
使用此模式的任何缺点?
不,没关系。仅仅为了你的例子它有点不必要,因为你的secret
是一种静态变量,所以我从实例方法访问它没有多大意义。较短:
function Animal(type) {
this.type = type;
}
Animal.prototype.some_property = 123;
Animal.getSecret = function() {
return "My Secret";
};