Why is this in an anonymous function undefined when using strict?
It's because, until ECMAscript 262 edition 5, there was a big confusion if people who where using the constructor pattern
, forgot to use the new
keyword. If you forgot to use new
when calling a constructor function in ES3, this
referenced the global object (window
in a browser) and you would clobber the global object with variables.
That was terrible behavior and so people at ECMA decided, just to set this
to undefined
.
Example:
function myConstructor() {
this.a = 'foo';
this.b = 'bar';
}
myInstance = new myConstructor(); // all cool, all fine. a and b were created in a new local object
myBadInstance = myConstructor(); // oh my gosh, we just created a, and b on the window object
The last line would throw an error in ES5 strict
"TypeError: this is undefined"
(which is a much better behavior)
If a strict mode function is executed using function invocation, its 'this' value will be undefined
Rather than try to suppress the warning, it's better to address the root cause.
Use of this
can be confusing, and the value of this
can unexpectedly change when refactoring code. Your code will be easier to read and maintain if you explicitly pass parameters.
The parameter passed to the test()
callback is the Event
object for the click:
function demo() {
'use strict';
function test(event) {
console.log('You clicked on:', event.target.outerHTML);
}
document.querySelector('#demo').addEventListener('click', test);
}
demo();
Console log output will be something like:You clicked on: <h1 id="demo">Click Me</h1>
The Event
object tells you the target element that the user clicked:
https://developer.mozilla.org/en-US/docs/Web/API/Event/target
Fiddle with the code:
https://jsfiddle.net/24epdxbz/2
From yehudakatz:
The ECMAScript 5 spec says that
undefined
is (almost) always passed, but that the function being called should change itsthisValue
to the global object when not in strict mode. This allows strict mode callers to avoid breaking existing non-strict-mode libraries.
Why does 'this' return 'undefined' when referred in an arrow function but doesn't when called on an anonymous function?
Because arrow functions don't have their own this
, they close over the this
of the calling context. But non-arrow functions, if they're not bound, take this
based on how they're called. I assume you're calling these functions like this:
obj.getScopeWithArrow();
obj.getScopeWithAnonymous();
In the first case, again, the arrow function doesn't get its own this
so it doesn't matter how you're calling it. In the second case, it does matter, and calling it like that makes this
within the call refer to the same object obj
refers to.
Separately: In your example, you must be in strict mode, because this
can only be undefined
in strict mode.
Separately 2: With regard to your method names: this
and "scope" have very, very little to do with one another.
Some examples:
function showThis(label, t) { if (t === window) { console.log(label, "(global object)"); } else { console.log(label, t); }}// Loose mode by default in a non-module script elementlet obj = { arrow: () => { showThis("arrow says ", this); }, normal: function() { showThis("normal says ", this); }};obj.arrow(); // global object (window on browsers)obj.normal(); // obj
function foo() { // Here, we're in strict mode "use strict"; let obj = { arrow: () => { showThis("arrow says ", this); }, normal: function() { showThis("normal says ", this); } }; obj.arrow(); // undefined obj.normal(); // obj
}foo();
Why is this undefined in a function defined and called in a JS class method. I exepected this to be window
1)function(){} declaration defines its own 'this' reference to context. In 'strict mode' such context will be undefined by default, in non-strict mode it will be 'window'
2) Class declarations evaluated in strict mode by standart https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Strict_mode
JavaScript undefined variable in an anonymous function
Closure issue.
Try adding a 3rd parameter to the setTimeout (doesn't work):
setTimeout(function(i){
children[i].style.display = "block";
console.log(i);
}, 2000, i);
Example
Another formate:
var i = 0;
var timer = setInterval(function () {
children[i].style.display = "block";
i++;
if (i == children.length) {
clearInterval(timer);
}
}, 2000);
EXAMPLE
ES6 is around the corner, the let
statement is especially built for situations like this:
for (let i = 0; children.length > i; i++ ) {
setTimeout(function(){
children[i].style.display = "block";
console.log(i);
}, 2000);
}
However this is not the answer you need for right now. This was just a note.
Using undefined in self-executing anonymous function
I wanted to also protect 'undefined' from being redefined
and
There's a compilation error due to the strict mode: "Certain variables such as undefined are no longer writeable"
So what is your problem? There is no need to declare a undefined
argument, because CoffeeScript won't let you use this "variable" anyway!
If you really (need/want to) worry about some third party script assigning a value to undefined
, don't use it in your code. You can always use the typeof
operator or CoffeeScripts existential operator instead.
Just don't worry about it. I think no one ever encountered such an error, apart from explicitly malicious attacks.
this inside an anonymous function?
Is this code from the book? I have the book, but I haven't read through it.
It's an error in the book. Check the errata: http://www.apress.com/9781590597279
Inside the anonymous function, this
is the global window
.
You could make it work by adding .call(this, i)
after it.
function User(properties) {
// Iterate through the properties of the object, and make sure
// that it's properly scoped (as discussed previously)
for (var i in properties) {
(function(i) {
// Create a new getter for the property
this["get" + i] = function() {
return properties[i];
};
// Create a new setter for the property
this["set" + i] = function(val) {
properties[i] = val;
};
}).call(this, i);
}
}
javascript object undefined under anonymous function
Your code is incorrectly assuming that this
will refer to a "ConstructNodes" object inside the event handlers. It won't; it'll be the element. Instead, store this
in an object, and things will be better:
ConstructNodes.prototype.getId = function(){
var nodes = document.getElementsByClassName(this.className), obj = this;
for (var i=0;i<nodes.length;i++){
nodes[i].onclick = function(){
var r = confirm(obj.alertMsg);
if (r==true){
alert(obj.hiddenId); // undefined
document.getElementById(obj.hiddenId).value = this.id;
alert(obj.hiddenId);
} else {
return;
}
};
}
};
(It's not at all clear what you're trying to do, so there may be some issues still.)
Related Topics
Websocket Handshake with Ruby and Em::Websocket::Server
Sort an Array of Object by a Property (With Custom Order, Not Alphabetically)
How to Convert a String to Bytearray
How to Get Objects Value If Its Name Contains Dots
How to Serialize Dom Node to JSON Even If There Are Circular References
Wicketpdf Rendering Table Not Aligned Properly and Footer Place at Last Page
How to Read Console Logs of Wkwebview Programmatically
Are There JavaScript or Ruby Versions of "HTML Tidy"
How to Disable Browser Developer Tools
Ruby Array to JavaScript Array
How to Fix Ajax to Always Fire When Checking Box
How to Include HTML in a Js Rails Response
Convert Array of Strings into an Array of Objects
Pass-By-Reference JavaScript Objects
Non-Blocking Settimeout in JavaScript VS Sleep in Ruby
JavaScript Getter for All Properties
Ruby Equivalent to JavaScript's Encodeuricomponent That Produces Identical Output