Javascript:我需要为对象中的每个变量放置 this.var 吗?

2024-01-02

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

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

Calling getBar()工作正常(忽略这一事实bar可能未初始化)。变量bar within getBar()是在类的范围内foo,所以我不需要说this->bar除非我真的需要明确表示我指的是班级”bar而不是参数。

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

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

它给了我bar is undefined。改变bar to this.bar解决了这个问题,但是对每个变量都这样做会使我的代码变得相当混乱。这对于每个变量都是必要的吗?由于我找不到与此相关的任何问题,这让我觉得我在做一些根本错误的事情。


编辑:是的,所以,从评论中我得到的是this.bar,对象的属性,引用不同于bar,局部变量。有人可以从范围和对象方面确切地说出为什么会这样,以及是否有另一种方法来定义不需要的对象?


JavaScript has no classes class-based object model. It uses the mightier prototypical inheritance, which can mimic classes, but is not suited well for it. Everything is an object, and objects [can] inherit from other objects.

构造函数只是一个为新创建的对象分配属性的函数。该对象(通过调用创建new keyword https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/new)可以通过this keyword https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this(这是函数的局部)。

方法也只是一个被调用的函数on一个物体 - 再次与this指向该物体。至少当该函数作为对象的属性调用时,使用会员经营者 https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Member_Operators(点、括号)。这会给新手带来很多困惑,因为如果您传递该函数(例如传递给事件侦听器),它就会与访问它的对象“分离”。

现在遗产在哪里? “类”的实例继承自同一原型对象。方法被定义为该对象上的函数属性(而不是每个实例一个函数),您调用它们的实例仅继承该属性。

Example:

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

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

当您设置从一个“类”到另一个“类”的继承时,它会变得更加复杂 - 基本上,您必须使子原型对象从父类继承,并将父构造函数应用于子实例以创建“私有属性” ”。看一下正确的 javascript 继承 https://stackoverflow.com/q/10898786/1048572, 继承原型中的私有变量 https://stackoverflow.com/q/3617139/1048572, 在 JAVASCRIPT 模块模式中定义私有字段成员和继承 https://stackoverflow.com/q/12463040/1048572 and JS Revealing原型模式如何实现继承? https://stackoverflow.com/q/9248655/1048572

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Javascript:我需要为对象中的每个变量放置 this.var 吗? 的相关文章

随机推荐

  • 是否可以在 pdf 中向使用 R knit::kable 生成的表格添加垂直线?

    我想制作一张桌子knitr kable边界上和某些列之间有垂直线 有办法做到吗 我的输出文档是pdf Thanks 不太清楚 但也许这可以帮助 library knitr library kableExtra library dplyr d
  • 如何关闭笔记本中的初始化单元?

    在我的笔记本中 我有一个相当大的初始化单元 如何使其可关闭 我的意思是我怎样才能将这个单元格卷成一行并能够将其展开呢 经典的解决方案是将初始化单元放入其自己的部分 Alt 4 标题为 初始化 此部分位于笔记本的开头或结尾 要隐藏内容 请关闭
  • JDialog 让主应用程序失去焦点

    我想知道为什么我的 JDialog 将我的主应用程序推入后台 这意味着 如果显示 JDialog 并且用户单击 确定 或 取消 则主应用程序将失去焦点并将被推入后台 经过调查 我发现 只有当我在显示 JDialog 时禁用主框架时 才会发生
  • 我的 Apache CXF 客户端出现问题

    我正在尝试编写一个 Apache CXF JAX WS 客户端 我的依赖项pom xml are
  • 如何禁用 html5 canvas 元素的选择

    我监听 html5 画布内的点击事件 它工作得很好 但是 当我单击图像上的任意位置时 浏览器会突出显示该图像 就好像它已被选中一样 类似于在页面上单击时图像可能会突出显示的方式 我很好奇是否有人知道如何禁用选择 html 元素 例如画布 我
  • 在多个转换中保持键控状态

    我有一个流 我想使用某个键对其进行分区 然后运行多个转换 每个转换使用一个状态 当我打电话时keyBy 我得到一个KeyedStream下一个转换可以正确访问分区状态 但之后链接的另一个转换在尝试访问分区状态时会出现异常 例外的是 状态密钥
  • 如何针对集合调用 Expression>

    我有一个从存储库模式定义存储库的接口 interface IRepository List
  • dplyr 根据向量中的名称改变多列

    我想使用以下方法将两列相乘dplyr s mutate功能 但是我不想为每个变异条件编写一个新行 而是想使用存储在向量中的列的名称var1 and var2 例如 最后我想在现有的bankdata与名字result1其中包含现金列和贷款列相
  • Flash Builder 4.6 - 代码隐藏方法

    我正在尝试找出使用 Flash 构建器用于移动应用程序的 代码隐藏 的正确方法 我正在创建一个 Flex 移动 AIR 项目 基于 选项卡式视图 模板 将我的 UI 设置为设计模式 现在我希望所有逻辑都位于一个单独的类中 该类将相应地改变
  • 我可以假设 C stdlib 函数不使用 errno 吗?

    我正在看一段 C 代码 它的意思是 void printerror char message printf There was an error s n message switch errno do stuff depending on
  • 使用 SolrJ 和 Solr4 进行分面

    我已经浏览过该网站上的相关问题 但尚未找到相关的解决方案 使用以下形式的 HTTP 请求查询我的 Solr4 索引时 facet true facet field country 响应包含所有不同的国家以及每个国家的计数 如何使用 Solr
  • 调试期间未命断点

    为什么 NetBeans Android 1 5 中的断点无法触发 你有一个叫做在其他 IDE 中开发 http developer android com guide developing other ide html它告诉你如何在 ec
  • 在 Linux 上哪里安装 GlassFish?

    免责声明 我对 Linux 还比较陌生 我争论过将其放在 SuperUser 或 ServerFault 上 因为答案does需要将 Linux 作为一个系统进行解释 而不是特定的编程问题 但是我从 Java 开发人员的角度对此感兴趣 并且
  • 如何在 Node.js 中设置 http.createClient 的超时?

    有一个帖子 如何在node js中设置客户端http连接的超时 https stackoverflow com questions 3586760 how do i set a timeout for client http connect
  • 如何获取组中对象的画布相对位置?

    通常一个对象相对于画布的位置可以从它的 left and top属性 但如果对象位于选择 组中 则这些属性将与组相关 有没有办法获得它们相对于画布的位置 当对象位于组内时 其相对于画布的坐标将取决于组的原点 以及对象的原点 假设我们有这段代
  • 使用云台信标设备进行室内定位如何提高数据的稳定性和准确性?

    在android中如何提高多个信标检测的稳定性 我正在使用Gimbal信标进行室内定位 蓝色是否适合室内位置数据访问 我在这方面进行了广泛的研究 因为我在充满会议室的走廊中放置了信标 所有会议室都在附近 首先 我建议将信标放置在天花板上 信
  • 如何在sbt中将jar打包到给定目录?

    在 sbt 中 如果我们执行package 将会生成一个jar文件target scala 2 12 XXX jar 但我想把jar文件放在myDirectory XXX jar 我怎样才能做到这一点 The target 默认路径的一部分
  • 使用 maven-shade-plugin 时出现多余的警告

    我在用Maven 阴影插件对于一个简单的 Maven 项目 该插件成功地将所有依赖项包含到最终的 阴影 jar 中 这个过程每次都很顺利 并且生产出的正是我所需要的 当运行 第一次 时 经过一段时间后clean 该插件很安静并且产生很少的输
  • 如何卸载 Laravel Passport

    我决定使用 JWT 并从项目中完全删除 Laravel Passport 我试图从composer remove laravel passport 然而 这并没有什么好处 Symfony Component Debug Exception
  • Javascript:我需要为对象中的每个变量放置 this.var 吗?

    在我最熟悉的 C 语言中 通常声明一个对象如下 class foo public int bar int getBar return bar Calling getBar 工作正常 忽略这一事实bar可能未初始化 变量bar within