Можете ли вы наследовать частные функции в JavaScript?
Я использую закрытие для создания объекта с частными и общедоступными методами. Это выглядит так:
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?
Ответы
Ответ 1
Вы хотите, чтобы один экземпляр наследовал частное состояние другого экземпляра? Конечно, вы можете сделать это в JavaScript. Сначала нам нужно определить служебную функцию:
function weakBind(functable, prototype, state) {
return function () {
return functable.apply(this, Object.getPrototypeOf(this) === prototype ?
[state].concat(Array.prototype.slice.call(arguments)) : arguments);
};
}
Теперь мы можем создать наш базовый класс следующим образом:
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;
}());
Теперь вы можете создать собаку следующим образом:
var dog = new Dog;
alert(dog.saySize()); // I am a big dog.
alert(dog.size); // undefined
Мы можем наследовать частное состояние следующим образом:
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;
}());
Теперь вы можете создать чихуахуа следующим образом:
var chi = new Chihuahua;
alert(chi.saySize()); // I am a small dog.
alert(chi.size); // undefined
См. демонстрацию: http://jsfiddle.net/b3Eyn/
Примечание: Я написал этот ответ, чтобы показать, что он может наследовать частное состояние в JavaScript. Однако я бы посоветовал вам не использовать эту схему. Если вы хорошо разработали код, тогда вам не нужно наследовать частное состояние в первую очередь.
Ответ 2
Нет, вы не можете.
Наследование JavaScript основано на прототипе, поэтому вы можете "расширить" только прототипы.
Ответ 3
Конфиденциальность переменных (функций) в JavaScript выполняется через области функций. Вы можете получить к ним доступ извне, только если они экспортированы из области закрытия, другого способа не будет.
Чтобы создать объект, чьи методы имеют доступ к частным функциям, вам просто нужно разместить его в той же области. Является ли объект тем, который наследует от других объектов, совершенно не имеет значения.
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();
Ответ 4
Вид...
Как указывает Берги, доступ определяется областью действия, поэтому, если вы определяете наследника внутри непосредственного родителя, вы можете получить примерно то, что хотите.
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
Ответ 5
Вы можете избежать использования точечной нотации. Но это не совсем личное.
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;
})()