Javascript using 'this' in a global object

What about the 'this' keyword when used in a gloabl object?

Say, for example, we have:

var SomeGlobalObject = { rendered: true, show: function() { /* I should use 'SomeGlobalObject.rendered' below, otherwise it won't work when called from event scope. But it works when called from timer scope!! How can this be? */ if(this.rendered) alert("hello"); } } 

Now, if we call the inline script on the HTML page:

 SomeGlobalObject.show(); window.setTimeout("Msg.show()", 1000); 

everything is working fine.

But if we do something like

 AppendEvent(window, 'load', Msg.show); 

we get an error because this.rendered is undefined when called from the event scope.

  • Do you know why this is happening?
  • Could you please explain if there is another smarter way to do this without rewriting "SomeGlobalObject.someProperty" each time into SomeGlobalObject code?

Thanks!

AppendEvent is just a cross-browser function for adding events, the code is below, but it doesn’t matter to answer the above questions.

  function AppendEvent(html_element, event_name, event_function) { if(html_element.attachEvent) //IE return html_element.attachEvent("on" + event_name, event_function); else if(html_element.addEventListener) //FF html_element.addEventListener(event_name, event_function, false); } 
+1
source share
4 answers

When you reference a function that is a method of an object, you separate it from that object, and this will no longer be a reference to the object.

The simplest solution is to wrap it with an anonymous function:

 AppendEvent(window, 'load', function () { Msg.show() } ); 

There is also a bind function available for functions in implementations of ECMAScript 5th Edition that allow this:

 AppendEvent(window, 'load', Msg.show.bind(Msg, arg1, arg2)); 

The JS framework, Prototype, provides this method for current JS implementations. Code (thanks @bobince):

 // From Prototype.js if (!Function.prototype.bind) { // check if native implementation available Function.prototype.bind = function(){ var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift(); return function(){ return fn.apply(object, args.concat(Array.prototype.slice.call(arguments))); }; }; } 
+4
source

Do it

 var SomeGlobalObject = { ... } AppendEvent(window, 'load', function(){ SomeGlobalObject.show(); }); 

Javascript supports dynamic scaling. Therefore, SomeGlobalObject will be available for the function declared in the string always.

+1
source

The keyword this always refers to the caller. In the first example, SomeGlobalObject is the caller.

I believe you need to do something like AppendEvent(window, 'load', function() { SomeGlobalObject.show() })

0
source

A simple way to describe what happened:

'this' always refers to invoker functions.

So make an abusive case:

 AppendEvent(window, 'load', Msg.show); 

Event handling is invoked by the window. Thus, 'this' becomes a window and

 window.rendered 

- undefined.

bind () will quickly become your best friend :-)

As a third-party

 window.setTimeout("Msg.show()", 1000); 

will work a little faster if you pass the object directly to the function

 window.setTimeout(Msg.show, 1000); 

This is because the first syntax requires eval () strings - basically compilation - before calling it

0
source

Source: https://habr.com/ru/post/1306777/


All Articles