开发者

Javascript error using this on a object

My page shows a window with a confirmation.

If I choose Yes, the method Method1 runs but an error is generated saying that the object [Object DOMWindow] has no method 'Method2'.

How can I solve this?

开发者_JS百科<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Testes Javascript O.O.</title>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.css" /> 
<link type="text/css" href="http://dev.jtsage.com/cdn/simpledialog/latest/jquery.mobile.simpledialog.css" rel="stylesheet" /> 
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script> 
<script type="text/javascript" src="http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.js"></script> 
<script type="text/javascript" src="http://dev.jtsage.com/cdn/simpledialog/latest/jquery.mobile.simpledialog.js"></script>
<script type="text/javascript">
var vssMkt = {};

var MsgBoxSimNao = function (parMensagem, parFuncaoSim, parFuncaoNao) {
    /// <sumary>Abre uma caixa de dialogo com uma mensagem e um botao de Sim e outro de Nao.</sumary>
    /// <param name="parMensagem" type="String">Mensagem a ser exibida.</param>
    /// <param name="parFuncaoSim" type="Function">Funcao a ser executada quando clicar no Sim.</param>
    /// <param name="parFuncaoNao" type="Function">Funcao a ser executada quando clicar no Nao.</param>
    $(this).simpledialog({
        'mode': 'bool',
        'prompt': parMensagem,
        'useDialogForceFalse': true,
        'buttons': {
            'Yes': {
                click: parFuncaoSim // Callback func if I press Yes
            },
            'No': {
                click: parFuncaoNao // Callback func if I press No
            }
        }
    })
}

var Obj1 = function () {
    this.Method1 = function () {
        MsgBoxSimNao("Show message?",
            this.Msg1,
            this.Msg2
        );
    }

    this.Method2 = function () {
        alert('Method 2');
    }

    this.Msg1 = function (parMsg) {
        alert('Yes');
        this.Method2();
    }

    this.Msg2 = function () {
        alert('No');
    }
}

function onLoad() {
    vssMkt.test = new Obj1();
    $("#link").click(function () {
        vssMkt.test.Method1();
    });
}

</script>
</head>

<body onLoad="onLoad();">
<div data-role="page">
  <div data-role="header">
    <h1>Javascript error</h1>
  </div>
  <!-- /header -->
  <div data-role="content">
  <a id="link" href="#" data-role="button">Start test</a>
  </div>
  <!-- /content --> 
</div>
<!-- /page -->
</body>
</html>


Edited

Sorry, first answer was not correct.

Your issue is in the constructor. Since you are passing methods to other functions for them to call, they need to keep a reference to the instance in a closure.

> var Obj1 = function () {
>     this.Method1 = function () {
>         MsgBoxSimNao("Show message?",
>             this.Msg1,
>             this.Msg2
>         );
>     }

To keep a reference to the instance, change it to:

var Obj1 = function () {

    // Reference to the instance
    var obj = this;

    this.Method1 = function () {
        MsgBoxSimNao("Show message?",
            this.Msg1,
            this.Msg2
        );
    }

In the call you have:

>     this.Method1 = function () {
>         MsgBoxSimNao("Show message?",
>             this.Msg1,
>             this.Msg2
>         );
>     }

so this.Msg1 and this.Msg2 will pass references to those functions when Method1 is called. When they are called from MsgBoxSimNao, they are called without any qualification so when Msg1 is called:

>     this.Msg1 = function (parMsg) {
>         alert('Yes');
>         this.Method2();
>     }

within the function this is set to the global object. Change the method to keep a reference to the instance:

this.Msg1 = function (parMsg) {
    alert('Yes');
    obj.Method2();
}

obj references the instance and its Method2 will be called. There are other ways to do it, but this is the simplest (to me anyway).

Untested, but should work.


See if this will fix the problem:

var Obj1 = function () {
    Method1 : function () {
        MsgBoxSimNao("Show message?",
            this.Msg1,
            this.Msg2
        );
    },

    Method2 : function () {
        alert('Method 2');
    },

    Msg1 : function (parMsg) {
        alert('Yes');
        this.Method2();
    },

    Msg2 : function () {
        alert('No');
    }
}


this in javascript isn't as well defined as it is in other languages. it doesn't always mean the object owning the object, it usually means the current calling object. So in this case, since it is called from the global scope, it gains the global object, which in JS is window.

If you are ok taking a dependence on ES5 features, you can simply change Method1 to pass this.Msg1.bind(this), this.Msg2.bind(this). If you need legacy support, I believe either JQuery, or a JQuery plugin provides identical functionality.

I'm not certain, but i also think that passing function() { this.Msg1()} in place of this.Msg1 will also close over this and properly call the function.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜