Why does the following work:
function sum(a,b) { return a + b; }
var result = sum.call(null,3,4); // 7
Why is result defined? I am invoking sum as a method of null. But null is not an object and cannot have properties!
What is going on?
The first argument for Function.prototype.call is the context, which defines the this value for the execution context of the invoked function, nothing else.
So basically, you're saying that this is referring to null (at least, in ES5 strict mode), but since you don't access this anyway, it makes no difference.
In non-strict mode, this cannot be null, so it's replaced with the global object instead.
When you use .call or .apply with null or undefined, the default this (usually window) is automatically used instead if not in strict mode.
From MDN (emphasis mine):
thisArg
The value of this provided for the call to fun. Note that this may not be the actual value seen by the method: if the method is a function in non-strict mode code, null and undefined will be replaced with the global object, and primitive values will be boxed.
If you are in strict mode, it actually will be null or undefined.
(function() {
'use strict';
return this;
}).call(null); // null
(function() {
'use strict';
return this;
})(); // undefined
Its not. NULL in this case specifies to what object the this keyword is bound to. In your method, by setting it to NULL it will either not have a this variable binding or it will be bound to the function itself or the window.
Since you're not using any variables or functions that are accessed via this, then there's no need to use the call method ... you can just use sum(3,4)
As stated in, for example, MDN, the first argument is
The value of this provided for the call to [the method]. Note that
this may not be the actual value seen by the method: if the method is
a function in non-strict mode code, null and undefined will be
replaced with the global object, and primitive values will be boxed.
As the MDN explained.
thisArg
The value of this provided for the call to fun. Note that this may not
be the actual value seen by the method: if the method is a function
in non-strict mode code, null and undefined will be replaced with the
global object, and primitive values will be boxed.
Simply put it by a little code.
<script >
'use strict'
function fun() {
alert(this);
}
fun.call(null);
</script>
In the strict mode ,this is null. But in the not strict mode . this is window or global object.
Related
I know that according to ECMAScript specification, non-strict methods will have thisArg transformed to the global object, if null or undefined was passed to them.
That's the reason this code logs the window object (in browsers) instead of null:
function x() {
console.log(this);
}
x.call(null);
What I don't understand, is why doing the same thing with Object.prototype.toString.call(null), doesn't transform null to the global object, but keeps it as null and returns the string [object Null].
Is it because 'use strict' is used in default implementation of toString method?
Is every built-in method run in strict-mode?
I couldn't find anything like that in the specification a https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-object.prototype.tostring.
Is every built-in method run in strict-mode?
Yes. It says so in ยง10.3 Built-in Function Objects:
"Built-in functions that are ECMAScript function objects must be strict functions."
This not only implies non-sloppy handling of the this argument, but also that these functions have no .arguments, .callee and .caller properties.
In the browser, it is expected that this, inside an IIFE, points to the window object. However, it is undefined in this case.
(function () {
"use strict";
console.log(this) // undefined
// more stuff
}());
In ECMAScript 5's strict mode only, when the value of this is undefined or null (i.e. when not in an object's scope or this is explicitly set), this will not return the global object from the function scope.
What actually happens when a function is called is the following - the ThisBinding is jargon for the value of this when called (ECMA-262).
10.4.3 Entering Function Code
The following steps are performed when control enters the execution context for function code contained in function object F, a caller provided thisArg, and a caller provided argumentsList:
1. If the function code is strict code, set the ThisBinding to thisArg.
2. Else if thisArg is null or undefined, set the ThisBinding to the global object.
If you want the global object, you can use a global variable that is defined in the global scope or use some hacks around this, such as using an immediately invoked new Function()1.
1: Using new Function() works as it does not go into strict mode unless the function has the pragma 'use strict'; within the body of the new Function() itself (reference).
From MDN, under "Securing" JavaScript
First, the value passed as this to a function in strict mode isn't
boxed into an object. For a normal function, this is always an object:
the provided object if called with an object-valued this; the value,
boxed, if called with a Boolean, string, or number this; or the global
object if called with an undefined or null this. (Use call, apply, or
bind to specify a particular this.) Automatic boxing is a performance
cost, but exposing the global object in browsers is a security hazard,
because the global object provides access to functionality "secure"
JavaScript environments must restrict. Thus for a strict mode
function, the specified this is used unchanged:
Example:
"use strict";
function fun() { return this; }
assert(fun() === undefined);
assert(fun.call(2) === 2);
assert(fun.apply(null) === null);
assert(fun.call(undefined) === undefined);
assert(fun.bind(true)() === true);
One way to pass the global object in explicitly in strict mode is to use call(this)
(function(){
"use strict";
console.log(this) // this points to window
// more stuff
}).call(this);
John Resig wrote:
Finally, a long-standing (and very annoying) bug has been resolved: Cases where null or undefined is coerced into becoming the global object. Strict mode now prevents this from happening and throws an exception instead.
(function(){ ... }).call( null ); // Exception
what bug is he referring to?
Basically, you are using the call() method from Function.prototype, which by default takes scope as the first parameter. If execution scope is undefined or null, it defaults to the global object. In some situations, using the call method with an Immediately Invoked Function Expression(the above code is rather uncommon) doesn't use the global object as the default fallback execution scope.
If this is evaluated within strict mode code, then the this value is not coerced to an object. A this value of null or undefined is not converted to the global object and primitive values are not converted to wrapper objects. The this value passed via a function call (including calls made using Function.prototype.apply and Function.prototype.call) do not coerce the passed this value to an Object (10.4.3, 11.1.1, 15.3.4.3, 15.3.4.4 clauses of the ECMA language specification).
Please explain what hack is used here (I can see that null is passed as a context to a function returning a property of it's context. So I can't clearly understand what is actually happening here.
function getGlobal(){
return (function(){
return this.dust;
}).call(null);
}
Setting the context to null will make this pointing to the global object. So the code provided will act as accessing the dust property of the global object.
According to the specification of ECMA 262 v5, 10.4.3 Entering Function Code
if thisArg is null or undefined, set the ThisBinding to the global object.
see http://es5.github.com/#x10.4.3
The trick is to use the fact that if you don't have a receiver of the function, window (in fact the global object of the executed script, hence the name) is used.
So this trick enables to bypass a property (dust) defined in the nearest embedding context and use the one defined in the global object.
There are things like
f.call(...)
f.apply(...)
But then there's this
(1, alert)('Zomg what is this????!!!11')
"1" does not seem to mean much in this context, the following works just fine:
(null, alert)('Zomg what is this????!!!11')
(1, null, alert)('Zomg what is this????!!!11')
(undefined, alert)('Zomg what is this????!!!11')
Could you point to a specific part of ECMAScript which describes that syntax?
You are just using The Comma Operator.
This operator only evaluates its operands from left to right, and returns the value from the second one, for example:
(0, 1); // 1
('foo', 'bar'); // 'bar'
In the context of calling a function, the evaluation of the operand will simply get a value, not a reference, this causes that the this value inside the invoked function point to the global object (or it will be undefined in the new ECMAScript 5 Strict Mode).
For example:
var foo = 'global.foo';
var obj = {
foo: 'obj.foo',
method: function () {
return this.foo;
}
};
obj.method(); // "obj.foo"
(1, obj.method)(); // "global.foo"
As you can see, the first call, which is a direct call, the this value inside the method will properly refer to obj (returning "obj.foo"), the second call, the evaluation made by the comma operator will make the this value to point to the global object (yielding "global.foo").
That pattern has been getting quite popular these days, to make indirect calls to eval, this can be useful under ES5 strict mode, to get a reference to the global object, for example, (imagine you are in a non-browser environment, window is not available):
(function () {
"use strict";
var global = (function () { return this || (1,eval)("this"); })();
})();
In the above code, the inner anonymous function will execute within a strict mode code unit, that will result on having the this value as undefined.
The || operator will now take the second operand, the eval call, which is an indirect call, and it will evaluate the code on the global lexical and variable environment.
But personally, in this case, under strict mode I prefer using the Function constructor to get the global object:
(function () {
"use strict";
var global = Function('return this')();
})();
Functions that are created with the Function constructor are strict only if they start with a Use Strict Directive, they don't "inherit" the strictness of the current context as Function Declarations or Function Expressions do.
It's the comma operator, which evaluates both of its operands and returns the value of the second one.
So, something like (null, alert) evaluates to the alert function, which you can immediately call using parentheses.
It's described in section 11.14 of ECMA-262 (PDF).
The comma operator causes expressions to be evaluated sequentially. Wrapping the expressions in parentheses returns the value of the last expression. So (1, alert)("hello") is functionally equivalent to:
1;
alert("hello");
Off the top of my head, I can't think of a reason to do this.