Javascript在ajax回调后引用相同的对象

javascript this refers to same object after ajax callback

本文关键字:对象 引用 ajax 回调 Javascript      更新时间:2023-09-26

我正在尝试使用javascript的oauth库来获取tweet。我已经创建了一个对象,该对象将获取twitter时间轴的url并将其放在列中。代码是

   lister=function(opts) {
    this.setresource =lister.setresource;
    this.config = lister.config;
    this.config.resource = opts;
    this.putTweet = lister.putTweet;
    this.listerstrap = lister.listerstrap;
    this.addStrip = lister.addStrip;
    this.setTweets = lister.setTweets;
    this.addTweets = lister.addTweets;
}    

现在,如果我创建两个list对象

    var l1 = new lister('user1'); //user1 and user2 refer to url of the timelines 
    l1.listerstrap();
    var l2 = new lister('user2');
    l2.listerstrap();

liststrap函数为:

     lister.listerstrap = function () {
   this.addStrip().setresource().addTweets();
   }

问题发生在addTweets()

     lister.addTweets = function () {
   var _ = this;
   oauth.get(twiapi + _.config.resource, function (res) {
       _.setTweets(JSON.parse(res.text));
       console.log(_.config.resource);  // * 
   });

在*处,this(_)指向相同的(l2实例),因此当调用setTweets时,来自两个资源的tweet被设置到同一列中

是闭包问题吗?

编辑:我正试图根据时间轴或列表将推文设置为不同的列(就像在Tweetdeck中所做的那样,每个列表都有不同的列)。虽然我从两个url获得tweet,但它们被设置为同一列。_包含对我在addStrip()中创建的每个列的div元素的引用。但不知何故_在回调中引用了同一个实例。我希望它将tweet设置为各自的列

问题不在于addTweets方法,如果你读了我之前的回答:忘了它吧。

问题是:

this.config = lister.config;
this.config.resource = opts;

你的构造函数给一个对象赋值一个引用,对象本身不会被复制。因此,通过将引用分配给实例,然后更改所引用的对象,您正在更改所有实例所引用的对象

快速解决方案是将this.config = lister.config;更改为如下内容:

this.config = {foo: 'bar', something: 'else', resource: opts};//each time the constructor is called, create a new object literal

但是,请务必考虑使用原型,因为将引用赋值给函数对象的属性,这也兼作构造函数,并不是最好的方法。

更新:

回应OP的评论:你看到的很有道理。您正在创建一个新实例,将单个config.resource对象(只有一个)设置为User1,并调用addTweets函数。这个函数执行一个异步请求。异步是经常被忽略的东西,但在这种情况下非常重要:在调用回调函数(使用config.resource值)之前,创建一个新实例,然后更改config.resource属性。直到构造第二个实例之后才调用回调函数。这就是为什么config.resource值会在调用addTweets和调用异步回调之间的瞬间改变,因为这是创建第二个实例的时候。就这么简单,真的。

我很确定_指的是不同的实例。问题是,当您这样做时,您正在覆盖共享配置对象的属性:

this.config = lister.config;
this.config.resource = opts;

所以,你的l1l2总是有相同的config对象。只要实例化了l2,它就会覆盖resource属性。

您可能想要创建一个克隆:

this.config = clone(lister.config);

其中clone可能是您选择的一些实现