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.
Related
From my Chrome interpreter:
a = 3; // OK, of course.
a.f = function() { return 4; }; // OK. To a number? Ok
a; // Prints 3
a.f(); // f is not a function.
a.f; // Undefined
Of course, a is not an object, and I cannot assign new members to something that isn't an object. But, why does the interpreter swallows the a.f assignment if after that the method or the member doesn't even exist?
If you look at 8.7.2 of the ECMA 5.1, you will notice this note at the bottom:
The object that may be created in step 1 is not accessible outside of the above method. An implementation might choose to avoid the actual creation of that transient object. The only situations where such an actual property assignment that uses this internal method can have visible effect are when it either invokes an accessor function or is in violation of a Throw predicated error check. When Throw is true any property assignment that would create a new property on the transient object throws an error.
Step 1 is Let O be ToObject(base).
If you look at the ToObject() method in 9.9, you will find these two rows in the table:
Number
Create a new Number object whose [[PrimitiveValue]] internal property is set to the value of the argument. See 15.7 for a description of Number objects.
Object
The result is the input argument (no conversion).
So it looks like when you attempt to set the function on the number, it is actually happening (although as a noop), it just becomes unaccessible after the assignment, due to the assignment happening on an internal transient object. When you do it on a regular object, it returns the actual object, so the assignment makes sense.
There's not really a good reason why it wasn't forbidden, it could easily have been if that was how it was implemented when the language was developed.
But why was it implemented without an error? Because it nicely mirrors what happens when you access a property on a primitive: it does implicitly get cast to an object. It doesn't matter whether you use the property reference for assignment or for retrieval, there's an object involved. The assignment will work as usual, even if the coerced object is thrown away immediately afterwards.
We even can see that when we provide an inherited accessor for that object on its prototype:
"use strict";
Object.defineProperty(Number.prototype, "f", {
set: function(value) {
console.log(typeof this+" "+this+" got "+value+" assigned to .f");
},
get: function() {
console.log(typeof this+" "+this+"'s .f property was accessed");
return function() {
console.log("method called on "+typeof this+" "+this);
};
},
configurable: true
});
(3).f = "test value";
(3).f();
I have seen different code examples with variables declared and set to undefined and null. Such as:
var a; // undefined - unintentional value, object of type 'undefined'
var b = null; // null - deliberate non-value, object of type 'object'
If the code to follow these declarations assigns a value to a or to b, what is the reason for using one type of declaration over another?
The first example doesn't assign anything to the variable, so it implicitly refers to the undefined value (see 10.5 in the spec for the details). It is commonly used when declaring variables for later use. There is no need to explicitly assign anything to them before necessary.
The second example is explicitly assigned null (which is actually of type null, but due to a quirk of the JavaScript specification, claims to have type "object"). It is commonly used to clear a value already stored in an existing variable. It could be seen as more robust to use null when clearing the value since it is possible to overwrite undefined, and in that situation assiging undefined would result in unexpected behaviour.
As an aside, that quirk of null is a good reason to use a more robust form of type checking:
Object.prototype.toString.call(null); // Returns "[object Null]"
I just saw this link which clarified my question.
What reason is there to use null instead of undefined in JavaScript?
Javascript for Web Developers states "When defining a variable that is meant to later hold an object, it is advisable to initialize the variable to null as opposed to anything else. That way, you can explicitly check for the value null to determine if the variable has been filled with an object reference at a later time."
I don't think there's a particular better way of doing things, but I'm inclined to avoid undefined as much as possible. Maybe it's due to a strong OOP background.
When I try to mimic OOP with Javascript, I would generally declare and initialize explicitly my variables to null (as do OOP languages when you declare an instance variable without explicitly initializing it).
If I'm not going to initialize them, why even declare them in the first place? When you debug, if you haven't set a value for a variable you watch, you will see it as undefined whether you declared it or not...
I prefer keeping undefined for specific behaviours:
when you call a method, any argument you don't provide would have an undefined value. Good way of having an optional argument, implementing a specific behaviour if the argument is not defined.
lazy init... in my book undefined means "not initialized: go fetch the value", and null means "initialized but the value was null (eg maybe there was a server error?)"
arrays: myArray[myKey] === null if there is a null value for this key, undefined if a value has never been set for this key.
Be careful though, that myVar == null and myVar == undefined return the same value whether myVar is undefined, null or something else. Use === if you want to know if a variable is undefined.
I would explicitly choose null, to not create an object whose id is later overwritten anyway:
var foo = {}; // empty object, has id etc.
var foo2 = null; // good practice, // filled with an object reference at a later time
var foo3;// undefined, I would avoid it
console.log(typeof foo);
console.log(typeof foo2);
console.log(typeof foo3);
Setting null also ensures good readability to identify the datatype (object),
results in
object
object
undefined
Source (Professional JavaScript for Web Developers 3rd Edition):
When defining a variable that is meant to later hold an object, it is
advisable to initialize the variable to null as opposed to anything
else. That way, you can explicitly check for the value null to
determine if the variable has been filled with an object reference at
a later time, such as in this example:
if (foo2 != null){
//do something with foo2
}
The value undefined is a derivative of null, so ECMA-262 defines them to be superficially equal as follows:
console.log(null == undefined); // prints true
console.log(null === undefined);// prints false
null is an object.. When something is undefined it is nothing.. it is not an object, neither a string, because it hasn't been defined yet.. obviously.. then it is simply a property with no function..
example:
You declare a variable with var but never set it.
var foo;
alert(foo); //undefined.
You attempt to access a property on an object you've never set.
var foo = {};
alert(foo.bar); //undefined
You attempt to access an argument that was never provided.
function myFunction (foo) {
alert(foo); //undefined.
}
In trying to better understand the prototype behind javascript, I have stumbled upon the following, which I am unable to make sense of so far.
I understand that functions are a first class object, but I don't get why Object gets this property after setting the property on Function.prototype
Function.prototype.foo = 'bar';
Object.foo // Object now has this property and returns 'bar'
Object.foo === Function.prototype.foo // returns true
Object is a function, typeof Object == 'function' is true. So you assign a property of Function.prototype, it will let the Object has the property also. (in the property chain.)
If I am not mistaken Function.prototype is a prototype for all inherited objects. Because you set Function.prototype.foo = 'bar'; all objects inherit the foo property. That is why the third line of code returns true.
This is because Object and Function objects share the same internal [[Prototype]] property.
As Ecma-262 says:
The value of the internal [[Prototype]] property of the Function prototype object is the Object prototype object.
So if you add any property to the Function's prototype, that property will be accessible through the Object object too, and vice versa.
If you want to understand it deeply, I'd suggest you to take a look at the Ecma-262 Specification.
Hope it helps.
I'm in ES5 strict mode, so the solution
function isArguments(item) {
return item.callee !== undefined;
}
unfortunately doesn't work.
function isArguments( item ) {
return Object.prototype.toString.call( item ) === '[object Arguments]';
}
William's answer is right, but some explanations may be useful.
In ECMAScript 5, the only thing that characterizes Arguments objects is their internal [[Class]], as seen in §10.6 Arguments Object:
When CreateArgumentsObject is called the following steps are
performed:
Let obj be the result of creating a new ECMAScript object.
Set the [[Class]] internal property of obj to "Arguments".
Return obj
[[Class]] is an internal property common to all objects, whose value is a String which classifies the object. This is explained in §8.6.2 Object Internal Properties and Methods:
The value of the [[Class]] internal property is defined by this
specification for every kind of built-in object.
The value of a [[Class]] internal property is used internally to
distinguish different kinds of objects.
Moreover, note that host objects won't be problematic:
The value of the [[Class]] internal property of a host object may be
any String value except one of "Arguments", [...]
Therefore, to identify an Arguments object you only need to check its class.
You can do that using §15.2.4.2 Object.prototype.toString:
Let O be the result of calling ToObject passing the this value as the argument.
Let class be the value of the [[Class]] internal property of O.
Return the String value that is the result of concatenating the three Strings "[object ", class, and "]".
Therefore, you can use Function.prototype.call to call that method with the this value set to the object you want to check. The returned string will be '[object Arguments]' if, and only if, it's an Arguments object.
Object.prototype.toString.call(obj) == '[object Arguments]'
Note that isn't completely foolproof, because the global Object could have been shadowed by a local one, or the global Object or its toString property could have been modified.
However, there is no better way:
Note that this specification does not provide any means for a program
to access that value except through Object.prototype.toString (see
15.2.4.2).
Generating and comparing strings to determine the type of an object is a little fuzzy. Like #bergi suggested, I think Lodash is doing it a more convenient way. Condensed into one function it is:
function isArguments(value) {
return !!value && typeof value == 'object' && Object.prototype.hasOwnProperty.call(value, 'callee') && !Object.prototype.propertyIsEnumerable.call(value, 'callee');
}
I inherited some javascript code another developer wrote. He didn't like the grid component we used throughout the project, so he decided to write his own. The grid he wrote can't sort dates, because it can only bind to strings / numbers. He converts all dates to strings before using them. I looked at the string formatting of date function he wrote, and figured I could just add a date property to the string with the original value, and then when sorting see if the string has a date property and sort based on that. However, it seems like you can't add properties to strings in javascript. I wasn't aware there were certain types you can't add properties to. For example:
<html>
<script>
var test = "test";
test.test = "test inner";
console.log(test);
console.log(test.test);
</script>
test.test will be undefined. Weird. My question is why this code doesn't work? And also, if you can think of any workarounds for sorting dates on that grid (besides actually binding to date objects instead of strings, which would be a pain to fix,) that would be really helpful.
There are 8 language types in JavaScript:
7 primitive types: Undefined, Null, Boolean, Number, BigInt, String, and Symbol
1 non-primitive type: Object
Values of the primitive types are called primitive values and they cannot have properties.
Values of the Object non-primitive type are called objects an they can have properties.
When you try to assign a property named 'bar' to a variable foo, like so:
foo.bar = 'abc';
then the result will depend on the type of the value of foo:
(a) if the value of foo is of the type Undefined or Null, then an error will be thrown,
(b) if the value of foo is of the type Object, then a named property 'bar' will be defined on the object foo (if necessary), and its value will be set to 'abc',
(c) if the value of foo is of any other type, then a TypeError will be thrown in strict mode: “can't assign to property "bar" on foo: not an object”. In loose mode, the above assignment operation will be a no op. In either case, the variable foo will not be changed in any way.
So, as you can see, assigning properties to variables only makes sense if those variables are objects. If that is not the case, then the assignment will either do nothing at all, or even throw an error.
In your case, the variable test contains a value of the type String, so this:
test.test = "test inner";
does nothing at all.
However, since ES5 introduced accessor properties, there is an exception to what I've said above. Accessor properties allow us to define functions which are invoked whenever the property is either retrieved or set.
For instance:
var str = '';
str.prop;
Here str is a variable holding a String value. Therefore, accessing a property of that variable should be a no-op (str.prop merely returns undefined). This is true with one exception: if String.prototype contains a accessor property 'prop' with a defined getter, then that getter will be invoked.
So, if this is defined:
Object.defineProperty( String.prototype, 'prop', {
get: function () {
// this function is the getter
}
});
then this
str.prop;
will invoke that getter function. This also works in strict mode.
Live demo: http://jsfiddle.net/fmNgu/
However, I don't think that adding accessor properties to the built-in prototypes would be a good practice.
If you use a String object you can add properties:
var test = new String("test");
test.test = "test inner";
console.log(test.toString()); // prints out "test"
console.log(test.test); // prints out "test inner"