我有一个关于 Javascript 对象中的公共(public)变量和私有(private)变量的问题。这是我一直在研究的简单代码,用于了解变量范围以及私有(private)和公共(public)属性。
var fred = new Object01("Fred");
var global = "Spoon!";
function Object01(oName) {
var myName = oName;
this.myName = "I'm not telling!";
var sub = new subObject("underWorld");
this.sub = new subObject("Sewer!");
Object01.prototype.revealName = function() {
return "OK, OK, my name is: " + myName + ", oh and we say " + global;
}
Object01.prototype.revealSecretName = function() {
console.log ("Private: ");
sub.revealName();
console.log("Public: ");
this.sub.revealName();
}
}
function subObject(oName) {
var myName = oName;
this.myName = "My Secret SubName!";
subObject.prototype.revealName = function() {
console.info("My Property Name is: " + this.myName);
console.info("OK, my real name is: " + myName + ", yeah and we also say: " + global);
}
}
到目前为止我观察到的有趣的事情是在我的对象中,一个普通的 var 被视为私有(private)的(显然,因为它们在一个函数 block 中),而一个 this
版本是公共(public)的。但我注意到与 this.xxx
同名的变量似乎被认为是不同的变量。因此,在上面的示例中,与我拉取 var myName
的函数相比,我的对象 fred
将为 this.myName
报告一些不同的内容。
但对于我创建的子对象,这种相同的行为并不相同。在 var sub
与 this.sub
的情况下,上面两个都使用 new subObject
调用来创建两个子对象。但似乎 this.sub
和 var sub
都返回了 Sewer!
版本。
Som 我有点困惑,为什么如果我对 this.myName
和 var myName
使用字符串,我会得到两个不同的结果,但我尝试做同样的事情与另一个对象不会产生类似的结果?我猜可能是我用错了它们,或者没有理解 this
和 var
版本之间的区别。
最佳答案
这里最大的问题实际上不是 this
之间的区别基于对象属性和 var
-声明的变量。
你的问题是你试图让原型(prototype)充当一个包装器,它会给你 protected 类属性,这些属性可供子类使用,更不用说你的主类的实例了。
prototype
不能在 "private"
上工作一个类的成员(即在构造函数范围内定义的变量,而不是添加到您要返回的构造对象的属性)。
function Person (personName) {
var scoped_name = personName;
this.name = "Imposter " + scoped_name;
}
Person.prototype.greet = function () { console.log("Hi, I'm " + this.name + "!"); };
var bob = new Person("Bob");
bob.greet(); // "Hi, I'm Imposter Bob!"
点prototype
string 要么提供对对象的可公开访问属性进行操作的方法(例如,如果您想更改 this.name
的值,但您将永远丢失隐藏的 scoped_name
引用)...
...或者如果您希望所有相同类型的对象都可以访问相同的值。
function Student (name, id) {
function showIDCard () { return id; }
function greet () { console.log("I'm " + name + ", and I attend " + this.school); }
this.showID = showIDCard;
this.greet = greet;
}
Student.prototype.school = "The JS Academy of Hard-Knocks";
Student.prototype.comment_on_school = function (feeling) {
console.log("I " + feeling + " " + this.school);
}
var bob = new Student("Bob", 1);
var doug = new Student("Doug", 2);
var mary = new Student("Mary", 1);
mary.school = "The JS School of Closure";
bob.greet(); // I'm Bob and I attend The JS School of Hard-Knocks
mary.greet(); // I'm Mary and I attend the JS School of Closure
mary.comment_on_school("love"); // I love The JS School of Closure
prototype
为 school
定义了默认值, 对于 Student
没有给自己的人。
prototype
还提供了可以在对象之间共享的功能,因为这些功能使用 this
访问对象的实际属性。
函数的任何内部变量ONLY 可以被INSIDE定义的属性或方法访问函数。
所以在这种情况下,prototype
方法可以NEVER 访问 id
, 除了通过 this.showID
,因为 this.showID
是对 showIDCard
的引用功能,这是为每个学生创建的,每个学生都有自己独特的id
,并且他们自己的该函数副本引用了他们自己的该参数的唯一副本。
我对 JS 应用大规模“类”方法的建议是采用一种有利于对象组合的风格。 如果你要子类化,让每个子类成为一个模块,有它自己的面向公众的接口(interface),和它自己的私有(private)范围的变量,然后让那个模块成为你试图制作的任何东西的属性,而不是而不是试图让继承链发挥作用。
就是说,如果您期望做一些事情,例如从基类继承,然后将其扩展 8 或 10 代,那么 JS 中的工作太多了。 它只会以泪水结束,并提示 JS 不是“OOP”(以您希望的风格)。
关于Javascript OOP 公共(public)和私有(private)变量范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12358440/