Javascript 未通过应用或调用将其设置为值

Javascript not setting this to value with apply or call

编辑:下面的代码是当场编造的,以展示我是如何处理我正在做的事情的。它肯定不会 运行,它缺少很多东西。 这是 codepen 中的一个工作示例:https://codepen.io/goducks/pen/XvgpYW

更短的示例:https://codepen.io/goducks/pen/ymXMyB

创建使用 call 或 apply 的函数时,使用 getPerson 时 this 值保持为空。但是,当我使用 apply 或调用 getPerson 时,它 return 是正确的人选。

大家多多批评指正,我真的是学的越来越多了。我正处于项目部分的中间,因此可能很难更改所有代码,但我的下一个项目可以更好地实现这一点。

调用和应用设置为 window 而不是对象。 我将提供更简单的代码,与我正在谈论的概念相同。

function createPerson(){
    this.manager = null;
    this.teamManager = null;
    this.setTeamManager = function(val){
        this.teamManager = val;
    }
    this.setManager = function(val){
        console.log('setting manager to',val);
        this.teamManager = val;
    }
    this.getTeamManager = function(){
        console.log('setting team manager to',val);
        return this.teamManager ;
    }
    this.getManager = function(){
        return this.manager;
    }
    this.appendSelect = function(elem){
        var that = this;
        createOtherSelects(that,elem);
    }
    //some functions that create selects with managers etc
    //now assume there are other selects that will filter down the teams,
    //so we might have a function that creates on change events
    function createOtherSelects(that){
        //code that creates locations, depending on location chosen will 
        //filter the managers
        $('#location').on('change',function(){
             //do some stuff
             //... then call create management
             createManagement(that,elem);
        });
    }
    function createManagement(that,elem){
         var currentLocation = that.location; //works
         var area = that.area;//works ... assume these are set above
         //code that returns a filter and unique set of managers back
         that.teamManager = [...new Set(
             data.map(person=>{
                 if(person.area==area && 
                    person.currentLocation==currentLocation
                 ){
                      return person;
                  }
              })
         )].filter(d=>{if(d){return d}});
         if(elem.length>0){
             var selectNames = ['selectManager','selectTeamManager'];
             var fcns = [that.setManager,that.setTeamManager];
             for(var i = 0; i < selectNames.length;i++){
                  //do stuff 
                  if(certainCriteriaMet){
                    // filter items

                      if(filteredManager == 1){
                           fcns[i].call(null,currentManager);//
                      }
                  }
             }    
        }
    }
}
var xx = new createPerson()

在控制台中,我看到 setting manager 和 setting team manager 具有正确的值。

然而,当我在控制台中调用 xx 时,我看到除了 xx.teamManager 和 xx.manager

而是应用于 window,因此如果我在控制台中键入 teamManager,它会 return 与正确的人。

如果我直接说 that.setManager('Steve') 甚至它工作得很好。

xx.setManager('steve')

setManager 中的 this 值以某种方式从对象的当前实例更改为 this window。不知道为什么,想学学apply和call的用法,以供日后参考。

我认为问题出在您的以下代码上

fcns[i].call(null,currentManager)

如果您不提供 "this" 调用,它将在非严格模式下替换为全局对象。

fcns[i].call(that,currentManager)

参见 mdn 文章 here

根据您的代码笔示例,您需要更改该行

fcnset[0].apply(that,[randomName]);

apply 方法的第一个参数是上下文,如果你没有给它你的方法的上下文,它默认使用全局上下文。这就是为什么你最终改变了 window 对象,而不是你想要的对象!