在C ++中,我最熟悉的语言通常是这样声明一个对象:
class foo { public: int bar; int getBar() { return bar; } }
调用getBar()可以正常工作(忽略bar可能未初始化的事实)。其中的变量bar在getBar()class的范围内foo,因此this->bar除非我真的需要明确指出我是在指代类bar而不是参数,否则我不需要说。
getBar()
bar
foo
this->bar
现在,我正在尝试开始使用Java OOP。因此,我查找了如何定义类并尝试相同的事情:
function foo() { this.bar = 0; this.getBar = function() { return bar; } }
它给了我bar isundefined。更改bar为this.bar可解决此问题,但是对每个变量执行此操作会使我的代码混乱很多。每个变量都需要吗?由于我找不到与此相关的任何问题,这使我感到自己在做一些根本错误的事情。
bar isundefined
this.bar
编辑:对了,因此,从注释中我得到的是,this.bar对象的属性,引用的内容与bar局部变量不同。有人可以说出范围和对象方面的确切原因,以及是否有另一种方法来定义不需要此对象的对象吗?
JavaScript有没有 类 基于类的对象模型。它使用强大的原型继承,可以模仿类,但不太适合。一切都是对象,对象[可以]从其他对象继承。
构造函数只是一个将属性分配给新创建的对象的函数。可以通过关键字(在函数本地)引用对象(通过使用new关键字的调用创建)。this
new
this
方法也只是在对象上调用的函数- 再次this指向该对象。至少当使用成员运算符(点,括号)将该函数作为对象的属性调用时。这给新手带来了很多困惑,因为如果您传递该函数(例如,传递给事件侦听器),则该函数与访问该对象的对象“分离”。
现在继承在哪里?“类”的实例继承自相同的原型对象。方法被定义为该对象上的函数属性(而不是每个实例的一个函数),调用它们的实例只是继承该属性。
例:
function Foo() { this.bar = "foo"; // creating a property on the instance } Foo.prototype.foo = 0; // of course you also can define other values to inherit Foo.prototype.getBar = function() { // quite useless return this.bar; } var foo = new Foo; // creates an object which inherits from Foo.prototype, // applies the Foo constructor on it and assigns it to the var foo.getBar(); // "foo" - the inherited function is applied on the object and // returns its "bar" property foo.bar; // "foo" - we could have done this easier. foo[foo.bar]; // 0 - access the "foo" property, which is inherited foo.foo = 1; // and now overwrite it by creating an own property of foo foo[foo.getBar()]; // 1 - gets the overwritten property value. Notice that (new Foo).foo; // is still 0
因此,我们仅使用该对象的属性并对它感到满意。但是所有这些都是“公开的”,并且可以被覆盖/更改/删除!如果那没关系,那么您很幸运。您可以通过在属性名称前加下划线来表示属性的“私有性”,但这只是对其他开发人员的提示,可能不会被遵守(特别是错误的)。
因此,聪明的人找到了一种使用构造函数作为闭包的解决方案,从而允许创建私有的“属性”。javascript函数的每次执行都会为局部变量创建一个新的变量环境,执行完成后可能会收集垃圾。在该范围内声明的每个函数也都可以访问这些变量,并且只要可以调用这些函数(例如,通过事件侦听器),环境就必须持久。因此,通过从构造 函数中导出本地定义的函数,您可以使用只能由这些函数访问的局部变量来保留该变量环境。
让我们来看看它的作用:
function Foo() { var bar = "foo"; // a local variable this.getBar = function getter() { return bar; // accesses the local variable }; // the assignment to a property makes it available to outside } var foo = new Foo; // an object with one method, inheriting from a [currently] empty prototype foo.getBar(); // "foo" - receives us the value of the "bar" variable in the constructor
现在,在构造函数内部定义的此getter函数称为“ _特权 方法”,因为它可以访问“私有”(本地)“属性”(变量)。的价值bar永远不会改变。当然,您也可以为其声明一个setter函数,并可以添加一些验证等。
注意,原型对象上的方法无权访问构造函数的局部变量,但它们可能使用特权方法。让我们添加一个:
Foo.prototype.getFooBar = function() { return this.getBar() + "bar"; // access the "getBar" function on "this" instance } // the inheritance is dynamic, so we can use it on our existing foo object foo.getFooBar(); // "foobar" - concatenated the "bar" value with a custom suffix
因此,您可以将两种方法结合起来。请注意,特权方法需要更多的内存,因为您创建具有不同作用域链(但代码相同)的不同功能对象。如果要创建大量实例,则应仅在原型上定义方法。
当您设置从一个“类”到另一个“类”的继承时,它会变得更加复杂-基本上,您必须使子原型对象从父类继承,并将父构造函数应用于子实例以创建“私有属性” ”。