3

基本上,我使用一个名为Joose for Javascript的元类框架,它允许我使用更优雅的类语法——但我不知道如何从类的更深层次的方法中引用对象的范围宣言。我还使用 require.js 进行依赖管理...

这是一个示例类定义:

   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 函数中,我必须编写 var self = this 才能让我的对象进入 AJAX 调用的范围 - 没问题。但是,我发现自己几乎对我的类声明中的每一个方法都这样做了!如何以干净有效的方式在所有方法中引用 self ?我知道您可以通过设置参数在 AJAX 中使用作用域,假设它不仅仅是 AJAX,而是其他将作用域关闭到外部的函数。

谢谢。

4

4 回答 4

2

每次嵌套函数时,都必须考虑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));
        },

请注意,并非所有浏览器都支持此功能,您可能需要为旧浏览器添加 shim。

或者只是习惯self = this


我也想对coffeescript 稍微点头,因为它支持声明在运行时不会改变上下文的函数。

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

obj.sayHello()

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

不过,在纯 JS 中,最常见的模式是简单的self = this,坚持下去。

于 2013-01-10T21:29:40.887 回答
1

答案是使用this. 您只需要创建一个闭包(var self = this;当您有一个将在对象外部调用的函数时,您可以这样做。(就像您在此处使用 ajax 调用的返回一样)。

没有其他方法可以创建闭包。


需要明确的是(因为有些人会因为任何轻微的技术挥手而跳),你不需要创建一个闭包。但我认为你应该—— JavaScript 被设计为与闭包一起工作,它们运行良好,并且被其他 JavaScript 程序员很好地理解。

于 2013-01-10T21:25:13.123 回答
0

我发现自己几乎对我的类声明中的每一个方法都这样做了!如何以干净有效的方式在所有方法中引用 self ?

你不能。的值(self由 引用的实例this)仅在调用该方法时才知道。

self如果您在构造函数(您的方法?)中声明了一个公共变量init并在那里创建了所有回调函数,您只能解决这个问题并使用一个公共变量。但是,可能不是最节省内存的方法:

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);
         },
         // …
     }
});
于 2013-01-10T21:26:45.427 回答
0

除了始终将 MyClass 的所有实例保持在范围内(或作为全局变量)之外,我没有看到任何解决方案。但是,您可以通过以下方式不必在self任何地方声明Function.prototype.bind

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

这不仅限于 $.get(),您可以在任何使用回调函数的地方使用它。

于 2013-01-10T21:28:24.610 回答