Javascript keyword questions this

Code example:

<!DOCTYPE html> <html> <head> <title>test</title> <script language="javascript" type="text/javascript"> function init() { var nodeList = document.getElementsByTagName("a"); var nodeArr = []; for( var i = 0; i < nodeList.length; i++) // Copy NodeList to Array nodeArr.push(nodeList[i]); for( var i = 0; i < nodeArr.length; i++) // Loop over array if( nodeArr[i].className == "clickLink" ) nodeArr[i].onclick = clickLink2; // Attach event function } window.onload = init; //Attach event function function clickLink2() { console.log("this: " + this); //Prints window URL in href console.dir( this ); //show attributes of anchor console.log( this.name ); // Prints name attribute } function clickLink( elem ) { console.log( "this: " + this ); //Prints [object Window] console.dir( this ); // Shows attributes, etc. al of [object Window] console.log( "name: " + elem.name ); } </script> </head> <body> <!-- inline --> <a href="#" name="blah1" onclick="clickLink(this); return false;">Test 1</a> <a href="#" name="blah2" onclick="clickLink(this); return false;">Test 2</a> <a href="#" name="blah3" onclick="clickLink(this); return false;">Test 3</a> <a href="#" name="blah4" onclick="clickLink(this); return false;">Test 4</a> <hr/> <!-- not inline --> <a href="#" name="blah5" class="clickLink">Test 5</a> <a href="#?t" name="blah6" class="clickLink">Test 6</a> <a href="#" name="blah7" class="clickLink">Test 7</a> <a href="#" name="blah8" class="clickLink">Test 8</a> </body> </html> 

I tested firefox with firebug to view console output.

Now I was wondering:

  • Why in clickLink does this apply to a window object?
  • Why is it in clickLink2 print to the console as the value of the href link?
  • Is there a better way to pass this to an unobtrusive application? how can you be sure what this means?

OK, so I took snippets from the answers here and found this to be a bit weird in some browsers. In addition, the purpose of the onclick function is different than binding (but, unfortunately, not all versions of IE support this, or see addEventListener vs attachEvent ). For some reason, the older IE also does this inside the body of the event-triggering function, still referring to the window object, not the caller. Therefore, I used event.srcElement . Here are some sample code:

 <!DOCTYPE html> <html> <head> <title>test</title> <script language="javascript" type="text/javascript"> function init() { var nodeList = document.getElementsByTagName("a"); var nodeArr = []; for( var i = 0; i < nodeList.length; i++) // Copy NodeList to Array nodeArr.push(nodeList[i]); for( var i = 0; i < nodeArr.length; i++) // Loop over array if( nodeArr[i].className == "clickLink" ) { var a = nodeArr[i]; if (a.addEventListener) { //IE9, other browsers a.addEventListener('click', clickLink2); // Attach event function } else if (a.attachEvent) { //IE6,7,8, etc. a.attachEvent('onclick', clickLink2 ); // Legacy IE Attach event function } a.onclick = function() { return false }; // override default onclick behavior for these anchors so URL is not followed } } window.onload = init; //Attach event function function clickLink2() { if( typeof(event) != 'undefined' ) { elem = event.srcElement; //IE < 8 keeps this as window object } else { elem = this; } alert( elem.name ); } function clickLink( elem ) { alert( elem.name ); } </script> </head> <body> <!-- inline --> <a href="#" name="blah1" onclick="clickLink(this); return false;">Test 1</a> <a href="#" name="blah2" onclick="clickLink(this); return false;">Test 2</a> <a href="#" name="blah3" onclick="clickLink(this); return false;">Test 3</a> <a href="#" name="blah4" onclick="clickLink(this); return false;">Test 4</a> <hr/> <!-- not inline --> <a href="#" name="blah5" class="clickLink">Test 5</a> <a href="#?t" name="blah6" class="clickLink">Test 6</a> <a href="#" name="blah7" class="clickLink">Test 7</a> <a href="#" name="blah8" class="clickLink">Test 8</a> </body> </html> 
+4
source share
4 answers

1) Why does clickLink refer to a window object? Simply put: clickLink is not an event handler; by adding the onclick attribute to elements, you use the onclick native method as the handler that calls the function. this function is declared in the main area, so it points to a window object. To be clear: the behavior looks like this:

 <p onclick='function(){window.clickLink(this);}'> 

Make the real event handler an anonymous function, rather than clicking the link. That's why it will point to a window: an anonymous function has also been declared in the global scope, so the clickLink caller is a window.

2) Why is it in clickLink2 to print to the console as the value of the href link?

Think of this phrase "Javascript allows you to manipulate the DOM, DOM tree, all events and behavior." Your init function controls onclick controls. the default onclick method is canceled and replaced by the clickLink2 method here nodeArr[i].onclick = clickLink2; .

Look at it like this: all of your elements have a prototype of the onclick method, which takes a parameter. In the first case, this parameter is a string that computes the call to the clickLink function. However, in the second case, instances that have a specific class have their own onclick method, which overrides the onclick prototype.

I hope this makes it a little easier for you. It's easy as soon as you understand the basic philosophy of events, handlers, methods, prototypes, etc ... and overcome the quirks of JS.

3) Is there a better way to pass this to an unobtrusive application? how can you be sure what this means?

Well, sort of the answer is that above, right? but one way or another: if you yourself define the method of the element or object, in general, this will indicate the object / element of the owner. If you rely on html and default behavior, JS will mainly take into account its own business, and this will point to a window.

I don't know if this is an option, but maybe you could try something like this:

 <a onclick='clickLink'> 

this should - in theory - do the same thing as your init function

Edit: A working alternative to the above:

 <p onclick='clickLink.call(this)'> 

The call defines the p element as the calling clickLink element, making this point the element that calls the function.

+2
source

When inline event handlers are called, they fire in the global scope. Therefore this window .

When event handlers are actually bound to an element, they are invoked in the context of that element, as when a method is run that is part of an object. This makes the this element.

For instance:

 function test(){ console.log(this); } test(); // window var obj = { test: test } obj.test(); // obj 

To ensure this , you must attach event handlers using JS (with element.addEventListener or element.onClick ) and not use the built-in handlers.

+2
source

This was one of the most amazing things I learned about JavaScript based on the .NET background.

this , when used in a method, does not apply to a specific object. This applies to the caller or to the object that raised the event that led to the event handler being called.

To answer number 3 of your questions: just copy what this refers to the new variable:

 var thisThis = this; //now pass thisThis. Interesting huh? //thisThis will not change with the change of the context. //this alone is a keyword that changes depending on //the context: eg who is the caller, what object raised the object, etc. 
+2
source

this is a variable pointing to the current area. If you run the following code in the console:

 var myPackage = {} myPackage.method = function() {console.log(this)} myPackage.method() 

this will point to the myPackage object ( method area).

Instead, if you try to run the following:

 console.log(this) // window 

this (window) is a link to the current browser window into which the script is being executed.

+2
source

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


All Articles