一尘不染

Javascript:是否需要为对象中的每个变量都放置this.var?

javascript

在C ++中,我最熟悉的语言通常是这样声明一个对象:

class foo
{
public:
    int bar;
    int getBar() { return bar; }
}

调用getBar()可以正常工作(忽略bar可能未初始化的事实)。其中的变量bargetBar()class的范围内foo,因此this->bar除非我真的需要明确指出我是在指代类bar而不是参数,否则我不需要说。

现在,我正在尝试开始使用Java OOP。因此,我查找了如何定义类并尝试相同的事情:

function foo()
{
     this.bar = 0;
     this.getBar = function() { return bar; }
}

它给了我bar isundefined。更改barthis.bar可解决此问题,但是对每个变量执行此操作会使我的代码混乱很多。每个变量都需要吗?由于我找不到与此相关的任何问题,这使我感到自己在做一些根本错误的事情。


编辑:对了,因此,从注释中我得到的是,this.bar对象的属性,引用的内容与bar局部变量不同。有人可以说出范围和对象方面的确切原因,以及是否有另一种方法来定义不需要此对象的对象吗?


阅读 270

收藏
2020-04-23

共1个答案

一尘不染

JavaScript有没有 基于类的对象模型。它使用强大的原型继承,可以模仿类,但不太适合。一切都是对象,对象[可以]从其他对象继承。

构造函数只是一个将属性分配给新创建的对象的函数。可以通过关键字(在函数本地)引用对象(通过使用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

因此,您可以将两种方法结合起来。请注意,特权方法需要更多的内存,因为您创建具有不同作用域链(但代码相同)的不同功能对象。如果要创建大量实例,则应仅在原型上定义方法。

当您设置从一个“类”到另一个“类”的继承时,它会变得更加复杂-基本上,您必须使子原型对象从父类继承,并将父构造函数应用于子实例以创建“私有属性”
”。

2020-04-23