微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么* this *不是* this *?

如何解决为什么* this *不是* this *?

| 我只是写了这段代码来代表这个正在杀死我的错误(Grrr!) 我想知道为什么当我收到错误消息:方法未定义我已经在Safari中检查了并且parserDidStart()方法中的此变量不是EpisodeController类型,而是EpisodeFeedParser类型,为什么?
<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经常被误解的方面。 (“ \”代表“ mean1”) 您可以将ѭ1视为另一个参数,该参数会无形地传递给函数。因此,当您编写类似的函数时,
function add (a,b) {
   return a+b;
}
你真的在写
function add(this,a,b) {
    return a+b;
}
那可能很明显,不明显的是传入的东西,并命名为“ this \”。规则如下。调用函数有四种方法,每种方法都将不同的事物绑定到
this
。 经典函数调用
add(a,b);
在经典函数调用中,
this
绑定到全局对象。现在,普遍认为该规则是错误的,将来的版本中可能会将其设置为null。 构造函数调用
new add(a,b);
在构造函数调用中,将``1''设置为一个新的新对象,该对象的内部(且不可访问)原型指针设置为add。 方法调用
someobject.add(a,b);
在方法调用中,将“ 1”设置为某个对象。最初定义add的位置,无论它是在构造函数内部,还是特定对象的原型的一部分,还是其他因素都无所谓。如果您以这种方式调用函数,则将“ 1”设置为调用它的任何对象。这是您违反的规则。 调用/应用调用
 add.call(someobject,b);
在call / apply调用中,将ѭ1设置为您传递给call方法现在可见的第一个参数的任何内容。 您的代码中会发生以下情况:
 this.parser.didStartCallback = this.parserDidStart;
在编写parserDidStart时,期望它的
this
在方法调用时将是EpisodeController……实际上发生的是,您现在正在将其
this
从EpisodeController更改为this.parser。在特定的代码行中不会发生这种情况。直到这里才实际发生切换:
this.didStartCallback(this);
这里的
this
是EpisodeParser,并且在运行此代码时,您已经将parserDidStart分配给了didStartCallback。当您在此处使用此代码调用didStartCallback时,实际上是在说... didStartCallback.call(this,this); 通过说this.didStartCallback(),您可以将其
this
设置为.. well。 您应该意识到一个名为bind的函数,在这里进行解释: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind Bind从现有函数创建一个新函数,该函数的ѭ1固定(绑定)到您显式传递的任何对象。     ,
this
传给
didStartCallback
EpisodeFeedParser.prototype.parse = function(doc){
    this.didStartCallback(this);
属于
EpisodeFeedParser
EpisodeController.prototype.fetchEpisodes
中,您会影响
EpisodeController.parserDidStart
parser.didStartCallback
parser.didStartCallback = this.parserDidStart;
所以
this.didStartCallback(this);
实际上是
EpisodeController.parserDidStart(this)
我们从一开始就看到最后一个
this
的类型为
EpisodeFeedParser
。 Q.E.D     ,尝试:
var that = this;
parser.didStartCallback = function(parser) {
  that.parserDidStart(parser);
};
这将创建一个将正确范围传递到
parserDidStart
的闭包。当前,当您调用
this.parser.parse()
时,它将传递
EpisodeFeedParser
作为上下文,因为它是从那里调用的。这是JavaScript范围的怪癖之一,并且可能令人沮丧。     ,问题在于,在执行过程中,当“ this \”引用EpisodeFeedParser时,正在“ this \”上调用“ didStartCallBack \”。我已经使用.call()修复了该问题,尽管我不确定为什么需要在此回旋处编写代码,但是我确定一定有原因。 重要更改:
parse: function(episodeController){
  this.didStartCallback.call(episodeController,this);
}//parse
完整代码:
<html>
<head>
<script type=\"text/javascript\">
    //An interesting context problem...
    //Why is it of type EpisodeFeedParser?

    // ---- EpisodeFeedParser
    var EpisodeFeedParser = function(url){
        this.url = url;
    };  
    EpisodeFeedParser.prototype = {
        url:null,didStartCallback:null,parse: function(episodeController){
            this.didStartCallback.call(episodeController,this);
        }//parse
    }//prototype


    // ---- EpisodeController
    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?\");
            debugger;
            this.testEpi(); //**********ERROR HERE!***********
        },fetchEpisodes: function(urlString){
            if(urlString !== undefined){
                if(this.parser === null){
                    this.parser = new EpisodeFeedParser(urlString);
                    this.parser.didStartCallback = this.parserDidStart;
                }//if
                this.parser.parse(this);
            }//if
        },//fetchEpisodes

        testEpi: function(){
            console.log(\"it worked!\");
        }
    }//EpisodeController.prototype


    // ---- Global Stuff
    function testEpisode(){
        var controller = new EpisodeController();
        controller.fetchEpisodes(\"myurl\");
    }
</script>
</head>

<body>
<button type=\"button\" onclick=\"testEpisode()\">press me</button>
</body>
</html> 
    ,
EpisodeFeedParser.prototype.parse = function(doc){
    this.didStartCallback(this);
};
我不明白为什么您会期望ѭ1等于26ѭ。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。