I am trying to sharpen my JavaScript skills and I am aware that there are four basic ways to invoke a function - which alter the way this is defined. The two I am interested in are the basic two:
Invocation as a function
Invocation as a method
Which is fine. The first, this will refer to the window object:
function doSomething() {
console.log(this);
}
doSomething(); // window is logged
And the second this will refer to the object it is being executed from within:
var t = {
doSomething: function () {
console.log(this);
}
};
t.doSomething(); // t is logged
Which is all fine. However, is it correct to say, that in these two invoking methods, this is always going to return the object the method is contained within (if that makes sense)?
In the first example, doSomething() is, in reality, defined within the window object - so is a property of the window object, even if we do not define it (or reference it).
Therefore, can it not be said that, in reality, invocation as a function is invocation as a method? Or not?
Imagine defining your function, not in the scope of the global object like you did, but in the scope of another function:
function outer() {
var inner = function(){console.log(this)};
inner();
};
outer();
What do you think the this will be bound to ? What will be printed ?
You might believe it will be the outer function object but its turns out that it will always be the global object.
It is just as if you had written:
function outer() {
var inner = function(){console.log(this)};
inner.call(window);
};
outer();
This is a quite hazardous and far from intuitive JS "feature".
So, to get back to your first example, what you are doing is basically this:
doSomething = function () {
console.log(this);
}
doSomething().call(window);
And, like Yoshi pointed out, if you were using the ES5's strict mode, you would end up doing something like that instead, which is, in my opinion, far less dangerous:
doSomething().call(undefined);
It also gives you a strong hint about the fact that you should never use this in a function ;)
Related
I have a javascript file in which I write a bunch of jquery functions. I have a function to return the angular scope. I found out that if I were to write the same function twice, the code still executes.
function getngScope()
{
alert(2);
return angular.element($('#data-area')).scope();
}
function getngScope()
{
alert(1);
return angular.element($('#data-area')).scope();
}
When I call getngScope() I get "1" alerted and the scope returned. Why does it have this behavior?
The second definition of an Object overwrites the first one. In general the last definition of an object overwrites all previous definitions.
Functions in JavaScript are Objects:
(function () {}) instanceof Object === true
When you create a new global function f it's equivalent to creating a property in the window object and assigning the function definition to that variable, if you create a function:
function myFun() { console.log('my function') };
and then check the value of window.myFun you'll notice it is the same function as myFun:
window.myFun === myFun // true
You'll also notice that modifying window.myFun changes/overwrites myFun.
E.g.
function myFun() { console.log('myFun') };
myFun(); // Prints: 'myFun'
// Overwrite myFun
window.myFun = function () { console.log('NoFun') };
myFun(); // Prints: 'NoFun'
The second definition of the function takes precedence.
I recommend you read the chapter on Functions from JavaScript: the good parts by Crockford.
functions are data in memory stack, so when you define another function with the same name, it overrides the previous one.
Well obviously you’re not meant to define the same function twice. However, when you do, the latter definition is the only 1 that applies. Try not to do that. Find another way other than giving two functions the same name.
The second function replaced the first function,you could always change this by modifying the name of the function ,if not you can add multiple arguments ..if that is ever needed...and for the explaination to this behaviour,unlike other programming languages javascript doesnt return any errors while being executed..so u can assume that it just corrects itself during the execution by overwriting the function.
Sorry for the rather beginner question. What's the differences of function usage between
$(document).keypress(function() {
//some code
});
and
var somethingElse = function() {
//some code
};
I know the latter is to create a function similar to Java's
public void somethingElse() {
//some code
}
but I always assume the former as anonymous function that act inside a method. Can someone shed me some light regarding this? Thanks.
The first one is a jQuery shortcut to create an event listener.
It's equivalent to:
document.addEventListener('keypress', function() {
// some code
});
More info: http://www.w3schools.com/jsref/met_document_addeventlistener.asp
Now, about named or anonymous functions, what's the difference between
var doSomething = function() {
// some code
};
and this?
function doSomething() {
// some code
}
There's no difference for the developer. Of course there's a difference on memory, but in javascript developers don't have to take care of it.
Actually for the case of an event handler or other techniques that use callback functions, you can pass an anonymous function or a previously declared one, it's exactly the same:
$(document).keypress(doSomething);
or
$(document).keypress(function() {
// some code
});
creates an anon function and passes it to the handler
creates an anonymous function and a variable that references it.
creates a named function - that is hoisted
the hoisted function becomes available to you at any line within your function scope, while the non-hoisted function will be undefined until the line where it is declared runs.
there is no difference between #2 and #3 (other than the hoisting) - some people think that the first one creates an object and the 2nd one is some magical thing, or a global function, but nope - they are both function objects within your scope.
The former is a callback, meaning some instructions that will be executed ONLY as soon as the keypress event in your example is triggered.
Thus, a function's name is not required.
Function expressions, the latter, is mostly used when adding an object's property acting as a method like:
var myObject = {};
myObject.sayHello = function() {
alert("Hello");
}
Is this:
(function(a) {
return 3;
})(this);
equivalent to:
(function() {
return 3;
})();
If there are any differences, please explain
Here's the difference I think you're looking for: the second example has access to the outer this (through the a variable), while the second example does not.
Normally, you don't need to pass in arguments to an IIFE (although you certainly can, to get more readable or modular code), because newly-declared functions have access to their outer scope variables:
var foobar = 5;
(function() {
// I can use the outer-scope `foobar` in here!
})();
However, this is an exceptional case, because the newly-created function will have its own this that will shadow the outer this:
// outer here, `this` is one thing
(function() {
// in here, `this` might be something else
// because each new functions invocation sets `this` within the function
})();
You can see shadowing behavior with non-this variables like this:
var foobar = 5;
(function() {
var foobar = 7;
// I can't use the outer-scope `foobar`
// because it is shadowed by local-scope `foobar`
})();
A similar thing happens with this. In my foobar example, the shadowing was done explicitly, but with this, the shadowing always happens, because each function gets a new local-scope this.
You can access the outer this by aliasing it a new name, done here by formal argument:
// outer here, `this` is one thing
(function(outerThis) {
// in here, `this` might be something else
// but `outerThis` refers to the outer `this`
})(this);
If you don't alias the outer this to a new name, you will not have access to it, because it will be shadowed by local this. Note that you can also alias your outer this to another outer-scope variable, like:
var outerThis = this;
(function() {
// we can access the outer-scope `outerThis` because it is not shadowed
})();
Well, the first you're passing an argument to, but it is never used. However, the functionality is the same for both. The second is slightly faster, due to not passing an argument for no reason, assuming this isn't just optimized away.
It depends on how you define equivalent.
If you define it in terms of what the functions actually do, then, yes, they are equivalent. Although, of course, this is only true for their current content. One difference is that the first one has access to the outer this, while the second one doesn't - although this does not matter in your example.
Regarding to your comment whether just passing this makes a difference here: No, it does not.
If you define equivalent in a different way, then the functions may be different, e.g. when defining equivalent as having the same arity.
I guess the obvious counter-question would be what's the use case behind your question: Why do you ask this? (If it's not just out of curiosity and for academical reasons.)
In some of my Javascript objects I find that my this pointer is correct - these are new Func() -type objects - when created, but in the assigned methods it can be wrong.
function Confused() {
console.log("checking",this==window,"is always false");
this.method = function() {
console.log("checking",this==window,"is true for some funcs but not others");
};
};
On some calls to (new Confused()).method() - it seems to have lost it's this pointer. The times this happen seem dependent on the function, rather than random; its something in the code around how I'm creating classes that is causing this.
An example is online at http://williame.github.com/barebones.js/ and the member callback G3D._file_loaded has a wrong this pointer when called sometimes.
Why, and how do I fix it?
There are 4 ways to use a function in Javascript
what each of these does is change what the content of this is :
function calls: this = global object (window in browser)
method calls: this = object it is called from.
constructor calls: this = new object you are creating.
call/apply calls: this = object you passed.
In your case this == window when you call the function directly (Confused()) but if you call using new (new Confused()) then it will be the new object you are creating.
The this keyword refers to the calling context. It is never wrong but it may not be what you would have expected it to be.
You can manually set context when calling a function, if you call it with .call or .apply.
Furthermore, if a reference to window is what you want, why not use window instead of this? It's a way more reliable means of accessing the window object.
In addition to David Hedlunds explanation, you can "work around" that problem like this:
function Confused() {
var that = this;
console.log("checking",that==window,"is always false");
this.method = function() {
console.log("checking",that==window,"is always false");
};
};
The problem is that the whoever actually invokes your function has control over context of your function. If you do not control the function invocation (that is, if you can't modify the code), than you are stuck with the solution I gave (at least I know of no other way).
While the solution seems a little "hackish", it really isn't if you think about it. It simply harnesses the power given to you by closures :D
I have tried to figure this out or search for it on google, i can only find how to create objects, not exactly how functions work. If someone could explain to me how encapsulation works.
function myObject() {
this.variable1 = "tst";
this.function1 = function() {
//Now this function works. A 'this' function to a private function is ok
_PrivateFunction1();
//Here is error one, I cannot seem to call methods within the object
//from.
this.function2();
}
this.function2 = function() {
alert("look! function2!");
}
function _PrivateFunction1() {
//This does work though. I am confused.
_PrivateFunction2();
}
function _PrivateFunction2() {
alert("look! PrivateFunction1");
//this does not work.
alert(this.variable1);
}
}
I think I can explain this better if we go in reverse order. First, we define some functions:
function _PrivateFunction1() {
//This does work though. I am confused.
_PrivateFunction2();
}
function _PrivateFunction2() {
alert("look! PrivateFunction1");
//this does not work.
alert(this.variable1);
}
This is pretty normal stuff. The only thing that's weird is that they appear inside another function, but that's perfectly fine. JavaScript has function scope, which means that all variables defined inside a function are defined in a new scope. They do not trample on the global namespace. And functions are first-class objects in JavaScript, which means they can be used just like other data types. They can be nested, passed to functions, returned from functions, etc.
Then we run into some trouble:
function _PrivateFunction2() {
alert("look! PrivateFunction1");
//this does not work.
alert(this.variable1);
}
}
Functions in JavaScript are always executed in some context which is referred to by the this keyword. When you call a function directly (i.e. like this: functionName()) the context in which that function executes is the global window object. So, inside _PrivateFunction2, this.variable1 is equivalent to window.variable1 which is probably not what you meant.
You probably wanted to refer to the current instance of myobject which is what this refers to outside of _PrivateFunction2. You can preserve access to this in an inner scope by storing a reference to it in another variable:
var _this = this;
function _PrivateFunction2() {
alert("look! PrivateFunction1");
//this does not work.
alert(_this.variable1);
}
There's something subtle here you should notice. _PrivateFunction2 has access to the variables defined in its lexical scope, which is why it can access _this. This will be important later.
Next up:
function _PrivateFunction1() {
//This does work though. I am confused.
_PrivateFunction2();
}
This should be the most normal-looking section to you, I would think. There's nothing strange going on here. Just one regular function calling another one. Don't be confused by the fact that these are nested inside myObject. That changes the scope they're in, but not much else.
Next we define some instance variables and methods:
this.variable1 = "tst";
this.function1 = function() {
//Now this function works. A 'this' function to a private function is ok
_PrivateFunction1();
//Here is error one, I cannot seem to call methods within the object
//from.
this.function2();
}
this.function2 = function() {
alert("look! function2!");
}
Here this really does refer to myObject, assuming -- and it's an important assumption -- that myObject was called with the new operator, like this:
var obj = new myObject();
If it had been called like this:
var obj = myObject();
Then this would refer to the window object, just like it did for the functions we saw earlier. The key takeaway is that the value of this is not fixed. It's determined by the way in which the function is called. There are even ways to set it to an arbitrary object explicitly.
The value of this inside this.function1 will also be the current instance of myObject, because it will most likely be used like this:
var obj = new myObject();
obj.function1();
Writing object.method() sets this to object inside method.
So how is this.function1 able to call _PrivateFunction1()? Just as we saw earlier when saving the value of this for use inside a nested function, _PrivateFunction1() is just another object defined in this.function1's lexical scope, so it is available for its use, just as _this was earlier.
And it's because of closure that these private variables are still alive long after myObject has returned.
Footnote: Because failing to use new when instantiating objects breaks things so spectacularly without warning, it's considered good practice to capitalize the names of functions you intend to be used as a constructor. So myObject should really be MyObject.
You have to save a copy of the actual object like here note the var that = this
Tested in chrome and FF
for encapsulation I would prefer module pattern like
var someMethod = function(){
var i,
length,
// public method
public = function(num1, num2){
return num1+num2;
},
//private method
_private = function(){};
//exposing the public method
return{
public:public
}
};
var callPublic = someMethod();
callPublic.public(20, 30);// call the public method and return 50
now , if you try to call that private method like
callPublic._private();//it will return not a function since its not been exposed
There are lot of other pattern to encapsulate your methods but module pattern is most common. Hope ot will help you how to encapsulate data in javascript.