I am reading a book and it says that this inside a function is set in 4 different ways. Default, implicit, explicit binding + using a new syntax. In all cases, this is set at function call. Take a look at example.
When I call jajca(), I am expecting this to be set via default binding.. thats is when jajca() is called this is already set to the object that was created using new syntax. Yet for some reason I don't understand, this inside jajca points to window even though that via default binding, this should be pointing to the object created using new.
function jajca() {
this.musicFolderPath = "value2"; // never gets assigned to the correct this.musicFolderPath
}
function Music(){
this.musicFolderPath;
jajca(); // music.musicFolderPath is undefined
// jajca.call(this); music.musicFolderPath is correctly set
}
var music = new Music();
//music.musicFolderPath is undefined
Can you explain why this is not set as I expected? If explicit binding is used, than this points to the object created using new keyword as expected.
When I call jajca(), I am expecting this to be set via default binding.. thats is when jajca() is called this is already set to the object that was created using new syntax. Yet for some reason I don't understand, this inside jajca points to window even though that via default binding, this should be pointing to the object created using new.
The gist of the idea is that whenever you call another function, the object that this represents will be "reset". (- According to the various rules of what "this" means -- this is what your book goes into. For example, when you do obj.bar(), the value of this in bar will be obj. That's why the "this" value "stays the same" when you do this.baz(): it's just saying, let the this inside baz be equal to the current this value.)
It's a pretty in-depth topic that your book likely goes into better detail than I could write in a brief StackOverflow answer, but if you keep that in mind while you're learning, you'll understand things easier.
In this case, yes, you'd want to do jajca.call(this) to make the value of this inside jajca be what you want it to be.
Related
Have you ever taken a look under the hood at the jQuery 1.4 source code and noticed how it's encapsulated in the following way:
(function( window, undefined ) {
//All the JQuery code here
...
})(window);
I've read an article on JavaScript Namespacing and another one called "An Important Pair of Parens," so I know some about what's going on here.
But I've never seen this particular syntax before. What is that undefined doing there? And why does window need to be passed and then appear at the end again?
The undefined is a normal variable and can be changed simply with undefined = "new value";. So jQuery creates a local "undefined" variable that is REALLY undefined.
The window variable is made local for performance reasons. Because when JavaScript looks up a variable, it first goes through the local variables until it finds the variable name. When it's not found, JavaScript goes through the next scope etc. until it filters through the global variables. So if the window variable is made local, JavaScript can look it up quicker.
Further information: Speed Up Your JavaScript - Nicholas C. Zakas
Undefined
By declaring undefined as an argument but never passing a value to it ensures that it is always undefined, as it is simply a variable in the global scope that can be overwritten. This makes a === undefined a safe alternative to typeof a == 'undefined', which saves a few characters. It also makes the code more minifier-friendly, as undefined can be shortened to u for example, saving a few more characters.
Window
Passing window as an argument keeps a copy in the local scope, which affects performance: http://jsperf.com/short-scope. All accesses to window will now have to travel one level less up the scope chain. As with undefined, a local copy again allows for more aggressive minification.
Sidenote:
Though this may not have been the intention of the jQuery developers, passing in window allows the library to be more easily integrated in server-side Javascript environments, for example node.js - where there is no global window object. In such a situation, only one line needs to be changed to replace the window object with another one. In the case of jQuery, a mock window object can be created and passed in for the purpose of HTML scraping (a library such as jsdom can do this).
Others have explained undefined. undefined is like a global variable that can be redefined to any value. This technique is to prevent all undefined checks from breaking if someone wrote say, undefined = 10 somewhere. An argument that is never passed is guaranteed to be real undefined irrespective of the value of the variable undefined.
The reason to pass window can be illustrated with the following example.
(function() {
console.log(window);
...
...
...
var window = 10;
})();
What does the console log? The value of window object right? Wrong! 10? Wrong! It logs undefined. Javascript interpreter (or JIT compiler) rewrites it this way -
(function() {
var window; //and every other var in this function
console.log(window);
...
...
...
window = 10;
})();
However, if you get the window variable as an argument, there is no var and hence no surprises.
I don't know if jQuery is doing it, but if you are redefining window local variable anywhere in your function for whatever reason, it is a good idea to borrow it from global scope.
window is passed in like that just in case someone decides to redefine the window object in IE, I assume the same for undefined, in case it's re-assigned in some way later.
The top window in that script is just naming the argument "window", an argument that's more local that the global window reference and it what the code inside this closure will use. The window at the end is actually specifying what to pass for the first argument, in this case the current meaning of window...the hope is you haven't screwed up window before that happens.
This may be easier to think of by showing the most typical case used in jQuery, plugin .noConflict() handling, so for the majority of code you can still use $, even if it means something other than jQuery outside this scope:
(function($) {
//inside here, $ == jQuery, it was passed as the first argument
})(jQuery);
Tested with 1000000 iterations. This kind of localization had no effect in performance. Not even a single millisecond in 1000000 iterations. This is simply useless.
I'm using the Polymer framework and I really enjoy it. But one thing I don't get is the confusion with the this-pointer. When functions get called from for example a button in your custom component the this-pointer points to the custom component. Very logical. But when your function within a custom component is called from something external, for example a callback from an library or a call from another component the this-pointer is something totally different. Why is it in this case not pointing to the custom component where the function is in?
Javascript is a bit of a weird bird when it comes to resolving this, often not doing what you would like. The only saving grace is that it's easy to explain and understand.
A function's this value is set by how it is called. Suppose you have a value val with a method method. If method is called like val.method() then in that call to method then this is val. If you instead do var theMethod = val.method; theMethod(); then for that call, this is something else (the global context object, in browsers this is window).
The solution fortunately is simple. There's a method on functions called bind that returns a new function that has the this immutably baked in. So var theMethod = val.method.bind(val); theMethod() has this bound to val.
In the future for many cases we'll be able to use ES6 Arrow Notation to get this behavior baked in at function definition time, but for now, when passing a method around (e.g. to register an event handler) be sure to bake the this in explicitly with bind.
After reading related questions #1 , #2
I still haven't found an answer to the following question:
Javascript can set context (i.e. set this) with: bind , call and apply.
But when I'm write an event handler:
document.getElementById('myInput').onclick = function ()
{
alert(this.value)
}
Who/What actually attaches this to the object itself ?
P.S. When using jQuery's :
$("#myInput").bind(function (){...})
there is an internal implementation of (bind, call or apply)
So when I am not using jQuery, who is doing it?
Why, the DOM/JavaScript of course, it's supposed to work that way by W3C.
Event handlers are invoked in the context of a particular object (the current event target) and are provided with the event object itself.
Source
How exactly that happens, we don't know. It's an implementation detail.
All we know is, that the semantics as defined by the W3C are achieved in some way, but which part of the browser does that and and how, that is left up to the browser developers, and they can implement it as they see fit.
To sum up all the discussions:
In general it is JavaScript that binds this to o inside a function call, when o.x() is called.
However, there are some alternative methods of calling functions (like f.apply() and f.call()) that change this behaviour.
onclick is a special case, and the method used to invoke it is unknown and depends on the DOM implementation.
The answers saying it is the DOM are wrong.
This is part of JavaScript itself, as a language. The DOM is ONLY what the name indicates "Document Object Model", which is just how HTML is represented for manipulation by using JavaScript. Objects related to the DOM follow the behavior specified by the standards, but this is implemented by using JS for it. It is the JS engine what does this, in communication with whatever layout engine is being used (Gecko, Trident, WebKit, Presto, etc.). So, if WebKit detects an event, it passes it to the JS engine as the DOM specification indicates so that it can manipulated by the JS programmer (which is why you're even asking about this, because you can work with it).
In other words, if you're writing something in JavaScript, the only engine that understands how to read and execute that is the JS engine. This engine (v8, SpiderMonkey/Jugger/Trace) will receive data from the layout engine and use it so that you can interact with it. Similarly, on the other hand, whenever you run code that affects the layout, the changes will be detected by the layout engine and it will change the layout so that the user perceives the changes: even if the JS code might have initiated this, it is the layout engine that takes care of the layout.
What "this" is when you assign a function to an object, is simply wherever the function belongs to. So, if you assign a function to instance of object a, then said function will refer to a whenever you use "this" inside of it.
If you wanted to think of it in implementation terms, think of it this way:
Whenever you are calling a method, you do so by first telling an instance that you want to call a method with N parameters. This instance calls the method but adds itself into the context, as "this".
In Python this is done more explicitly by making the first parameter of all instance methods the instance itself. Here it is the same, but the instance is passed implicitly instead of explicitly.
Remember, the instance owns the method. When you do "document.getElementById('something')" the call returns an object (which happens to be an HTMLElement object that is part of the DOM, but that's coincidental to how JS interacts with the DOM), and then you are assigning the function as the property click.
Then, whenever you call the method, the JavaScript engine passes the instance by default, just like it passes other variables (like arguments is also generated without you doing anything, also done by the JS engine which implements the ECMAScript standard).
I would recommend checking pages 63:
"The this keyword evaluates to the value of the ThisBinding of the current execution context."
but most importantly, page 68 "Function calls"
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
In your example, of an onclick handler it's perfectly straight forward: a DOM element is an object, you're defining the onclick property to be a function. That function effectively becomes a method of that DOMElement/object.When that object is clicked, the function is called as a method of that element, so this points to its owner, the element.
Put simply, the context in which the function executes is the same as the context in which is was created (again: in your example as a method of a DOM Element), unless a reference to a function object is assigned to another object, or when that function object is invoked in another context using call or apply & co.There's a little more to it than this, of course: as I hinted at above, functions are objects themselves and are said to be loosely coupled to their "owner". Well, actually they don't have an owner as such, each time a function is called, its context is determined:
var foo = someObject.someFunction;//reference to method
someObject.someFunction();//this === someObject, context is the object preceding the function
foo();//implies [window].foo(); ==> this is window, except for strict mode
As #wroniasty pointed out, my talking about ownership might be slightly confusing. The thing is, functions are objects, they're not owned by anything. When an object is assigned a method, all that object really owns is a reference to a given function object. When that function is called via that reference, this will point to the object that owned the calling reference. When we apply that to your elem.onclick = function(){}, we see the element only owns a reference to a function expression that was declared in some scope (global, namespace-object, doesn't matter). When the click event fired, that reference will be used to call the handler, thus assigning a reference to the element to this. To clarify:
document.getElementById('foo').onclick = (function()
{//This function returns the actual handler
var that = this;//closure var
console.log(this);//logs window object
//defined in global context
return function(e)//actual handler
{
console.log(this === that);//false
console.log(this);//elem
console.log(that);//window
};
})();//IIFE
So the handler was declared in the global context, and the handler can access its the context it was declared in using that, thanks to closures (but that's another story). The point is, the event references the handler using the onclick property of the element foo. That property is a reference to a function object, so the function object sets its context to whatever object made the call.
I do hope this clears up any confusion I caused with regard to ownership of functions, and perhaps how context in JS is determined.
http://dmitrysoshnikov.com/ecmascript/chapter-3-this/#this-value-in-the-function-code
Basically, it's done by JavaScript internals.
The context is the object calling the function, e.g.
elem.onclick(); // elem === this
However:
func = elem.onclick;
func() // global === this
This really has nothing to do with the DOM as has been mentioned, but how JavaScript is designed to work when you call a function within an object.
Take this as an example:
var myObject = {
id: 1,
onclick: null
}
myObject.onclick = function() {
console.log(this.id);
}
Calling myObject.onclick() will log 1 to the console, which means myObject is its context.
Since onclick is also a property of an object, this will be the parent object, in your case an HTMLElement.
For illustration purposes, although implementations may differ, think of the following function
function f() { alert(this.name); }
as
function f(this) { alert(this.name); }
Imagine this as a secret parameter that you can override with bind, apply and call but that normally gets set to the calling object by the browser.
Example
var a = {},
b = {};
a.name = "John";
b.name = "Tom";
// "this" param added secretly
function printName( ) {
console.log( this.name )
};
a.printName = printName
b.printName = printName;
When calling the printName function the browser sets that "secret" this parameter to the calling function. In the example below this is b and so "Tom" is printed to the console.
printName( ); // global context assumed so this === window
b.printName( ); // this === b and outputs "Tom"
printName.call( a ); //this === a and outputs "John"
Further info here.
Note: please keep in mind that this is not a generic question on the use of this on javascript. This is about aspect.around malfunctioning (it's meant to set the scope for the call, and it doesn't). The question is: why is aspect.around malfunctioning? this question needs you to read carefully how to reproduce and do so with the fiddle provided!
I had to shred my app to pieces in order to make the problem fit in a fiddle.
So here it is:
http://jsfiddle.net/mercmobily/THtsv/1/
It's a simple form, with validation:
Type something in the textbox: the validation method of the widget will be called.
Then press the submit button: validation will fail, and aspect.around will be called to wrap something around the validation method.
At that point, try to type anything in the textbox again: It will come back with an error, as the validator will fail because of "this" being set to "window" instead of the widget.
So, once the aspect is added, the validator stops working. Basically, the value of "this" gets lost. Now:
aspect.around() is meant to run the new validator in the right scope (obviously) and it's failing to do so
I can "fix" this problem by changing the call to the validator into this: return originalValidator.call(this, value); However, it doesn't answer the question "Why is 'this' lost?"
If you backtrace the code, you will see that aspect.around() is doing what it normally does... but it must be doing something wrong
So, the question: why is dojo.around() malfunctioning, not setting this to the passed object's scope?
Merc.
It is not very easy to follow what exactly you're asking. From your jsFiddle, I see this comment so I'll attempt to answer the question you pose here:
// QUESTION: FIND OUT WHY WE NEED THIS "call"
return originalValidator(value);
// return originalValidator.call(this, value);
The answer to why you need the .call here in order to preserve the value of this is as I described below in the generic description of how this works when making a function call.
When you make an ordinary function call as in this statement:
return originalValidator(value);
The value of this is set back to window. That's how javascript works. If you want to preserve the current value of this in that function, you have to specify that you want a particular value of this set using .call() or .apply() or an obj.method() call. The value of this in an ordinary function call is NOT bound to the function. It's set by the caller and can be anything the caller wants. If you don't specify it, then javascript sets this to window and that is exactly what is happening in your code.
Here's the generic description of how the value of this is set and this generic description applies in your specific case.
The simple rule is that the value of this is reset on every single function call in javascript. If it's just a plain function call, then this is set to the global object (which is window in the browser environment). So any simple function call will always set this to window.
If you make a method call like obj.method(), then this will be set to point to the obj while in the method().
If you use func.apply(a, b) or func.call(a, b) then you can explicitly control what this is set to via the value of the first argument to .apply() or .call(). See this MDN doc here or here for more info on .call() and .apply().
this is the current context. By default it's the global object (or null in strict mode), when calling a function on an object (foo.bar()) it's set to that object. When using .call() or .apply() to call a function it's set to whatever first argument was passed to that function.
This means that you cannot assume that this is still the same when you go into another function - even if you define that function in a context where this is what you want.
The most common approach is adding var self = this; and then using self instead of this in the inner function - since self is a normal variable it will be in the function's closure and not be affected by this being bound to something else in the function.
I have recently started to delve deeper in to JavaScript and have come across this code construct in JQuery.
(function( window, undefined ) {
})(window)
Reading on stack overflow (and elsewhere) I have come to the conclusion that this is the same as
function foo(window, undefined) {
...
}
foo(window);
Am I correct in my assumption?
If so, what are the advantages of the former? (other than confusing newbs)
There are several things you need to know to make sense of it:
It is an anonymous function, which simply means it does not have a name.
The function is called immediately after it is declared. You see the open parenthesis on line 2, immediately after the function definition? That means, "call this function".
Only one parameter is passed to the function. That parameter is "window", which is the name of the global scope inside of a browser.
The function being called actually expects *2* parameters, but we're calling it with one. Javascript lets you call functions with more or fewer parameters than the function actually expects. There are ways of getting to the list of parameters that was passed.
Since we are only passing one parameter, the second parameter will automatically be set to "undefined". "undefined" is a special javascript value that means, get ready, "undefined".
It just so happens that we have also named our second parameter with the name "undefined". So in effect, we have created a local variable (parameters are very much like local variables) that is named undefined, and whose value is undefined.
Why on Earth did we do that? It is a way of ensuring that, within our anonymous function, if we refer to "undefined", it really will have the value of "undefined". If we didn't do that, and some crazy code outside of our scope redefined "undefined" (by saying something like "undefined = 42"), then we'd write code thinking we were referring to undefined but we'd actually be referring to 42. These shenanigans with passing 1 parameter but expecting 2, and calling the second one undefined, protects us from such nonsense.
I hope that's clear, let me know if it is not. I learned all that from Paul Irish's video mentioned above.
This is an anonymous function. It is created and then goes out of scope, which here is the advantage. It is created and instantiated immediately. What is good about this is that it is not going to collide with any function on the global namespace, and thus will not obliterate anything you may have included on the page.
It is an anonymous function, it has quite a few benefits, like being only active in the current scope. You can read more about it here.