How are native objects implemented in browser in JavaScript? [duplicate] - javascript

While working on another problem, I created this fiddle:
http://jsfiddle.net/tr2by/
function foo() {
// console.log(_.isBoolean(this));
console.log(this === true);
}
foo.call(true); // object:[object Boolean]
foo.apply(true); // object:[object Boolean]
Is this an example of auto-boxing?
Going from a value type to a reference type.
Here is a wikipedia def.

First of all I assume you are talking about automatic conversion of primitive values to objects. This happens in two cases in JavaScript:
When you pass a primitive value as the this value to .call or .apply (not in strict mode though).
When you are trying to access a "property" of a primitive value, e.g. "foo bar".split().
In the first case the conversion is permanent, i.e. this will indeed reference an object, in the second the conversion only takes place internally for the duration of the evaluation
If you are not interested in the details of the conversion, you can ignore the rest of the answer.
1. Primitive value as this
When a function is exectued and its this value is not an object, it is converted to one, at least in non-strict mode. This is described in §10.4.3 Entering Function Code [spec] in the ECMAScript 5.1 documentation:
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:
If the function code is strict code, set the ThisBinding to thisArg.
Else if thisArg is null or undefined, set the ThisBinding to the global object.
Else if Type(thisArg) is not Object, set the ThisBinding to ToObject(thisArg).
[...]
As you can see in step three the value is converted to an object by calling ToObject [spec].
2. Property access
Something similar happens when you are trying to access properties (§11.2.1 Property Accessors [spec]). The quoted part here explains how the expression foo[bar] is evaluated, i.e. how property access with the bracket notation is evaluated. The part we are interested in applies to dot notation as well.
The production MemberExpression : MemberExpression [ Expression ] is evaluated as follows:
Let baseReference be the result of evaluating MemberExpression.
Let baseValue be GetValue(baseReference).
[...]
8. Return a value of type Reference whose base value is baseValue and whose referenced name is propertyNameString, and whose strict mode flag is strict.
The important step is the last one: No matter to what MemberExpression evaluates, it is converted to a value of type Reference [spec]. This is a datatype only used in the specification and contains additional information about how the actual value should be retrieved from the reference (not to be confused with object references in actual JavaScript code!).
To get the "real" value/result from such a reference, the internal function GetValue(V) (§8.7.1) [spec] is called (just like in step 2 in the above algorithm), where it says:
The following [[Get]] internal method is used by GetValue when V is a property reference with a primitive base value. It is called using base as its this value and with property P as its argument. The following steps are taken:
Let O be ToObject(base).
[...]
Example:
Assume we have the expression
var foo = "BAR".toLowerCase();
This is an assignment expression which is evaluated as follows:
The production AssignmentExpression : LeftHandSideExpression = AssignmentExpression is evaluated as follows:
Let lref be the result of evaluating LeftHandSideExpression.
Let rref be the result of evaluating AssignmentExpression.
Let rval be GetValue(rref).
[...]
Step 1: The left hand side is evaluated, which is the identifier foo. How exactly identifiers are resolved is not important for this.
Step 2: The right hand side is evaluated, i.e. "BAR".toLowerCase(). The internal result of that evaluation will be a reference value, similar to:
REFERENCE = {
base: "BAR",
propertyNameString: "toLowerCase",
strict: false
}
and stored in rref.
Step 3: GetValue(rref) is called. The base of the reference is the value "BAR". Since this is a primitive value, ToObject will be called to convert it to a temporary String object. Furthermore, the reference is actually a property access, so GetValue will eventually call the method toLowerCase on the String object and return the method's result.

Javascript boxes the this argument provided to call and apply in non-strict mode. From MDN:
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.

The other answers provide detailed information about when autoboxing occurs, but here's a couple more things to remember:
Autoboxing does not occur when using the in operator, which throws a TypeError if the value received is not an object. A simple solution is to manually box the object with Object(value).
Some form of autoboxing occurs when iterating using for...of or the spread syntax [...value] which allows strings to be iterated.

Related

Definition of name property in assignment expression

Since ECMAScript 6, most function objects have a name property defined.
Now, if an anonymous function expression is assigned to a variable or is part of a property definition inside an object initializer, the identifier of the variable or the name of the property will be the value of the name property of the function object.
const a = function () {};
console.log(a.name); // a
const object = {
b : function () {}
};
console.log(object.b.name); // b
I don't have problems to understand the spec regarding the documented semantic of this behaviour, but I can't really see, why an assignment to a left hand side member expression as in the following example does not affect the name property of the function, which seems to be the case.
const object = {};
object.c = function () {};
console.log(object.c.name); //
As part of the member expression, there is obviously an indentifier which could (and should?) be used as the value of the name property. Even if the property name would be an expression inside brackets, this should be no problem, since using computed property names inside an object initializer does not prevent the name property of the anonymous function to be defined either.
It would be great, if someone could confirm that the observed behaviour is conforming to the spec and anyway, explain in short the specific semantics that apply to this syntax.
This first snippet is described under assignment operators:
e. If IsAnonymousFunctionDefinition(AssignmentExpression) and IsIdentifierRef of LeftHandSideExpression are both true, then
i. Let hasNameProperty be HasOwnProperty(rval, "name").
ii. ReturnIfAbrupt(hasNameProperty).
iii. If hasNameProperty is false, perform SetFunctionName(rval, GetReferencedName(lref)).
When you assign to a MemberExpression, as in your last snippet, IsIdentifierRef(LeftHandSideExpression) is false and no conversion takes place.
If you search the standard for IsAnonymousFunctionDefinition you'll find a couple of other cases where this logic is used (object initializers, destructuring assignments).
IsIdentifierRef is defined twice (here and here), and both definitions boil down to "if an expression is IdentifierReference return true otherwise return false", where IdentifierReference is an Identifier (the yield stuff is for backward compatibility with non-strict code).

Arguments and reference

Consider this JavaScript function:
var f = function (a) {
console.log(a+" "+arguments[0]);
a = 3;
console.log(a+" "+arguments[0]);
}
I would expect that a and arguments[0] reference the same value only up to the second statement of the function. Instead they appear to always refer the same value: f(2) causes
2 2
3 3
and f({foo: 'bar'}) causes:
[object Object] [object Object]
3 3
Are argument identifiers and the arguments identifier linked in a special way?
Are argument identifiers and the arguments identifier linked in a special way?
Yes (but only in non-strict mode).
From the specification (ES6, ES5):
For non-strict mode functions the integer indexed data properties of an arguments object whose numeric name values are less than the number of formal parameters of the corresponding function object initially share their values with the corresponding argument bindings in the function’s execution context. This means that changing the property changes the corresponding value of the argument binding and vice-versa. This correspondence is broken if such a property is deleted and then redefined or if the property is changed into an accessor property. For strict mode functions, the values of the arguments object’s properties are simply a copy of the arguments passed to the function and there is no dynamic linkage between the property values and the formal parameter values.

"cases where null or undefined is coerced into becoming the global object"

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).

Difference between undefined and not being defined in Javascript

See http://jsfiddle.net/FDhQF/1/ for a trivial example.
What's the difference between something being undefined and something not being defined in Javascript? For instance, trying to access a property for an object (effectively, trying to access a variable) that isn't defined will return undefined. But you can also set something = undefined. When you do that, trying to access it still return undefined, but the pointer is still there. An example, as above, is how iterating over an object still goes over the property that you've (re)declared as undefined. It seems like there are two different sorts of undefined. Can anyone shed some light on the situation?
Both, accessing a property that isn't defined on an object and a property that contains the primitive undefined value, will return you undefined.
For example:
var obj = {
a: undefined
};
obj.a; // undefined
obj.b; // undefined
The difference is that a is an own property, and b isn't:
obj.hasOwnProperty('a'); // true
obj.hasOwnProperty('b'); // false
In the first case a is an own property, even if it contains undefined as its value. In the second case, b is not an own property, accessing obj.b will look for a property named b, all way up in the prototype chain.
When the prototype chain ends (when it reaches an object with a null [[Prototype]]), the property lookup ends and undefined is explicitly returned.
You should know that the hasOwnProperty method checks only if the property physically exist on the object (own properties), but we have also inherited properties, for that case we can use the in operator, for example:
function Test () {}
Test.prototype.a = 'foo'; // instances of Test will inherit from Test.prototype
var obj = new Test(); // { a="foo", b="bar"}
obj.b = 'bar';
obj.hasOwnProperty('a'); // false
'a' in obj; // true
obj.a; // 'foo'
obj.hasOwnProperty('b'); // true
As you can see, obj inherits from Test.prototype, and the a property is not an own property, but it is available through the prototype chain. That's why hasOwnProperty returns false and the in operator returns true.
You can see how internally properties are resolved by the [[Get]] internal operation
Notes:
Accessing undefined as an identifier is not considered to be safe on ECMAScript 3 (the most widely implemented version of the language standard), because instead of being a language keyword (such as null for example) is just a property of the global object, and it is writable on this version of the Spec., meaning that if someone replaces its value (e.g. window.undefined = 'LOL';) , it will break your code.
The typeof operator as #strager mentions can be used instead, for example:
if (typeof obj.prop == 'undefined') { /*....*/ }
This operator returns always a string (it's safe to use == :), and its value depends of the type of its operand, the possible values are described here.
Another common way to solve this is to declare your own undefined variable, available on the scope of your functions, for example, some libraries use the following pattern:
(function(undefined) {
// code here
})();
The function has an argument named undefined, and it is executed immediately without passing any value to it (the last pair or parens make the invocation).
Maybe is worth mentioning that the undefined global property was finally described on ECMAScript 5 as non-writable (immutable, as well non-enumerable and non-configurable -non deletable-).
Using the hasOwnProperty method directly from an object instance is also not considered as safe, because if some object has a property with the same name, the original method will be shadowed. For example:
var obj = { hasOwnProperty: function () { /* evil code :) */ } };
If you call:
obj.hasOwnProperty('prop');
The method defined on the object will be executed (and you wouldn't want this since you know exactly which method you want to invoke...), because it shadows the one from the Object.prototype, however it can be safely invoked by:
Object.prototype.hasOwnProperty.call(obj, 'prop');
Here is a good explanation of "undefined". The gist however is that setting something to "undefined" is not UN-defining it, because "undefined" is actually a primitive value, which is used when a variable (or property) has not been assigned a value.

Where is arguments property defined?

Consider the following code
function add(x, y) {
alert(arguments.length);
var total = x + y;
return total;
}
add(); // NaN alerts 0
add(2,3); // 5 alerts 2
add(3,3,5); //6 alerts 3
Where is arguments defined? How come it is available inside my add function?
It is automatically created for all functions.
See https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Functions_and_function_scope/arguments
A detailed explanation about when and how the arguments object is created:
From the ECMAScript specification:
10.1.8 Arguments Object
When control enters an execution context for function code, an arguments object is created and
initialised as follows:
The value of the internal [[Prototype]] property of the arguments object is the original Object prototype object, the one that is the initial value of Object.prototype (see 15.2.3.1).
A property is created with name callee and property attributes { DontEnum }. The initial value of this property is the Function object being executed. This allows anonymous functions to be recursive.
A property is created with name length and property attributes { DontEnum }. The initial value of this property is the number of actual parameter values supplied by the caller.
For each non-negative integer, arg, less than the value of the length property, a property is created with name ToString(arg) and property attributes { DontEnum }. The initial value of this property is the value of the corresponding actual parameter supplied by the caller. The first actual parameter value corresponds to arg = 0, the second to arg = 1, and so on. In the case when arg is less than the number of formal parameters for the Function object, this property shares its value with the corresponding property of the activation object. This means that changing this property changes the corresponding property of the activation object and vice versa.
That is just a standard feature of Javascript. Whenever any function is called, there is an arguments array automatically added to the local scope. This allows a function to receive a variable or unknown amount of parameters from the caller, and dynamically use these as necessary.
Commonly this is used when one function is placed as a wrapper around another where the exact parameters are unknown and arbitrary to the wrapper, who simply performs an action and then passes the provided arguments directly into the wrapped function.
arguments is a property of function objects. See Using the arguments object or Property: Function: arguments for more information.
It's worth noting that arguments is not a "real" array, the documentation calls it an "array-like object" - more in Turning JavaScript's arguments object into an array.

Categories