2013-01-10 66 views
2

基本上,我使用一个称为Joose的元类框架,它允许我使用更优雅的类语法 - 但我不知道如何去引用范围对象来自类声明的更深层次的方法。我也用require.js为dependemcy管理...Javascript范围引用外部对象

下面是一个例子类定义:

define([ 
     'jquery', 
     'handlebars', 
    ], function($, Handlebars){ 

     var MyClass = Class("MyClass", { 

     //inheritance   
     isa: SuperClass, 

     //instance vars 
     has: { 

      hello:{ 
       is: 'r', 
       init: 'Hi There!', 
      }, 

      someVarToBeSetUsingAjax:{ 
       is: 'rw', 
       init: false, 
      }, 
     }, 

     //methods 
     methods: { 

      init: function() { 

       var self = this; 
       self.getAjaxVar(); 

      }, 

      getAjaxVar: function() { 

       var self = this; 

       //HOW CAN I REFERENCE 'self' THROUGHOUT MY OBJECT? 

       $.get('ajax/test.html', function(response) { 
       self.someVarToBeSetUsingAjax = response.value; 
       }); 
      }, 

      //lots more methods... 

     } 
    }); 

    return MyClass; 

}); 

好了,我的问题是 - 在AJAX功能我必须写变种自我=这让我的对象进入AJAX调用的范围 - 没有问题。但是,我发现自己正在为我的课程声明中的几乎每一种方法都这样做!我如何以一种干净而有效的方式在所有方法中引用自我?我知道你可以通过设置一个参数来在AJAX中使用范围,假设它不仅仅是AJAX,还有其他一些将范围关闭到外部的函数。

谢谢。

回答

1

每次嵌套函数时,都必须考虑this。但是如果你不嵌套一个函数,或者这个函数不使用this你不需要考虑它。

 init: function() { 
      var self = this; 
      self.getAjaxVar(); 
     }, 

所以在这种情况下没有必要。这是完全一样的:

 init: function() { 
      this.getAjaxVar(); 
     }, 

但在这里:

 getAjaxVar: function() { 
      var self = this; 

      $.get('ajax/test.html', function(response) { 
      self.someVarToBeSetUsingAjax = response.value; 
      }); 
     }, 

您创建一个内部函数,并且要的this原始值的参考,所以你必须别名thisself使其可访问。

没有办法将this修复为您班上各处的值。


这就是说,你确实有一些选择。

Function.prototype.bind()可以提供帮助。

var func = function() { return this.name }; 
var obj = { name: 'Bob' }; 
var boundFunc = func.bind(obj); 
boundFunc(); // 'Bob' 

bind将返回一个新的功能与this总是被设置为一个特定的对象。

所以:

 getAjaxVar: function() { 
      $.get('ajax/test.html', function(response) { 
      this.someVarToBeSetUsingAjax = response.value; 
      }.bind(this)); 
     }, 

注意这不是在所有的浏览器都支持,您可能需要为旧的垫片。或者只是习惯self = this


我想给咖啡脚本一个小点头,因为它支持函数的声明,在运行时不会改变上下文。

obj = { 
    name: "bob" 
    sayHello: -> 
    doSomeAjax({ 
     success: => 
     alert "successfully made " + this.name + " say hello!" 
    }) 
} 

obj.sayHello() 

->使功能正常。但胖箭头=>将在函数内部和外部保留this的值。实例方法中的回调非常方便。当编译为JS时,它基本上为你做了一个self = this别名,在内部函数中每次使用self来引用this。这很漂亮。

尽管在普通的JS中,最常见的模式是简单的self = this,坚持下去。

+0

是的,我知道第一点,我只是想说明。感谢您的帮助,但我想我只需要习惯它! –

+0

标记为正确,因为它是最彻底的 –

1

答案是使用this。你只需要创建一个闭包(当你有一个函数将被称为外部对象的时候,你可以使用这个闭包(当你在这里从ajax调用返回时)。

没有其他的。方法来创建一个封闭


要清楚(因为有些人会在任何轻微的技术挥手跳),你不“需要”来创建一个封闭但我认为你应该 - JavaScript是设计用于闭包工作,它们工作良好,并且其他JavaScript程序员也很好理解它们。

+0

@Bergi - 因此没有其他的方法来做闭包(你的第一个评论)。 – Hogan

+0

糟糕,我必须误读为“*没有其他方式[达到此目的] *比*创建封闭。*” – Bergi

+0

@Bergi - NP,因为您可以看到您的评论促使我创建第二个这是对我最初的答案的巨大改进。 :) – Hogan

0

我发现自己正在为我的课程声明中的几乎每一种方法都这样做!我如何以一种干净而有效的方式在所有方法中引用自我?

你不行。只有在调用该方法时才知道self的值(this引用的实例)。

如果你在构造函数中声明了这个变量(你的init方法?)并且在那里创建了所有的回调函数,那么你只能解决这个问题并使用一个通用的self变量。也许不是最内存高效的方法,但:

return Class("MyClass", { 
    // … 

    methods: { 
     init: function() { 
      var self = this; 
      this.ajaxVarCallback = function(response) { 
       self.someVarToBeSetUsingAjax = response.value; 
      }; 
      // and other functions that use "self" 

      this.getAjaxVar(); 
     }, 
     getAjaxVar: function() { 
      $.get('ajax/test.html', this.ajaxVarCallback); 
     }, 
     // … 
    } 
}); 
0

除了始终保持MyClass的所有实例范围(或作为一个全局变量),我没有看到任何解决方案。但是,你可以破除不必使用Function.prototype.bind无处不在声明self

$.get('ajax/test.html', function(response) { 
    this.someVarToBeSetUsingAjax = response.value; 
}.bind(this)); 

这不限于$获得(),你可以用它无处不在,你正在使用的回调函数。