访问js函数内的变量

时间:2012-05-21 00:42:38

标签: javascript

所以我有一个伪类,里面有函数和变量。例如:

function MyClass()
{
    this.a = 0;
    this.b = function(c)
    {
        this.a += c;
    }
}

然后,当我稍后使用它时,我会这样做:

var myObject = new MyClass();
myObject.b(3);
myObject.b(5);

但是当我这样做时:

console.log("A: " + myObject.a);

我明白了:

A: 0

我做错了什么?

这是我的实际代码。它被分成多个文件,但我会提出相关的文件:

function SongDatabase() {

    this.songs = new Array();

    this.loadSongs = function () {

    };

    this.saveSongs = function () {

    };

    var _Constructor_ = function () {
            var mySong = new Song();
            this.songs = new Array(mySong);
        };
    _Constructor_();
}

function LyriX() {
    var songDatabase = new SongDatabase();
    //var playlistDatabase = new PlaylistDatabase();
    songDatabase.loadSongs();
    var sourceList = new ScrollableList();
    sourceList.setElement($S.getElement("sourceList"));
    var accessoryList = new ScrollableList();
    accessoryList.setElement($S.getElement("accessoryList"));

    var sourceListClick = function (index) {
            $S.log("source click: " + index);
            if (index == 0) {
                displaySongs();
            }
        };
    sourceList.setClickListener(sourceListClick);

    var displaySongs = function () {
            $S.log("display songs");
            // STACK OVERFLOW LOOK HERE!!! thanks :)
            // in debug in chrome songDatabase.songs is a zero length array
            accessoryList.loadArray(songDatabase.songs);
        };
}

$S.addOnLoadListener(function () {
    new LyriX();
});

4 个答案:

答案 0 :(得分:2)

一个问题:

> var _Constructor_ = function () {
>    var mySong = new Song();
>    this.songs = new Array(mySong);
> };
> _Constructor_();

在上面,当_Constructor_作为函数调用时,不设置其this值,因此它默认为全局对象(在非严格模式下,或在严格模式下未定义) )。因此songs成为全局变量或在严格模式下抛出错误。

无论如何,这似乎是相当无用的功能,请考虑:

this.songs = [ new mySong() ];

答案 1 :(得分:1)

function MyClass()
{
    this.a = 0;
    this.b = function(c)
    {
        this.a += c;
    }
}

a+=c更改为this.a+=c;

答案 2 :(得分:1)

我看到有人在JavaScript中使用“Java”。 :)

您应该了解的有关JavaScript的一些事情:

  1. 在JavaScript中,数组不像其他语言那样工作。 它们更像是字典,然后你用C或Java称为数组; 它们没有更高的内存效率或更快; 没有预先分配; 在低级实现中没有任何缺陷等。 JavaScript数组只是一个方便(但有用!)的结构 用于保存订单命令数据。

  2. 可以使用new Array(length)表达式创建数组, 或简单的文字表达式[]。 通常,您需要使用数组文字[]

  3. 使用new Array(length)并没有真正做任何有用的事情; 它设置了数组的初始length属性,但基本上就是这样。 所有元素都保持undefined。 没有其他约束或边界检查。 您可以通过调用a[100] = 'whatever'创建的数组var a = new Array(5) 并且口译员不会睁大眼睛。

  4. JavaScript使用的原型继承与明显不同 在C ++和Java等语言中使用的经典继承模型。

  5. 考虑到这些要点,让我们检查以下代码块:

    function SongDatabase() {
        this.songs = new Array();
        this.loadSongs = function () {
            // etc.
        };
    
        this.saveSongs = function () {
            // etc.
        };
    
        var _Constructor_ = function () {
            var mySong = new Song();
            this.songs = new Array(mySong);
        };
        _Constructor_();
    }
    

    这段代码可能没有按照您的想法进行。

    1. 通过初始化SongDatabase函数中的SongDatabase()方法 您正在为songDatabase的每个实例创建新的方法函数。 当你处理几十个实例时,这可能不是什么大问题, 但如果您正在处理数百,则所需的额外内存可能会成为一个问题。 您可以在此处使用prototype模式(请参阅下文)。
    2. 您的_Constructor_功能没有做任何事情。 var mySong = new Song()创建一个新的mySong对象 _Constructor_功能的本地功能和无法在其外部访问。 当_Constructor_调用返回时, 它的mySong变量是垃圾收集的(就像任何其他局部变量一样)。
    3. _Constructor_是私人功能,不是方法; 我不完全确定该上下文中的this将引用什么。 您最终可能会在全局对象上创建一个歌曲属性 (但我想测试一下这一点。)
    4. 正如我之前提到的,当您使用Array()运算符致电new时 它需要一个可选参数来设置数组的初始length。 在这种情况下,解释器会尝试将mySong强制转换为数字 (mySong 添加到数组中!); 如果失败,它将只返回一个带有length = 0的新数组。
    5. 相反,你最好这样写SongDatabase()

      function SongDatabase() {
          this.songs = [];
          // etc.
      }
      
      SongDatabase.prototype.loadSongs = function () {
          // load songs into `this.songs`
      };
      
      SongDatabase.prototype.saveSongs = function () {
          // save songs loaded into `this.songs`
      };
      

      原型模式可能看起来很奇怪, 但它可能是处理您的用例的最佳方式。 您仍然可以直接访问songs数组(可能重要也可能不重要), 并将loadSongssaveSongs函数附加到SongDatabase的原型 确保共享这些功能。

答案 3 :(得分:0)

与其他语言一样,变量不会绑定到“类”。将其视为具有属性的对象。单个a只引用变量“a”(在函数中没有用var声明,所以在这里甚至全局)。您想要更新this对象的属性“a”,而是使用this.adot operator来访问该属性)。您也可以阅读Working with objects


编辑后(您说您一直在使用this.a),它适用于我:http://jsfiddle.net/WKuZe/


在您向我们提供了真实的代码之后,我注意到了这个奇怪的结构:

function SongDatabase() {
    this.songs = new Array();
    // some methods
    var _Constructor_ = function () {
        var mySong = new Song();
        this.songs = new Array(mySong);
    };
    _Constructor_();
}

SongDatabase之类的构造函数(使用new关键字)调用新实例为this。普通函数通常不会被调用,即thisundefined或非严格模式下的全局对象。请参阅documentation for the this keyword on MDN

在这里,首先使用空数组初始化songDatabases'songs属性。然后,在_Constructor_函数中,您创建一个包含一首歌曲的其他数组,但将其分配给window.songs,因为该函数在songDatabase实例上不是called。您的loadSongs()方法可能会出现同样的问题。除了调用和binding之外,为实例对象提供“静态”引用的常用方法是一个范围变量:

function SongDatabase() {
    var that = this; // <== always points to the instance
    // some methods
    function _Constructor_ () {
        var mySong = new Song();
        that.songs = new Array(mySong);
    //  ^^^^
    };
    _Constructor_();
}

如果_Constructor_不是本地函数,但可能是添加接口的全局函数,则可以提供实例(this)作为参数或使用_Constructor_.call(this),这允许使用this关键字就像_Constructor_是“类”一样。