理解JavaScript OOP

时间:2012-05-23 03:18:39

标签: javascript oop

好吧,这是我第一次使用javaScript进行第一次课程,我已经研究过几个月来使用JQuery,所以我的教学并不是很难。在这段代码中,我会问很多问题..

好的,这是我第一个javascript类的代码

window.myclass = function(){
    this.n1 = 0;
    this.n2 = 0;
    this.ans = 0;
    this.hehe = 0;

    this.defaultNumbersAdd = function(){

       this.hehe =setInterval(function(){
          //just an example of inert function...
          //the truth is i can't grab the this.n1 and this.n2...
          this.ans = this.n1 + this.n2;
       },100);
       clearTimeout(this.hehe);
    };

    this.returnAns = function(){
       return this.ans;
    };

    this.getAnswer = function(){
        this.defaultNumbersAdd(); //i want to reuse this function but I can't access it
        return this.returnAns(); //and also this one
    };

    this.modifynumbers = function(n1,n2){
        this.n1 = n1;
        this.n2 = n2;
    };
};

var myclassins = new window.myclass();
alert(myclassins.getAnswer);

现在我的问题是

1)我如何获取要在我的函数中使用的类变量(this.vars)

2)我如何在另一个函数中使用其他函数

注意:对不起,如果我的解释有点模糊......

5 个答案:

答案 0 :(得分:4)

直接位于window.myclass对象内部的this指针指向该对象本身,并且您正在使用它来定义该对象的基本属性,例如n1和n2。

但是,在对象中定义的函数内,this指针指的是函数,而不是对象。 ***但是,在setTimeouts和setIntervals中,“this”关键字引用窗口对象或全局范围。 (例如,请参阅底部的更新。)

因此,您可以直接使用您用于实例化类的全局范围中的变量名称直接访问属性,

    this.returnAns = function(){
       return myclassins.ans;
    };

但是,上面的方法将您的类与实例化时给予对象的名称联系起来,并且仅对单个对象有用。

更好的解决方案是在对象中定义变量并使用它引用“this”指针:

window.myclass = function(){
    this.n1 = 0;
    this.n2 = 0;
    this.ans = 0;
    this.hehe = 0;
    var _self = this;   // reference to "this"

    this.defaultNumbersAdd = function(){

       myclass.hehe =setInterval(function(){
          //just an example of inert function...
              //the truth is i can't grab the this.n1 and this.n2...
          _self.ans = _self.n1 + _self.n2;
          console.log(_self.ans);
       },100);
       clearTimeout(_self.hehe);
    };

    this.returnAns = function(){
       return _self.ans;
    };

    this.getAnswer = function(){
        this.defaultNumbersAdd(); //i want to reuse this function but I can't access it
        return _self.returnAns(); //and also this one
    };

    this.modifynumbers = function(n1,n2){
        _self.n1 = n1;
        _self.n2 = n2;
    };
};

最后,另一种技术是使用闭包定义函数,将“this”指针传入一个返回另一个函数的函数,如下所示:

    this.modifynumbers = (function(__this) {
        return function(n1,n2){
            __this.n1 = n1;
            __this.n2 = n2;
        }
    })(this);

最简单的方法当然是使用var self;但是,在JavaScript中有几种不同的方法来完成任务,这些技术在不同的场景中可以证明是有用的。

<强>更新

@apsillers指出,当在setTimeout和setInterval函数调用的回调内部引用时,“this”关键字指向窗口对象。这是一个例子:

// top level scope
var global = "globalvalue";

window.demo = function() {
    this.somevar = "somevalue";        

    this.someFunct = function() {
        console.info("somevar = " + this.somevar);  // prints "somevalue"
        console.info("global = " + this.global);   // prints undefined! this points to "demo"!

        setTimeout( function() {
            console.info("timeout - somevar = " + this.somevar);  // undefined! references the "window" context
            console.info("timeout - global = " + this.global);   // prints "globalvalue"
        },1000);
    };
};
var dem = new demo();

dem.somevar;   // accessible from outside the object. prints "somevalue"
dem.someFunct();

someFunct()的输出:

# inside method of object
somevar = somevalue
global = undefined

# inside timeout
timeout - somevar = undefined
timeout - global = globalvalue

正如您所看到的,在setTimeout内部,“this”明确指向窗口或全局范围! (注意:您实际上可以使用该小代码段并在Chrome或Firebug调试器中运行它。)

答案 1 :(得分:3)

您可以使用this article中描述的模块模式。使用它的好处是你可以拥有私有变量,并且只暴露那些你想要公开的变量。

var Myclass = (function(){

    var

    // Private
    n1 = 0,
    n2 = 0,
    ans = 0,
    hehe = 0,

    defaultNumbersAdd = function(){
       hehe = setInterval(function(){
          this.ans = this.n1 + this.n2;
       },100);
       clearTimeout(hehe);
    },

    returnAns = function(){
       return ans;
    },

    getAnswer = function(){
        this.defaultNumbersAdd();
        return returnAns()    
    },

    modifynumbers = function(n1 ,n2){
        n1 = n1;
        n2 = n2;
    };

    // Public
    return {
      defaultNumbersAdd: defaultNumbersAdd,
      getAnswer: getAnswer,
      modifynumbers: modifynumbers
    };
}());

// Then you can use the object as it already exists
myclass.method();

答案 2 :(得分:2)

我认为您对'this'关键字感到困惑。

'this'指的是当前的对象上下文。使用setInterval,您可以将函数传递到另一个上下文,其中this表示其他内容。因此,您可以将this分配给传递当前所引用对象的变量,也可以将defaultNumbers.add内部属性分配给变量:

this.defaultNumbersAdd = function(){
   var ans = this.ans,
   n1 = this.n1,
   n2 = this.n2;

   this.hehe =setInterval(function(){
      //just an example of inert function...
      //the truth is i can't grab the this.n1 and this.n2...
      ans = n1 + n2;
   },100);
   clearTimeout(this.hehe);
};

答案 3 :(得分:1)

我通常会为此声明一个新变量:

window.myclass = function(){
....
....

var self = this
....
....
}

现在你可以打电话给自己了。 .....你想要什么

答案 4 :(得分:1)

第1点:如果您想要来自对象的所有成员变量,请使用for(.. in ..)

// output all keys and values
for(key in myclassins) {
    console.log(key, myclassins[key]);
}

请注意,函数是JavaScript中的第一类变量,因此如果您只想枚举myclassins的非函数成员变量,请执行:

// output all keys and values that are not functions
for(key in myclassins) {
    if(!myclassins[key] instanceof Function) {
        console.log(key, myclassins[key]);
    }
}

第2点:在JavaScript中,this变量称为函数的 context 。上下文可能会更改 - 例如,当您调用setInterval时,它会导致匿名函数以this == window的上下文而不是当前对象的上下文运行。如果要引用当前对象的上下文,请将其存储在构造函数开头的另一个变量中,如var self = this;,然后在匿名self函数中引用setInterval当你想引用这个对象时。

这是因为JavaScript支持闭包,这意味着当您定义一个函数时,该新函数可以访问当前作用域中当前存在的所有变量,包括(在本例中){ {1}}。

备注

  • JavaScript是prototype-based, not class-based。理解它可能是一个困难的区别,而不是与您的确切代码有任何关系的区分。但是,如果您说“JavaScript类”,您可能会发现有人纠正您。

  • 初始化CamelCase是传统的类型名称,例如,实例self的类型为fooBar(不是FullTimeEmployeefullTimeEmployee)。< / p>