Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/433.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
javascript OOP混乱_Javascript - Fatal编程技术网

javascript OOP混乱

javascript OOP混乱,javascript,Javascript,可能重复: 我有一个这样定义的类 function SocialMiner(tabUrl) { var verbose=true; var profileArray=new Array(); this.tabUrl=tabUrl; this.getTabUrl=function(callback) { chrome.tabs.getSelected(null, function(tab) {

可能重复:

我有一个这样定义的类

function SocialMiner(tabUrl) 
{
    var verbose=true;

    var profileArray=new Array();

    this.tabUrl=tabUrl;

    this.getTabUrl=function(callback)
    {
        chrome.tabs.getSelected(null, function(tab)
        {


            callback(tab.url);
        });
    }   

    this.setTabUrlValue=function(pageUrl)
    {
        this.tabUrl=pageUrl;
        console.log("22"+this.tabUrl);   //this statement shows url correctly
    }
}
当我像这样调用这个方法时

 miner.getTabUrl(miner.setTabUrlValue);

   miner.logToConsole("1"+miner.tabUrl);   //This statement returns undefined

回调内部的
console.log
正确输出
url
,但是
miner
ojbect的
tabUrl
属性未定义,如第二个
console.log
中所示。为什么会这样?

我认为发生这种情况是因为闭包变量在函数调用中无法生存。

解决方案是在构造函数中保存对该的引用(稍后可通过闭包获得):

setTabUrlValue
中使用:

that.tabUrl=pageUrl;
我怀疑将方法作为函数(
回调
)运行会失去作用域,即不再知道任何
。换句话说,它在构造函数的范围内运行,而不是作为使用它的实例的方法。函数可以使用构造函数范围中引用
this
的变量,并且
在实例创建时指向右侧
this

您还可以强制
回调
在当前实例范围内运行,如下所示:

callback.call(this,tab.url);
console.log("5");
miner.getTabUrl(function(pageUrl) {
    miner.setTabUrlValue(pageUrl);
    console.log("6");
    miner.logToConsole("1"+miner.tabUrl);
    console.log("7");
});
在这种情况下,您可以留下
this.tabUrl=pageUrl原样

这是对代码的简化。这些方法返回
this
,以便能够直接引用实例的属性(请参见
console.log
最后一行):

再看看@您的代码,我认为您两次失去了作用域,因为
callback
是从另一个回调中调用的。这就是为什么我认为你的代码应该是:

chrome.tabs.getSelected(
      null, 
      function(tab) {
        callback.call(that,tab.url); //< use that here
      }
);
chrome.tabs.getSelected(
无效的
功能(选项卡){
callback.call(即tab.url);//<在这里使用它
}
);

此外,在您编写的代码@github中,我没有看到任何
miner
实例的实例化。

这是JavaScript中一个棘手的问题,正如其他人指出的,这是问题的关键。在任何地方使用
this
的问题在于,它的值可能会根据调用函数的人/地点而变化(例如,请参阅JavaScript中的和方法)。我猜想,如果您将
this
的值写入控制台中的
chrome.tabs.getSelected
函数的回调中,您会发现它不再是您的矿工

解决方案是,当您确信它是正确的时,捕获对您实际感兴趣的
这个
的引用,然后从那时起使用该引用。在您的示例中,看到它的注释可能更有意义:

function SocialMiner(tabUrl) 
{
    //At this point we know "this" is our miner object, so let's store a
    //reference to it in some other (not so transient) variable...
    var that = this;

    var verbose=true;

    var profileArray=new Array();

    this.tabUrl=tabUrl;

    this.getTabUrl=function(callback)
    {
        chrome.tabs.getSelected(null, function(tab)
        {
            //at this point "this" is whatever the "chrome.tabs.getSelected"
            //method has decided it is (probably a reference to the tab or something)
            callback(tab.url);
        });
    }   

    this.setTabUrlValue=function(pageUrl)
    {
        //because this can be called from anywhere, including the chrome callback
        //above, who knows what "this" refers to here (but "that" is definitely
        //still your miner)
        that.tabUrl=pageUrl;
        console.log("22"+that.tabUrl);
    }
}
您可以看到,在像jQuery这样大量使用回调的库中,
this
的变化有多大,在jQuery中,
this
通常被设置为方便的值,但肯定不是您最初调用时逻辑范围内的
this

编辑:看看,这只是一个时间问题,
chrome.tabs.getSelected
显然在您对日志的“第二次”调用完成后异步返回

console.log("5");
miner.getTabUrl(miner.setTabUrlValue);   //setTabUrlValue is logging with '22'
console.log("6");
miner.logToConsole("1"+miner.tabUrl);
console.log("7");


// Output:
5
6
1 undefined       //the chrome.tabs.getSelected hasn't returned yet...
7
22 http://url     //now it has (so if you tried to use miner.tabUrl now you'd be all good...
解决方案是将get/set之后的所有内容放入回调,因为在tabUrl设置完成之前,您不希望发生任何事情。。。比如说:

callback.call(this,tab.url);
console.log("5");
miner.getTabUrl(function(pageUrl) {
    miner.setTabUrlValue(pageUrl);
    console.log("6");
    miner.logToConsole("1"+miner.tabUrl);
    console.log("7");
});

希望您能按照预期的顺序得到结果。

是否存在
logToConsole
方法?因此,这个问题有3个正确的答案,问题是对“this”是什么的误解。您无法获得有效答案的原因是,您的代码段高度依赖于脚本的其余部分。我强烈建议您访问jsfiddle.net,一起获得一个更通用的答案来说明您的问题。这将使你更容易理解你的问题,并给你一个正确的答案。@Matt:请看更正后的代码,它仍然不起作用。第二行未定义miner.TabUrl。这不是重复的,你回复中的帖子包含了一个不同的问题,你可以详细说明一下,我认为这是因为回调是异步执行的。不是吗?对callback()的调用不会保留正在操作的对象。这是一个静态函数调用。您需要做的是将回调作为一个方法应用于对象:callback.call(this,pageUrl)@扎斯:上面的解决方案似乎不起作用。你能解释一下吗?我试过了,但没有起作用。请看这里的要点:嗨,Madhur Ahuja,请看编辑后的答案。也许我会晚一点再看,但现在已经很晚了,该睡觉了;~)祝你晚安,但还是不走运:(谢谢。我没有看到构造函数中定义了
.logToConsole
,这可能是问题所在吗?@Kooilnc:请在这里查看完整的代码,谢谢您的详细解释。我现在正在使用这个实现,如gist中所示。但是,第二行仍然在为miner打印未定义的。tabUrl@Madhur-查看我的编辑。。。