【问题标题】:change "var" inside constructor closure where new instance is created在创建新实例的构造函数闭包中更改“var”
【发布时间】:2014-09-16 11:56:53
【问题描述】:

我的英文写得不好我很抱歉...

我对 var 在函数闭包中的行为有一些疑问,例如:

var c = function(){
    var _self = this;
}

当我创建一个新实例时:

var A = new c();

A.logSelf = function(){
    console.log(_self);
}

在 A 范围(或闭包...并借助 jQuery 帮助扩展构造函数的默认行为(简单来说):

var c = function(obj){
    var _self = this;
    this.name = "lol";
    this.init = function(){
        _self = this;
    }
    this.sayName = function(){
        console.log(_self.name);
    }
    $.extend(this,obj);
    this.init();
}

var A = new c({
    name : "A",
    init : function(){
        _self = this;
    },
    sayA : function(){
        console.log(_self.name)
    }
});

现在,如果我在控制台日志 A 中调用 A.sayName()A.sayA(),我会说:“哇,我是有史以来最棒的!”,但是当我试图实例化一个B var all changed:

var B = new c({
    name : "B",
    init = function(){
        _self = this;
    }
});

... 现在 A.sayName() 记录 A,但 A.sayA() 记录 B(因为 _self 在所有 c 的实例中现在是我的最后一个实例已创建 [B 在这种情况下])...

为什么?我怎么了?

也许 AB 的闭包是相同的,因为它们都是同一个构造函数的实例? 但是为什么在AB的c方法ereditend中_self的值是正确的?我不明白这是什么意思!叹息。

工作示例

--> jsfiddle

为什么我需要这个?

在我的 A & B 实例中,我使用了一些 $.ajax 和 jQuery 处理程序,在 jQuery 用来回调的匿名函数中(都知道)this 是对某事的引用,我无法引用该实例包装匿名函数。

每次我需要使用 jQuery 回调或使用 $.ajax 的上下文属性时,我都需要 _self 来轻松引用而无需重估 var _self。

我更喜欢将self 赋值一次,并且在我的实例的范围(或闭包)内它永远不会改变他对this 的引用。

一些例子...

c = function(){
    //...
    this.render = function() {
            //var __self = this; 

            if (typeof this.view.surce === "undefined") {

                //this.writeRequest();

                $.ajax({
                    url: this.config.path + "/index.shtml",
                    data: this.config.req,
                    datatype: "html",
                    success: function(ht) {
                        __self.view.elements.html = ht;
                        __self.run();
                    },
                    error: function() {
                        __static.log("Error inside ajax call for view TMPL");
                    }
                })
            } else {
                this.run();
            }
        }

    //...

    this.run = function() {
        if (this.view) this.$el = $(__static.tmpl(this.$tmpl.html(), this.view.elements));
        this.$el.appendTo(this.$place);

        if (typeof this.view.callback === "function") {
            this.view.callback.call(this, this.$el);
            delete this.view.callback;
        }

        this.cases();
        this.show();
    }

    //...
}

真正的问题在于A的这个方法:

    endpoint : function(){
        //var __self = this; 
        this.$el.find(".call-to").on("click", function(e) {
            e.preventDefault();
            if(typeof __static.B !== "undefined") return __static.B.show();
            //__static is the reference of the scope (all works inside a self invoked anonymous function).
            __static.B = new __static.C(Bconfig, __static); //Bconfig is an object that contain all extend and override the C constructor.
            __self.close();
            __static.B.view = new _viewConf(__static.B.config.type[__self.view.b]);
            __static.B.render();
        });
    },

在这两种情况下,我每次需要使用时都需要与__self竞争。

(我已经在此处搜索了答案,并且通常在 google 中搜索...但我没有找到我的具体案例)

【问题讨论】:

  • 如果可以的话,可以发$.ajax()的回调片段吗?
  • 我用一些例子更新了我的问题:)

标签: javascript jquery closures this


【解决方案1】:
var B = new c({
    name : "B",
    init = function(){
        _self = this;
    }
});

这段代码 sn-p 有一个函数 B.init,它将全局 _self 设置为 B (this)。

当您定义 A 时,它是相似的并且也在编辑全局 _self

也许你想要的是这样的

[ FIDDLE ]

使用$.ajaxcontext 功能没有任何问题。但是你可以有这样的东西:

var c = function(obj){
    var _self = this,
        data;
    ...
    this.request = function(){
            $.ajax( { 
                url : 'blah',
                // context : this,
                success : function(d){
                    data = d;   // setting a private var of A
                    _self.sayName();  // in lieu of using context to set "this".  calling A public method
                }
            });  // end ajax; 
    }  // end anon;
} // end constructor;

【讨论】:

  • 如果方法在 c 构造函数内部没有问题,问题在于在 c 的新实例中覆盖或扩展构造函数的方法内部...
  • 在这种情况下,因为您正在扩展新对象,因此对您已经创建的对象有引用,为什么不使用该引用?您不必在实例化它的那一刻就扩展它。
  • 我不确定是否理解...但它是正确的。在 AB 实例中赋值的 _selfwindow 的属性。这就是我的问题的答案。您是建议直接使用B.method()A.method()
【解决方案2】:

这里的问题是您在实例 A(和 B)中分配给的 _self 变量与函数 c 范围内的 _self 变量不同,它是一个全局变量(在窗口对象中)

var c = function(obj){
    var _self = this; // scope of function 'c'
    this.name = "lol";
    this.init = function(){
        _self = this; // still scope of function 'c'
    }
    this.sayName = function(){
        console.log(_self.name); // scope of function 'c'
    }
    $.extend(this,obj);
    this.init();
}

var A = new c({
    name : "A",
    init : function(){
        _self = this; // global scope here, _self === window._self
    },
    sayA : function(){
        console.log(_self.name) // also call to the global _self object
    }

});

这样,对象 A 和 B 都在其函数中使用 window._self,从而使它们共享数据。在这里要学习的是,您不能使用“var”声明来操作在函数范围内定义的变量。你可以操作的那些你必须分配给'this'(在构造函数的情况下)

【讨论】:

  • 好的...清楚。那么,我可以做一些我想做的事情吗? (该死我的英语不好!)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-08
  • 1970-01-01
  • 1970-01-01
  • 2021-03-05
  • 1970-01-01
  • 2020-09-14
相关资源
最近更新 更多