为什么*这个*不是*这*? [英] Why *this* is not *this*?

查看:98
本文介绍了为什么*这个*不是*这*?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚写了这段代码来表示这个杀死我的错误(Grrr!)

I just wrote this piece of code to represent this error that is killing me (Grrr!)

我想知道为什么当我得到错误时:方法未定义我已经在Safari中检查过,而且在parserDidStart()方法中的这个变量不是EpisodeController类型,它的类型为EpisodeFeedParser,为什么会这样?

I wonder why when I get error: method undefined I have checked in Safari and this variable inside parserDidStart() method is not of type EpisodeController it is of type EpisodeFeedParser why is this?

<html>
<head>
<script type="text/javascript">
var EpisodeFeedParser = function(url){
    this.url = url;
    this.didStartCallback = null;
};
EpisodeFeedParser.prototype.parse = function(doc){
    this.didStartCallback(this);
};

var EpisodeController = function(){
    this.episodes = new Array();
    this.parser = null; //lazy
};
EpisodeController.prototype.parserDidStart = function(parser){
    console.log("here *this* is not of type EpisodeController but it is EpisodeFeedParser Why?");
    this.testEpi(); //**********ERROR HERE!***********
};
EpisodeController.prototype.fetchEpisodes = function(urlString){
    if(urlString !== undefined){
        if(parser === undefined){
            var parser = new EpisodeFeedParser(urlString);
            parser.didStartCallback = this.parserDidStart;
            this.parser = parser;
        }
        this.parser.parse();
    }
};
EpisodeController.prototype.testEpi = function(){
console.log("it worked!");
};

function testEpisode(){
    var controller = new EpisodeController();
    controller.fetchEpisodes("myurl");
}
</script>
</head>
<body>
<button type="button" onclick="testEpisode()">press me</button>
</body>
</html> 


推荐答案

这是Javascript经常被误解的方面。 (和this,我的意思是这个

this is a frequently misunderstood aspect of Javascript. (and by "this", I mean this)

你可以想到这个作为另一个无形传递给你的函数的参数。所以当你写一个函数时,

You can think of this as another parameter that gets invisibly passed in to your functions. So when you write a function like,

function add (a,b) {
   return a+b;
}

你真的在写

function add(this, a, b) {
    return a+b;
}

这可能是显而易见的,不明显的是什么被传入,并命名为this。其规则如下。有四种方法可以调用一个函数,它们各自绑定一个不同的东西到这个

That much is probably obvious, what isn't obvious is exactly what gets passed in, and named as "this". The rules for that are as follows. There are four ways to invoke a function, and they each bind a different thing to this.

add(a,b);

是绑定到全局对象。该规则现在普遍被视为一个错误,并且可能在将来的版本中设置为null。

in the classic function call, this is bound to the global object. That rule is now universally seen as a mistake, and will probably be set to null in future versions.

new add(a,b);

在构造函数调用中,已设置到一个新的新对象,其内部(和不可访问的)原型指针设置为add.prototype

in the constructor invocation, this is set to a fresh new object whose internal (and inaccessible) prototype pointer is set to add.prototype

someobject.add(a,b);

在方法调用中,设置某个人。无论你最初定义添加的位置,它是在构造函数内部,特定对象的原型的一部分,还是其他什么都没关系。如果以这种方式调用函数,将设置为您调用它的任何对象。这是你违反的规则。

in the method invocation, this gets set to someobject. it doesn't matter where you originally defined add, whether it was inside a constructor, part of a particular object's prototype, or whatever. If you invoke a function in this way, this is set to whatever object you called it on. This is the rule you are running afoul of.

 add.call(someobject,a,b);

在呼叫/应用调用中,设置为传入调用方法的当前可见第一个参数的任何内容。

in the call/apply invocation, this is set to whatever you pass in to the now visible first parameter of the call method.

代码中发生的事情是:

 this.parser.didStartCallback = this.parserDidStart;

当你编写parserDidStart时期望它的这个这个从EpisodeController更改为this.parser。 特定代码行中没有发生这种情况。直到此处才开始实际切换:

while you wrote parserDidStart with the expectation that its this would be an EpisodeController when you method invoke it... what actually happens is you're now changing its this from the EpisodeController to this.parser. That's not happening in that particular line of code. The switch doesn't physically happen until here:

this.didStartCallback(this);

其中此实例中的此是EpisodeParser ,并且在运行此代码时,您已将parserDidStart命名为didStartCallback。当你在这里调用didStartCallback时,使用这段代码,你实际上是在说......

where this in this instance is the EpisodeParser, and by the time this code is run, you've asigned parserDidStart to be named didStartCallback. When you call didStartCallback here, with this code, you're essentially saying...

didStartCallback.call(this,this);

didStartCallback.call(this,this);

通过说这个.didStartCallback(),你将它的这个设置为..那么...... 这个当你调用它时。

by saying this.didStartCallback() ,you're setting its this to.. well.. the this when you call it.

你应该知道一个叫做bind的函数,这里解释一下:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

You should be aware of a function called bind, which is explained here: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

Bind从现有函数创建一个新函数,其被固定(绑定)到任何对象你明确传入。

Bind creates a new function from an existing function, whose this is fixed (bound) to whatever object you explicitly pass in.

这篇关于为什么*这个*不是*这*?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆