Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/406.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript:我是否需要为对象中的每个变量设置this.var? 在C++中,我最喜欢的语言,通常声明一个这样的对象: class foo { public: int bar; int getBar() { return bar; } }_Javascript_Scope_This - Fatal编程技术网

Javascript:我是否需要为对象中的每个变量设置this.var? 在C++中,我最喜欢的语言,通常声明一个这样的对象: class foo { public: int bar; int getBar() { return bar; } }

Javascript:我是否需要为对象中的每个变量设置this.var? 在C++中,我最喜欢的语言,通常声明一个这样的对象: class foo { public: int bar; int getBar() { return bar; } },javascript,scope,this,Javascript,Scope,This,调用getBar()工作正常(忽略bar可能未初始化的事实)。getBar()中的变量bar在类foo的范围内,所以我不需要说this->bar,除非我真的需要明确我指的是类“bar,而不是,比如说,一个参数 现在,我正试图开始使用Javascript中的OOP。因此,我研究了如何定义类,并尝试了同样的方法: function foo() { this.bar = 0; this.getBar = function() { return bar; } } 它给我的条是未定义

调用
getBar()
工作正常(忽略
bar
可能未初始化的事实)。
getBar()
中的变量
bar
在类
foo
的范围内,所以我不需要说
this->bar
,除非我真的需要明确我指的是类“
bar
,而不是,比如说,一个参数

现在,我正试图开始使用Javascript中的OOP。因此,我研究了如何定义类,并尝试了同样的方法:

function foo()
{
     this.bar = 0;
     this.getBar = function() { return bar; }
}
它给我的
条是未定义的
。将
bar
更改为
this.bar
可以解决此问题,但对每个变量执行此操作会使我的代码非常混乱。这对每个变量都是必要的吗?因为我找不到任何与此相关的问题,这让我觉得我在做一些根本错误的事情


编辑:是的,从评论中我得到的是,
this.bar
,一个对象的属性,引用了一些不同于
bar
,一个局部变量的东西。有人能解释一下,在范围和对象方面,这到底是为什么吗?如果有另一种方法来定义一个不需要的对象,JavaScript没有基于类的对象模型。它使用了更强大的原型继承,它可以模仿类,但并不适合。一切都是对象,对象[可以]从其他对象继承

构造函数只是为新创建的对象分配属性的函数。对象(通过调用创建)可以通过(函数的本地)引用

方法也只是一个在对象上调用的函数,同样是
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函数,然后添加一些验证等

请注意,prototype对象上的方法无权访问构造函数的局部变量,但它们可能使用特权方法。让我们添加一个:

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中的OOP,您可能需要看一看模块设计模式(例如,描述)

基于闭包效应,此模式允许模拟对象中的私有属性

对于“private”属性,您可以通过其标识符直接引用它们(即,构造函数中的no
this
关键字)


但是无论如何,JS中的闭包和设计模式是一个高级主题。因此,要熟悉基础知识(也在前面提到的书中进行了解释)。

在javascript
中,此
始终指函数的所有者对象。例如,如果在页面中定义函数
foo()
,则所有者是javascript对象
windows
;或者,如果在html元素
上定义
foo()
,则所有者是html元素主体;同样,如果您定义了元素的onclick函数,那么所有者就是锚

在本例中,您在开始时将属性
bar
分配给“owner”对象,并尝试返回局部变量
bar

由于您从未定义过任何局部变量BE
bar
,因此当bar未定义时,它将为您提供帮助

理想情况下,您的代码应该将变量定义为
var bar如果要返回值零。

明确表示function Person(name) { this.name = name; console.log(this); //Developer {language: "js", name: "foo"} if called by Developer } function Developer(name, language) { this.language = language; Person.call(this, name); } var dev = new Developer('foo', 'js');
function foo() {
    var bar = 'foobar';
    this.getBar = function () {
        return bar;
    }
}

var f = new foo();
console.log(f.getBar());  //'foobar'
function foo() {
    bar = 'foobar';
    this.getBar = function () {
        return bar;
    }
}

var f = new foo();
console.log(window.bar);  //'foobar'
function ShoppingCart() {
    var items = [];

    this.getPrice = function () {
       var total = 0;
       for (var i = 0; i < items.length; i += 1) {
          total += items[i].price;
       }
       return total;
    }

    this.addItem = function (item) {
        items.push(item);
    }

    this.checkOut = function () {
        var serializedItems = JSON.strigify(items);
        //send request to the server...
    }
}

var cart = new ShoppingCart();
cart.addItem({ price: 10, type: 'T-shirt' });
cart.addItem({ price: 20, type: 'Pants' });
console.log(cart.getPrice()); //30
var module = (function {

    var privateProperty = 42;

    function privateMethod() {
        console.log('I\'m private');
    }
    return {

       publicMethod: function () {
           console.log('I\'m public!');
           console.log('I\'ll call a private method!');
           privateMethod();
       },

       publicProperty: 1.68,

       getPrivateProperty: function () {
           return privateProperty;
       },

       usePublicProperty: function () {
           console.log('I\'ll get a public property...' + this.publicProperty);
       }

    }
}());

module.privateMethod(); //TypeError
module.publicProperty(); //1.68
module.usePublicProperty(); //I'll get a public property...1.68
module.getPrivateProperty(); //42
module.publicMethod(); 
/*
 * I'm public!
 * I'll call a private method!
 * I'm private
 */
function Foo() {
  this.bar = 0;
  this.getBar = function () { return this.bar };
}
var foo = new Foo();
{
    bar: 0,
    getBar: function () { return this.bar; }
};
var foo = {
    bar: 0,
    getBar: function () { return this.bar; }
};
function Foo( bar, bob ) {
   this.bar = bar;
   this.bob = bob;
}

Foo.prototype.calculate = function () {
  // 'this' points not to the 'prototype' object 
  // as you could've expect, but to the objects
  // created by calling Foo with the new keyword.
  // This is what makes it work.
  return this.bar - this.bob;  
};

var foo1 = new Foo(9, 5);
var foo2 = new Foo(13, 3);
var result1 = foo1.calculate();
var result2 = foo2.calculate();

console.log(result1); //logs 4
console.log(result2); //logs 10
var x = {}; 
x.hello = function(){
    var k = 'Hello World'; 
   this.m = 'Hello JavaScript'; 
}

var t = new x.hello(); 
console.log(t.k); //undefined
console.log(t.m); //Hello JavaScript