我是javascript的新手,我花了一些时间尝试在js中创建命名空间对象。
现在,这就是我想要做的:
MainObject = function() {
var privateVariable = "i'm private";
var privateMethod = function() {
// doSomething
}
this.publicMethod = function() {
// doPublicSomething
}
}
MainObject.prototype.nested = function() {
this.publicNestedMethod = function() {
// that's not working at all
this.privateMethod(privateVariable);
}
}
MyObject = new MainObject();
MyObject.publicMethod();
MyObject.publicNestedMethod();
我试图在第一个中包含嵌套类,但如果我尝试它也不起作用:
this.nested = function() {
var mainObject = this;
return {
publicNestedMethod = function() {
mainObject.privateMethod();
}
}
}();
有人可以帮帮我吗?我会对此失去理智。
淮德拉。
闭包是一个词法特征,而不是语义特征。如果对象在另一个的词法范围之外,它就不能再“嵌套”并访问前者的局部变量。在嵌套函数/类的代码中,没有this.privateMethod
这样的东西,因为privateMethod
永远不会成为MainObject
的属性。它只是函数内的局部变量。
JavaScript中没有“私有属性”,“私有方法”或“私有成员”之类的东西。天哪,没有“阶级”这样的东西。有些人喜欢使用如上所述的局部变量来模拟私有成员,但这样做会导致这样的情况,两个概念之间的差异就会出现并在后面咬一个。
总而言之,用JS中的所有OO技术编写Java代码是一个坏主意,就像用C#编写C代码及其所有指针和无界缓冲区一样。当然,在这两种情况下你都可以做到,但你不会以这种方式欣赏和利用语言的功能。
现在我已经完成了咆哮,你可以做这样的事情来获得“命名空间”功能:
MainObject = function() {
var privateVariable = "I'm private";
var privateMethod = function() {
alert('Private');
}
this.publicMethod = function() {
alert('Public');
}
this.nested = {
publicNestedMethod: function() {
privateMethod();
}
};
// or
this.nested = (function() {
var nestedPrivate = 5;
return {
publicNestedMethod: function() {
alert(nestedPrivate);
privateMethod();
}
};
})();
}
MyObject = new MainObject();
MyObject.publicMethod();
MyObject.nested.publicNestedMethod();
对“私人”方法使用下划线约定是保持组织有序的合理方法。
MainObject = function() {
this._privateVariable = "i'm private";
this._privateMethod = function() {
// doSomething
}
this.publicMethod = function() {
// doPublicSomething
}
}
那么提供原型继承的好处,其中所有“子类”在原型中共享方法的单个实例,但是为了提供继承私有实例的功能......我想出了:
function Person(name,latentPower){
var privatesForChildren = { password:"xyz"
,latentPower:"invisibility"}
this.inherit = function(){
for(v in privatesForChildren){
eval("var " + v + "=privatesForChildren['" + v + "'];");
}
}
this.name = name;
this.revealName = function(){ alert("My name is" + this.name + "."); }
this.revealPowers = function(){ alert("I'm normal."); }
}
function Mutant(name,latentPower,fuel){
this.inherit.call(this); // Inherit private instance variables
var fuel = fuel;
this.name = name;
this.revealPowers = function(){
alert("I manifest the powers of " + latentPower + " when I " + fuel + ".");
}
}
Mutant.prototype = new Person;
Mutant.prototype.constructor = Mutant;
bob = new Person("Bob","telekenesis");
jim = new Mutant("Jim","nausea","eat pizza");
buford = new Mutant("Buford","Teflon Man","breathe");
jim.revealName(); //Inherited properly from prototype
bob.revealPowers();
jim.revealPowers();
buford.revealPowers(); //distinct from Jim's so is an "instance var"
alert(bob.latentPower); //returns undefined
alert(buford.latentPower); //returns undefined, so is "private".
这有用吗?
根据ES6,您可以使用JavaScript类和继承来完成您的需要。
ECMAScript 2015中引入的JavaScript类主要是基于JavaScript现有基于原型的继承的语法糖。
参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
我将使用变量显示以下示例,但它也可以应用于函数。
此解决方案只能与您的私有变量的getter一起使用,否则您的子类将无法访问它们。
class Main {
constructor() {
let privateVariable = "private";
this.publicVariable = "public";
this.getPrivateVariable = () => {
return privateVariable;
}
}
}
Main.Sub = class Sub extends Main {
getAllVariables() {
return this.publicVariable + "-" + this.getPrivateVariable();
}
}
// Testing...
let main = new Main();
let sub = new Main.Sub();
console.log(main.privateVariable); // undefined
console.log(main.publicVariable); // "public"
console.log(sub.privateVariable); // undefined
console.log(sub.publicVariable); // "public"
console.log(main.getPrivateVariable()); // "private"
console.log(sub.getPrivateVariable()); // "private"
console.log(sub.getAllVariables()) // "public-private"
也许这个解决方案对你更好,因为它不会在Main和Nested类之外公开你的私有变量。
class Main {
constructor() {
let privateVariable = "private";
this.publicVariable = "public";
Main.Nested = class Nested extends Main {
getAllVariables() {
return this.publicVariable + "-" + privateVariable;
}
}
}
}
// Testing...
let main = new Main();
let nested = new Main.Nested();
console.log(main.privateVariable); // undefined
console.log(main.publicVariable); // "public"
console.log(nested.privateVariable); // undefined
console.log(nested.publicVariable); // "public"
console.log(main.getPrivateVariable); // undefined
console.log(nested.getPrivateVariable); // undefined
console.log(nested.getAllVariables()) // "public-private"
什么OO系统允许您继承私有方法?私有的一部分是其他对象无法访问的。
特别是在JS中,“私有成员”实际上只是声明它们的函数的局部变量。 JS没有“类”,“继承”,“公共”和“私有”的典型OO概念,因此您不能指望从其他OOP语言逐字复制您的OOP技术。
这是一个惯例。您可以模仿私有成员之类的OO Java技术,但不建议这样做。你可以这样模仿:
MyFunction = function(options){
var private = {};
//to reference MyFunction as a context
var that = this;
function privateFunctionThatCallPublicMethod(){
that.publicFunction("hello");
}
this.publicFunction = function(params){
alert(params + " " + private);
}
...
}
var instance = new MyFunction({oneOption:'fsdfsad'});
这是我发现仿效OO Java技术的最佳方法......
但是有一个问题,效率很低......你必须使用原型,否则它会为每个“类”实例的每个函数创建一个对象。
MyFunction = function(options){
this._private = {};
}
MyFunction.prototype._privateFunctionThatCallPublicMethod = function(){
this.publicFunction("hello");
}
MyFunction.prototype.publicFunction = function(params){
alert(params + " " + this._private);
}
就像你认为私人成员(以这种方式)是一种惯例。还有,你必须知道另一件事......
将对象的函数作为参数传递给另一个函数时,必须绑定函数的上下文...
function bind(fnThis, fn) {
return function(){
return fn.apply(fnThis, arguments);
};
}
function makeSomething(callback){
callback("hello");
}
var instance = new MyFunction();
makeSomething(bind(instance, instance.publicFunction));
这是因为你必须将“this”作为实例绑定在publicFunction的主体中,否则将成为“窗口”。