Can you inherit private functions in JavaScript?
我正在使用一个闭包用私有和公共方法创建一个对象。看起来像这样-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | var Dog = (function() { function Dog() {} var size = 'big'; var _privateSaySize = function() { return 'I am a ' + size + ' dog.'; } Dog.prototype.publicSaySize = function() { return _privateSaySize(); } return Dog; })(); |
但是现在我想要一个对象,它只有私有函数,并且由另一个对象继承。但这在JavaScript中是可能的吗?
不,你不能。
Javascript继承是基于原型的,所以您只能"扩展"原型中的方法。
javascript中变量(函数)的隐私权是通过函数范围实现的。只有当它们从闭包范围中导出时,才可以从外部访问它们,没有其他方法。
要使方法可以访问私有函数的对象,只需将其放在同一范围内。对象是否是从其他对象继承的对象是完全无关的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | function Dog() {} function Dalmatian() {} Dalmation.prototype = Object.create(Dog.prototype); Dalmation.prototype.size ="big"; function Dackel() {} Dackel.prototype = Object.create(Dog.prototype); Dackel.prototype.size ="small"; (function() { // private function function say(s) { console.log("I'm a"+s+" dog"); } // both accessible from the Dog and Dackel public methods Dog.prototype.saySize = function() { say(this.size ||"normal"); }; Dackel.prototype.saySize = function() { say(this.size +" but loud"); }; })(); new Dog().saySize(); new Dalmatian().saySize(); new Dackel().saySize(); |
号
有点。。。正如Bergi指出的那样,访问是由作用域定义的,所以如果您在父对象的直接对象内定义继承者,您可以大致得到您想要的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | var BarkingDog; var Dog = (function() { function Dog() {} var size = 'big'; var _privateSaySize = function() { return 'I am a ' + size + ' dog.'; }; Dog.prototype.publicSaySize = function() { return _privateSaySize(); }; BarkingDog = (function () { function BarkingDog () {} var say = 'woof'; BarkingDog.prototype = new Dog(); BarkingDog.prototype.bark = function () { return _privateSaySize() + ' ' + say; }; return BarkingDog; })(); return Dog; })(); var myDog = new BarkingDog(); console.log(myDog.bark()); console.log(myDog.publicSaySize()); |
不知道为什么你会想…D
您想让一个实例继承另一个实例的私有状态吗?当然可以用JavaScript实现。首先,我们需要定义一个实用函数:
1 2 3 4 5 6 | function weakBind(functable, prototype, state) { return function () { return functable.apply(this, Object.getPrototypeOf(this) === prototype ? [state].concat(Array.prototype.slice.call(arguments)) : arguments); }; } |
。
现在我们可以创建如下的基类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | var Dog = (function () { function Dog() { if (this instanceof Dog) { // constructor code } else return Object.create(private); } var public = Dog.prototype, private = Object.create(public, { size: { value:"big" } }); public.saySize = weakBind(function (private) { return"I am a" + private.size +" dog."; }, public, private); return Dog; }()); |
现在您可以创建一只狗,如下所示:
1 2 3 | var dog = new Dog; alert(dog.saySize()); // I am a big dog. alert(dog.size); // undefined |
。
我们可以继承私有国家如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | var Chihuahua = (function () { function Chihuahua() { Dog.call(this); } var private = Dog(); Object.defineProperty(private, { size: { value:"small" } }); var public = Chihuahua.prototype = Object.create(Dog.prototype); public.saySize = weakBind(public.saySize, public, private); return Chihuahua; }()); |
。
现在您可以创建一个奇瓦瓦,如下所示:
1 2 3 | var chi = new Chihuahua; alert(chi.saySize()); // I am a small dog. alert(chi.size); // undefined |
参见演示:http://jsfiddle.net/b3eyn/
注意:我写这个答案只是为了证明可以在javascript中继承私有状态。不过,我建议你不要使用这种模式。如果您的代码设计得很好,那么首先就不需要继承私有状态。
你可以避免使用点符号。但这并不是真正的隐私。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | var Dog = (function() { function Dog() {} var size = 'big'; Dog.prototype['-privateSaySize'] = function() { return 'I am a ' + size + ' dog.'; } Dog.prototype.publicSaySize = function() { return this['-privateSaySize'](); } return Dog; })() |