What is the point of the `Function` identifier on `window`? - javascript

If you open your console and type Function, it auto completes it for you, indicating that the indentifier Function is part of the winddow object. It appears as though the Function identifier refers to an empty anonymous function.
What is the point of the Function identifier on window?

Function is a global variable. Global variables are properties of the global object. In browsers, the global object is window.
If you are asking what the purpose of Function itself is: It's a constructor function (just like Object, Array or RegExp) to create new function objects. It lets you create a new function from code contained in a string (almost like eval). E.g.:
var myFunc = new Function('return 42;');
console.log(myFunc()); // 42
Functions created this way behave like they had been declared in global scope, i.e. they do not close over the scope they actually have been created in.
This can be useful for browser tools which evaluate user provided JS code provided, like the Babel REPL.

Related

Can we Change the definition of predefined functions? Then How to Prevent it? [duplicate]

This question already has answers here:
Is 'window' always on top of the scope chain in javascript?
(5 answers)
Closed 8 years ago.
As I understand from my practice (in the Google Chrome Console), we can change the definition of predefined functions. Let me explain through code:
function alert(){
return 2+2;
}
and I am calling alert("hi"), it is returning 4, it's Ok, as we have defined.
But, even when I call window.alert("hi"), it is returning 4, which is unexpected (for me).
Here I just created a new function, I have not mentioned any object name or Prototype property, but still it is overriding the window object properties itself.
My doubt is, if we change the definition of the function, will it override the definitions of a function with the same name in all the objects??
Let's say I have two objects objA and objB, both are having a function named strange(). Now I am defining a function strange() in the outside of both the objects. Then, whether it will override the definition of strange() in both objA nad objB? If so, why?
If so, how to prevent this? means how to prevent the overriding in all the objects?
Thanks in advance...!!!!
No - by declaring function alert() you are redefining window.alert() function because the default scope is window
var newObj = {
alert: function() {
return "this is a functino on my newObj object";
}
};
function alert() {
return 2 + 2;
}
console.log(alert());
console.log(window.alert());
console.log(newObj.alert());
The reason defining alert overrides the window property is because you declared it in the global context; anything declared in the global context will, by default, attach itself to window. To not override the window object, declare your function inside another function (or use a different name):
// This creates an anonymous function
(function() {
// Since alert is defined in this function (not the global scope)
// It won't override window.alert
function alert() { /* Do something */ }
})();
// You can no longer access the old alert here, so alert will refer to window.alert
In addition, if you add alert to a specific object, it will not change the alert of any other object, unless you use a with statement (considered bad practice).
var myNamespace = {
alert: function() { /* Custom alert */ }
}
// Will not change myNamespace.alert
function alert() {}
No I don't think so - with the alert function, the "window." prefix is assumed so really window.alert() and alert() are the same thing. I guess it's a short-cut to stop you havign to type window. all the time.
Regarding your other example, objA.strange() isn't related to objB.strange() (assuming objA and objB are in fact different objects).
the function strange() outside of both these objects is actually in window.strange() (it's implied) so again it's a different function under a different object.
You can, I gather, use prototype to redefine native JS functions, but this is normally undesirable.
If you define a variable or function in the default scope in javascript (creating a function directly inside a <script> tag for instance), it is considered part of the window object (if javascript is executed in a browser environment).
So, when you call (the default) alert, you arev actually calling window.alert.
Let's say I have two objects objA and objB, both are having a function
named strange(). Now I am defining a function strange() in the outside
of both the objects. Then, whether it will override the definition of
strange() in both objA nad objB
A definition of strange outside both the object scope (closure) will not impact the definition of the function (method) in the object. But if you define strange within the object again, the latter one will shadow the previous one.
It boils down to the scope of the function and the closure withing which the function (or variable) is defined.
See also
Functions and function scope from MDN. This will answer most of your questions
Closure from John Resig's Learning Advanced Javascript

How does javascript's 'this' binding work when assigning a "method" to another variable?

Consider:
function Thing() {
this.prop = null
}
Thing.prototype.whoIsThis = function() {
console.log(this)
}
a = new Thing()
a.whoIsThis() // logs '> Thing {...}'
f = a.whoIsThis
f() // logs '> Window {...}'
So this is not bound to the Thing in the second call. How does this work in this situation? Isn't a.whoIsThis a "method" of a Thing regardless of any variable its assigned to?
When you say a.whoIsThis, it will refer the function object only. The function object will have no reference to the object on which it is attached. But when you invoke the function, JavaScript dynamically decides the current object and sets that as this inside the function.
This dynamicity allows us to use any object as the current object in the runtime.
But when you simply invoke a function object, without any object reference, by default, JavaScript will set this as the global object (window object in browser) and in Strict mode, this will be set to undefined.
A function's this keyword behaves a little differently in JavaScript compared to other languages. In most cases, the value of 'this' is determined by how a function is called, when 'this' is inside a function.
1) When a function is called as a method of an object, its this is set to the object the method is called on.
2) When a function is called directly, the value of this is not set by the call. Since the code is not in strict mode, the value of this must always be an object so it defaults to the global object. In strict mode, the value of this remains at whatever it's set to when entering the execution context, so 'undefined'.
More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
This binding is decided at run time and not at author time
having f = a.whoIsThis is just another reference to the function WhoIsThis
now Imagine If you have the function declared in the global scope..which is really what f is now..and when calling f JS at run time run the function as if it was declared in the global scope(as I mentioned) so It asks ..what this refers to if I'm in the global scope => default binding rule would answer..it's simply the global(window) object

what's correct: var declaration if undefined

I have heard different opinions about the usage of var at a situation like this:
function(maybeUndefined) {
if(typeof maybeUndefined === 'undefined')
var maybeUndefined = 'bob';
}
Is it necessary to notate var, or not, because maybeUndefined is an argument of function?
You do not need the var in this case, as mayBeUndefined is already allocated within the scope of the function (hint: listing argument variables in a function definition causes those variables to be declared locally). That var is therefore completely optional, though completely pointless (and a drain on readability).
Example:
function func ( arg1, arg2 ) {
var local1, local2;
function nested1 () {}
function nested2 () {}
// other code
}
Here we have a function declaration. When this declaration is parsed into a function object, a lexical environment (= scope) is created for that function with the following bindings:
arg1
arg2
local1
local2
nested1
nested2
this
arguments
(Notice how there also are two special, built-in bindings: this and arguments. These are always created for all function objects.)
These names are defined as local bindings. (This process is specified in "Declaration binding instantiation". Warning: this algorithm is not meant to be read by humans :-)) Therefore, when a name is defined as a parameter, it is not necessary to declare it as a local variable. This mechanism is independent of whether a value (argument) is passed for that parameter when the function is invoked.
So, even if you invoke the function like so:
func(123);
the name arg2 will still be defined (as a binding in the function's environment), although its value will initially be undefined for that particular invocation.
Btw, if you use the strict language (recommended!), function environments are static which means that the above bindings are garanteed to be the only bindings in the function's environment. The default language, on the other hand, provides certain mechanisms to, dynamically, add/remove bindings from the function's environment. Example:
(function () {
// the name "temp" does not exist as a binding in the function's environment
eval('var temp');
// now it does
delete temp;
// and it's gone again
}());
You should not use var again, it is bad for readability, and the variable will already be scoped locally as a result of being an argument.
Also, you should note that it is not a part of this. this will only be scoped to the function object if the new keyword has been used, and as you do not have a named function, that seems unlikely in this case. Without new, this refers to window (or is undefined if use strict; is used), of which your variable is definitely not a part of as a result of the argument having a local scope.
Interfacing
Including a function argument is effectively the same as scoping a variable (in other words, it's effectively the same thing as defining a function-level reference using the var keyword). The main reason for providing function arguments (in JavaScript) is for your own interfacing preference.
The arguments object
Arguments may still be passed to functions without parameters, and will still be accessible in the 'hidden' arguments object -- which is sort of a "pseudo-array" (if you will), in that it is functionally an array, but is not equipped with the same APIs JavaScript equips the Array (pseudo-type) with:
// The following functions do the same thing, but one is "more readable"
function foo() {
return arguments;
}
function bar(baz, qux) {
return arguments;
}
Evaluation (interface) vs Execution (implement)
When both functions are evaluated (on file 'load'), the arguments object is undefined in every function definition; the object doesn't become "defined" until the function body executes the code therein; to visualize that using pseudo-code, it'd look something like this:
// Function bodies (as objects)
foo : {
arguments : new Array // [undefined]
__proto__ : Empty() // the super-object that allows this object to inherit "functionality"
}
bar : {
arguments : new Array(baz, qux) // [undefined, undefined]
__proto__ : Empty()
}
Function invocation
So when you invoke a function, it "implements" or "executes" its body (its "object"). When it does that, if the objects that have been pushed into the arguments object are defined, then the function can reference them. If not, a reference error will be thrown, logging that the variables are undefined in that scope.
In short:
It isn't necessary to interface function-scope-level variables (aka "private members") using var because the language already attaches the arguments object to all function body objects.
More reading:
JavaScript Memoization: "Function-caching" multiple arguments for better performance:
http://decodize.com/javascript/javascript-memoization-caching-results-for-better-performance/

Function context ("this") in nested functions

When you invoke a top-level function in Javascript, the this keyword inside the function refers to the default object (window if in a browser). My understanding is that it's a special case of invoking the function as method, because by default it is invoked on window (as explained in John Resig's book, Secrets of the JavaScript Ninja, page 49). And indeed both invocations in the following code are identical.
function func() {
return this;
}
// invoke as a top-level function
console.log(func() === window); // true
// invoke as a method of window
console.log(window.func() === window); // true
So far so good... Now here is the part I don't understand:
When a function is nested in another function and invoked without specifying an object to invoke on, the this keyword inside the function also refers to window. But the inner function cannot be invoked on window (see code below).
function outerFunc() {
function innerFunc() {
return this;
}
// invoke without window.* - OK
console.log(innerFunc() === window); // true
// invoke on window
//window.innerFunc(); - error (window has no such method)
console.log(window.innerFunc) // undefined
}
outerFunc();
It makes perfect sense that the nested function isn't available on window, as it is after all nested... But then I don't understand why the this keyword refers to window, as if the function was invoked on window. What am I missing here?
EDIT
Here is a summary of the great answers below and some of my follow up research.
It is incorrect to say that invoking a function "normally" is the same as invoking it as a method of window. This is only correct if the function is defined globally.
The function context (the value of the this keyword) does not depend on where / how the function is defined, but on how it is being invoked.
Assuming that the code is not running in in strict mode, Invoking a function "normally" will have the function context set to to window (when running in a browser, or the corresponding global object in other environments).
An exception to the above rules is the use of bind to create a function. In this case even if the function is invoked "normally", it could have a context other than window. That is, in this case the context is determined by how you create the function, rather than how you invoke it. Although strictly speaking this isn't accurate, because bind creates a new function that internally invokes the given function using apply. The context of that new function will still be determined by the way it's invoked, but it shields the context of the function it internally invokes by using apply.
By invoking "normally" I refer to the following simple way of invocation:
myFunction();
To complete the picture, here is a brief coverage of other ways of invocation and the corresponding context:
As a property of an object (method) - the context is the object
Using apply or call - the context is specified explicitly
With the new operator (as a constructor) - the context is a newly created object
Feel free to update the above as necessary, for the benefit of people with similar questions. Thanks!
You can call any function that is in scope with functionName(). Since you haven't called it on an object, it will be called in the context of the default object (window). (IIRC, it will be called in the context of undefined if you are in strict mode).
The default object for context has nothing to do with where a function is defined or what scope that function appears in. It is simply the default object.
If a function is a property of an object, you can call it as reference.to.object.function(), and it will be called in the context of object instead of the default object.
Other things that change the context are the new keyword and the apply, call, and bind methods.
In JavaScript, when a function is invoked without an explicit context, the context is the global object. In the case of web browsers, the global object is window.
Additionally, JavaScript has functional scope, so any variables or functions within a function are not accessible in a scope outside of that function. This is why you can't access window.innerFunc.
Whether a function is nested inside another one has nothing to do with the value of this when the function is called. The only things that matter are:
If the function is "found" by traversing a property on an object, then the value of this will be a reference to that object:
someObject.prop( whatever );
It doesn't matter how the function was declared.
If you use call() or apply() to invoke a function, then the value of this is taken from the first argument to whichever of those functions you use.
If you've created a bound wrapper for the function with bind(), then the value of this will be as requested when bind() was called.
If you're calling a function as a constructor with new, then this will refer to the newly-created object instance.
Otherwise, this is either a reference to the global context, or else it's undefined (in "strict" mode or in an ES5-compliant runtime).
The "location" in the code where a function is defined does matter, of course, in that the scope includes whatever symbols it includes, and those are available to the function regardless of how a reference to it is obtained.
It does not depend where the function is declared but how it is called:
var obj = {
f: function() {
return this;
}
}
var f = obj.f;
console.log(obj.f()) // obj
console.log(f()) // window/default obj
Or in other words. The syntax obj.f() executes the function with this=obj while f() executes the function with this=window. In JavaScript the caller specifies the value of this.
When you define func in the global scope, it actually is assigned as a property of the window object. That is, the window object holds all globally scoped variables. (*) Therefore, func and window.func represent the same thing. innerFunc is defined inside a function scope and is not available outside of that scope. Therefore, window.innerFunc is (still) undefined.
However, the this context is determined by how you call the function. When you call a method like obj.method(), the this context is set to obj. On the other hand, you can also call the method on its own:
var f = obj.func;
f(); // in this call: this === window
In this case, you're not calling a function on an object and thus the this context is set to the default. The default however is the global scope and as stated above, this is represented by window.
You can always override the this context by using Function.prototype.call() or Function.prototype.apply() which take a this context as first argument. For example:
var f = obj.func;
f.call(obj); // in this call: this == obj
(*) Note that this only applies to JavaScript running inside a browser. In other environments, this may differ. For example, in Node.js the GLOBAL variable holds the global scope.

Are non-top-level functions members of any object?

I know that top-level functions are members of the window object, and it's consistent with the fact that this inside them refers to the window.
But for non-top level functions, this is still window, but they are not members of window!
Here's some code:
function topLevel1() {
alert(this)
}
function topLevel2() {
function inner() {
alert(this)
}
inner()
}
topLevel1() // alerts DOMWindow
alert(window.topLevel1) // alerts text of topLevel1, as expected
topLevel2() // again, alerts DOMWindow
alert(window.inner) // undefined
alert(window.topLevel2.inner) // undefined
If inner is neither a member of window nor of topLevel2, whose member is it?
How can it be that it's this is window, but it's not a window's member?
Isn't it a law in Javascript that if this == owner, then the current method was called via owner.? (except special cases like constructors, apply, call, etc)
Again, the this value of a function is decided of how the function is invoked, not where it is located or how it was designed.
If you just call a function
foobar()
anywhere in your code, just like that, its this value will always be window (non-strict mode) or undefined (strict). Now there are plenty of ways to modify the this, like calling the function with .apply(), .call() or .bind(). All of those methods give your the opportunity to modify the this value for a given function. Also, if you call a function with the new keyword, this referes to a newly created object (which is also returned).
So, location of a function tells you zero about its context or this.
Now to answer your specific questions:
inner is a member of the Activation Object from topLevel2 (ES3)
described above
I guess thats also covered above
A fantastic reference of the this keyword is: http://www.quirksmode.org/js/this.html
The inner() function inside topLevel2() can only be visible to topLevel2. It's a scope issue. That's why you get undefined.

Categories