'this' 在 JavaScript 类方法中未定义

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4011793/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 07:08:26  来源:igfitidea点击:

'this' is undefined in JavaScript class methods

javascriptclassprototype

提问by Carson Myers

I'm new to JavaScript. New as far as all I've really done with it is tweaked existing code and wrote small bits of jQuery.

我是 JavaScript 的新手。就我真正用它所做的一切而言,新的东西是调整现有代码并编写了少量 jQuery。

Now I'm attempting to write a "class" with attributes and methods, but I'm having trouble with the methods. My code:

现在我正在尝试编写一个带有属性和方法的“类”,但是我在使用这些方法时遇到了问题。我的代码:

function Request(destination, stay_open) {
    this.state = "ready";
    this.xhr = null;
    this.destination = destination;
    this.stay_open = stay_open;

    this.open = function(data) {
        this.xhr = $.ajax({
            url: destination,
            success: this.handle_response,
            error: this.handle_failure,
            timeout: 100000000,
            data: data,
            dataType: 'json',
        });
    };

    /* snip... */

}

Request.prototype.start = function() {
    if( this.stay_open == true ) {
        this.open({msg: 'listen'});
    } else {

    }
};
//all console.log's omitted

The problem is, in Request.prototype.start, thisis undefined and thus the if statement evaluates to false. What am I doing wrong here?

问题是,在Request.prototype.startthis是不确定的,因此,如果语句评估为假。我在这里做错了什么?

采纳答案by Chetan Sastry

How are you calling the start function?

你是如何调用start函数的?

This should work (newis the key)

这应该有效(是关键)

var o = new Request(destination, stay_open);
o.start();

If you directly call it like Request.prototype.start(), thiswill refer to the global context (windowin browsers).

如果直接调用它 like Request.prototype.start()this将引用全局上下文(window在浏览器中)。

Also, if thisis undefined, it results in an error. The if expression does not evaluate to false.

此外,如果this未定义,则会导致错误。if 表达式的计算结果不为 false。

Update: thisobject is not set based on declaration, but by invocation. What it means is that if you assign the function property to a variable like x = o.startand call x(), thisinside start no longer refers to o. This is what happens when you do setTimeout. To make it work, do this instead:

更新this对象不是基于声明设置的,而是通过调用设置的。这意味着如果您将函数属性分配给一个变量,例如x = o.start并调用x(),则this内部 start 不再引用o. 当你这样做时会发生这种情况setTimeout。要使其工作,请执行以下操作:

 var o = new Request(...);
 setTimeout(function() { o.start(); }, 1000);

回答by EliuX

I just wanted to point out that sometimes this error happens because a function has been used as a high order function (passed as an argument) and then the scope of thisgot lost. In such cases, I would recommend passing such function bound to this. E.g.

我只是想指出,有时会发生此错误,因为一个函数已被用作高阶函数(作为参数传递),然后this失去了作用域。在这种情况下,我建议将此类函数绑定到this. 例如

this.myFunction.bind(this);

回答by xj9

JavaScript's OOP is a little funky (or a lot) and it takes some getting used to. This first thing you need to keep in mind is that there are no Classesand thinking in terms of classes can trip you up. And in order to use a method attached to a Constructor (the JavaScript equivalent of a Class definition) you need to instantiate your object. For example:

JavaScript 的 OOP 有点时髦(或很多),需要一些时间来适应。您需要记住的第一件事是没有课程,而在课程方面的思考可能会让您失望。为了使用附加到构造函数的方法(类定义的 JavaScript 等价物),您需要实例化您的对象。例如:

Ninja = function (name) {
    this.name = name;
};
aNinja = new Ninja('foxy');
aNinja.name; //-> 'foxy'

enemyNinja = new Ninja('boggis');
enemyNinja.name; //=> 'boggis'

Note that Ninjainstances have the same properties but aNinjacannot access the properties of enemyNinja. (This part should be really easy/straightforward) Things get a bit different when you start adding stuff to the prototype:

请注意,Ninja实例具有相同的属性,但aNinja无法访问 的属性enemyNinja。(这部分应该非常简单/直接)当您开始向以下内容添加内容时,情况会有所不同prototype

Ninja.prototype.jump = function () {
   return this.name + ' jumped!';
};
Ninja.prototype.jump(); //-> Error.
aNinja.jump(); //-> 'foxy jumped!'
enemyNinja.jump(); //-> 'boggis jumped!'

Calling this directly will throw an error because thisonly points to the correct object (your "Class") when the Constructor is instantiated (otherwise it points to the global object, windowin a browser)

直接调用它会抛出一个错误,因为this当构造函数被实例化时,它只指向正确的对象(你的“类”)(否则它指向全局对象,window在浏览器中)

回答by Nitin

In ES2015 a.k.a ES6, classis a syntactic sugar for functions.

在 ES2015 中,又名 ES6,classfunctions.

If you want to force to set a context for thisyou can use bind()method. As @chetan pointed, on invocation you can set the context as well! Check the example below:

如果您想强制为this您设置上下文,可以使用bind()方法。正如@chetan 所指出的,在调用时您也可以设置上下文!检查下面的例子:

class Form extends React.Component {
constructor() {
    super();
  }
  handleChange(e) {
    switch (e.target.id) {
      case 'owner':
        this.setState({owner: e.target.value});
        break;
      default:
    }
  }
  render() {
    return (
      <form onSubmit={this.handleNewCodeBlock}>
        <p>Owner:</p> <input onChange={this.handleChange.bind(this)} />
      </form>
    );
  }
}

Here we forced the context inside handleChange()to Form.

在这里,我们强制内部的上下文handleChange()Form