2

Here is a snippet of my HTML:

 <tr>
                <td class="timeHeader" id="timeInOutString"></td>
                <td id="timeControlHours"></td>
                <td>:</td>
                <td id="timeControlMins"></td>
                <td onclick="this.TimeChangeView.AcceptTime()">Accept</td>
            </tr>
            <tr>
                <td></td>
                <td onclick="this.TimeChangeView.downHours()">

Javascript:

function TimeChangeView(ac) {

    this.downHours = function(){


        //get element by Id

        var value = parseInt(document.getElementById('timeControlHours').innerHTML);

        value = isNaN(value) ? 0 : value;
        value--;

        //add leading zeroes

        value = formatHoursMins(value);

        document.getElementById('timeControlHours').innerHTML = value;

    }




}

Error:

Uncaught TypeError: Cannot call method 'downHours' of undefined

I have defined it in the script within a method called TimeChangeView, yet it is complaining that I have not defined it, why? Thanks.

3
  • 1
    You need to learn how the "this" word works. Google has many good articles about it index and ready for you. Commented Mar 21, 2014 at 19:59
  • The problem isn't downHours. Read the error message carefully. Cannot call method 'downHours' of undefined. TimeChangeView has a method called downHours but undefined doesn't. this.TimeChangeView returns undefined because this is window. Commented Mar 21, 2014 at 20:03
  • When I remove this it complains by saying uncaught TypeError: Object function TimeChangeView(ac) Commented Mar 21, 2014 at 20:07

2 Answers 2

3
<td onclick="this.TimeChangeView.downHours()">

You are calling the method TimeChangeView on the object this.

this refers to the object that the function is a method of. TimeChangeView is not a method of the object this, hence it does not work. (this is the window here)

You could pass this to the function TimeChangeView like so: TimeChangeView(this).

Read more about it here.

Update

To give you a better idea of how objects work in JavaScript, consider THIS CODE

As you can see, in the first function I call a method on the object:

button1.onclick=function()
{
    //Since we are calling a function on the object button1,
    //  in this function this = button1 (as an object)
    alert(this.id);
};

Hence this is in this case the object button1.

In the other function, I define a global function to which an object has to be passed:

function testFunction(passedObject)
{
    // In this function, we pass the object 'this' from button2
    // If I now call passedObject.id, it will give the id of the passed object
    // In this case that is 'button2'
    alert(passedObject.id);
}

In this function, there is no this. I can, however, pass an object to this function by calling this within an object in the HTML code.

E.g.:

<button id="button2" onclick="testFunction(this)">Button 2</button>

So now I call testFunction(this) and I pass the object <button id="button2">Button 2</button> as an argument.

So to summarize:

  • Within an object, this refers to the object itself
  • Outside an object, this refers to the nearest parent
  • Within a method called upon an object, this refers to the object itself

A nice sentence to summarize this behaviour is:

In JavaScript this always refers to the “owner” of the function we're executing, or rather, to the object that a function is a method of. source

Sign up to request clarification or add additional context in comments.

5 Comments

but are the js scripts not loaded into the browser window at run time? Thus this will reference the function?
Just think of this not as a static object but as a dependent reference to a changing object (depending on the scope). So don't think like it's Java ;)
right. When I remove it I just get the following error TypeError: Object function TimeChangeView(ac), any idea why?
Yes, TimeChangeView(ac), is expecting an argument ac as input when calling it. So calling it like TimeChangeView() is wrong.
Yeah - you see when I add TimeChangeView(this), it still complains. So I am not sure how to call that function directly. Sorry for all the questions, I am quite new to OOP in JS
0

A better way to do this is to call the apply/call method on the function TimeChangeView. The apply/call accepts two arguments the this object and any arguments that the function need (Note the second argument can be optional). For example we can then use it in this way TimeChangeView.apply(TimeChangeView) which sets the this value to TimeChangeView (Remember that function in JS is an object). You can also assign the TimeChangeView to a variable which you can use the variable to reference the functions inside TimeChangeView. Ex

var timeChangeView = TimeChangeView.apply(TimeChangeView); <\td onclick="timeChangeView.downHours()">

You also need to return the this object inside the TimeChangeView function definition.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.