更好的设计方法,以便从对象的方法中引用自己的属性

5

我有一个“是/否”单选框输入。当用户点击“是”时,显示yesDiv,当用户点击“否”时,显示noDiv。

为了实现这个功能,我创建了对象myObject。

var myObject= {
        init: function(config){
            this.config=config;
            this.config.InputRadio.bind('click',this.config,this.switchDiv);
        },
        switchDiv: function(ev){
                    self=ev.data;
            if ($(this).val()==1){
                self.divYes.hide();
                self.divNo.show();
            }else{
                self.divYes.show();
                self.divNo.hide();
            }
        }
}

myObject.init({
        InputRadio:$("input[name=yesno]"),
        divYes:$("#yesDiv"),
        divNo:$("#noDiv")
});

这个方法是可行的,我知道在方法'switchDiv'中无法使用this来引用对象属性,因为函数内部'this'的作用域。在相关问题中( Referencing own object properties),我找到了将this.config作为参数发送并使用self=ev.data的解决方案。

但现在我的问题是:每当我想从对象的方法中访问对象自己的属性时,必须将它们作为参数传递给该方法,这不是有点奇怪吗?难道没有更好的声明对象的方法来避免这种情况吗?


当调用switchDiv时,'this'是单选按钮。因此它不能同时是myObject。您可以利用它作为单选按钮的优势,通过调用$(this).val()来实现。它既不能是单选按钮,也不能是myObject - Scott Sauyet
这必须在特定对象中吗?使用像这样的公共API?您是否在构建后保留“myObject”?您是否调用其公共“init”和“switchDiv”方法或再次访问其公共“config”属性?也许代码应该被埋在匿名闭包中,以维护状态但不提供公共接口。 - Scott Sauyet
3个回答

2
如果你想确保在调用`switchDiv`时,`this`指向`myObject`,我的建议是略微修改你的`init`函数。我还更新了你的`switchDiv`函数以反映这一点。你仍然需要重新分配`this`,但只需在`init`函数中重新分配即可。
var myObject= {
        init: function(config){
            var _this = this;
            this.config=config;
            this.config.InputRadio.on('change',function(){
                _this.switchDiv(); // now "this" will refer to myObject, not the input
            });
        },
        switchDiv: function(){
            if (this.config.InputRadio.filter(":checked").val() === '1'){
                this.config.divYes.hide();
                this.config.divNo.show();
            }else{
                this.config.divYes.show();
                this.config.divNo.hide();
            }
        }
};

通过将对 switchDiv 的调用包装在匿名函数中,您可以更好地维护 this 的上下文。
以下是演示: http://jsfiddle.net/VSdAL/ 相关提示,不建议在分配 this 给变量以在回调或其他函数中使用时使用 self。默认情况下,selfwindow.self 的快捷方式,它是指当前窗口的全局变量。您不希望重新分配它,以免弄乱其他使用 self 的代码。

这个观点忽略了对象的函数已经被绑定到单选按钮的事件处理程序上。当它被触发时,this现在是单选按钮。 - Scott Sauyet
我的错误;我已经编辑了我的答案以更好地回答手头的问题。 - jackwanders

0
ECMAScript 1.5(并非所有浏览器都支持)具有一个方法 Function.bind用于绑定this值:
this.config.InputRadio.bind('click', this.switchDiv.bind(this));

现在,当调用绑定的switchDiv时,this将始终引用myObject,您可以直接使用this.config而不是传递事件数据。

0

除非您需要对象的公共API,否则最好根本不创建这样的对象。将所有状态保留在隐藏范围内,例如this fiddle

var createYesNoToggler = function(radioName, yesId, noId) {
    var divYes = $("#" + yesId), divNo = $("#" + noId),
        radios = $("input[name=" + radioName + "]");
    radios.click(function() {
        if ($(this).val() === "1") {
            divYes.show();
            divNo.hide();
        } else {
            divYes.hide();
            divNo.show();
        }
    });
};

createYesNoToggler("yesno", "yesDiv", "noDiv");

或者,如果你只需要它一个,那么就不要将函数设为公共的:

(function(radioName, yesId, noId) {
    var divYes = $("#" + yesId), divNo = $("#" + noId),
        radios = $("input[name=" + radioName + "]");
    radios.click(function() {
        if ($(this).val() === "1") {
            divYes.show();
            divNo.hide();
        } else {
            divYes.hide();
            divNo.show();
        }
    });
}("yesno", "yesDiv", "noDiv"));

(但如果您只需要一个,那么可以通过更简单的方式完成。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接