在函数中获取正确的作用域(不使用that=this)

Getting correct scope in functions (not using that = this)

本文关键字:that this 作用域 函数 获取      更新时间:2023-09-26

我正在尝试修复我在这里的一个函数,以便能够在不使用this=this(或self=this)的情况下使用它。这是一个范围界定问题,但我不确定如何绕过它,我想养成不使用that=this的习惯。所以这些函数都在返回(角度工厂)中,我在引用另一个函数时遇到了问题。让我告诉你我的意思:

  return {
            loadStates: function() {
                     var that = this;
                     //chgeck if is loaded module, then change and fire callback
                     var currentModules = moduleHolder.getModules();
                     if (currentModules[name]) {
                        //works here
                         this.prepState();
                     } else {
                         //module cannot be found check for 5 seconds
                         $log.warn("Requesting " + name + "...");
                         var timeToCheck = true;
                         setTimeout(function() {
                             timeToCheck = false;
                         }, 5000);
                         var check = {
                             init: function() {
                                 check.checkAgain();
                             },
                             checkAgain: function() {
                                 if (timeToCheck) {
                                     if (currentModules[name]) {
                                        //but not here
                                         that.prepState();
                                     } else {
                                         //still doesn't exists
                                         setTimeout(check.checkAgain, 200);
                                     }
                                 } else {
                                     //doesn't exist after 5 seconds
                                     $log.error("Requested module (" + name + ") could not be found at this time.");
                                 }
                             }
                         };
                         check.init();
                     }
                 },
                 prepState: function() {
                 }
             }

因此,在顶部,如果它找到currentModule〔name〕,我可以使用this.prepState(),它可以很好地工作。然而,在计时函数中,我不能使用this,因为它在一个不同的范围内,所以我通过在顶部设置一个that=this来暂时解决这个问题,但我想看看我是否不能使用这个方法。如果不使用that=this,如何绕过这一点?谢谢

这是一个范围界定问题。。。

不,不是。CCD_ 1和scope基本上没有任何关系。(目前,ES6的箭头函数将改变这一点。)这是如何调用函数的问题。

如果您将函数引用传递给稍后将调用它的对象,除非您将其传递给的对象有一种方法可以在调用它时告诉它this使用什么,否则您的函数将被调用为this,而不是引用您希望它引用的内容。

您可以使用Function#bind:获得一个新的函数引用,该引用将使用正确的this调用您的原始函数

var usesCorrectThis = originalFunction.bind(valueForThis);

例如,假设我有:

var check = {
    name: "Fred",
    sayHello: function() {
        console.log("Hi, I'm " + this.name);
    }
};

如果我这样做:

check.sayHello();

一切都很好:将函数作为从属性中检索该函数的表达式的一部分进行调用,告诉JavaScript引擎在调用期间将该对象用作this

但是,如果我这样做:

setTimeout(check.sayHello, 0);

这并不正确,因为当setTimeout调用函数时,它没有为this使用正确的值。

所以我可以使用Function#bind来解决这个问题:

setTimeout(check.sayHello.bind(check), 0);

更多(在我的博客上):

  • 神话般的方法
  • 你必须记住this0

有不同的方法可以做到这一点。一种方法是使用绑定功能。你可以使用

 var checkInitBindFn = check.init.bind(this);
 checkInitBindFn();

其次,你也可以使用call和application。

check.init.call(this);
check.init.apply(this);

像这样你可以用这个代替那个。在线查看完整的api文档。。。

这不是范围界定问题。如果你想避免self = this,你总是可以通过对象引用函数。生成更干净的代码,并且由于angular中的工厂是单体的,所以不会浪费内存。

angular.module('myApp').factory('myFactory', function ($timeout) {
  var myFactory = {
    loadState: function () {
      $timeout(function () {
        myFactory.check();
      }, 500);
    },
    check: function () {
    },
  };
  return myFactory;
});