Why declare a variable as a new Object? - javascript

As a beginner, working with existing code, I've come across the following:
var foo = {};
which I believe is equivalent to:
var foo = new Object();
I was under the impression that any variable was automatically an Object, so what would be the purpose of specifically coding that, rather than just declaring an empty variable:
var foo;

I was under the impression that any variable was automatically an Object
That is a mistaken impression. If you declare a variable and do not assign it a value, it is initialised to undefined (as mention in the spec and described in detail), which is not an object (it's a primitive value):
var foo;
console.log(foo); // undefined
If you were to attempt to set a property of an undefined variable you would receive a TypeError:
var foo;
foo.example = "hello"; // TypeError: Cannot set property 'example' of undefined
However, if you assign an empty object to that variable, the above code will succeed:
var foo = {}; // Now refers to an empty object (equivalent to `new Object()`)
foo.example = "hello";
console.log(foo); // '{example:"hello"}'
I believe your understanding probably stems from the common misunderstanding that "everything in JavaScript is an object". This is not true. Many things in JavaScript are objects, but primitive values are not. For example:
var a = "hello"; // String primitive, not an object
var b = new String("hello"); // String instance, object
var c = 10; // Number primitive, not an object
var d = true; // Boolean primitive, not an object
var e; // Undefined value, not an object
var f = null; // Null value, not an object

James's answer is correct. In case he's throwing too much info too quickly (refer back to it later, if so), here's a quick summary.
You are correct in this: var foo = {} and var foo = new Object() are not only equivalent, the results are identical. Only use object literals. (ignore new Object(), new Array(), etc).
var foo; does nothing other than declare a variable. It is 'undefined' by default.

var foo = new Object() also gives the new object a prototype property which can be used to manipulate object inheritance and call standard object functions defined by javascript
see here for details on how you can manipulate the object.protype:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/prototype

Related

Javascript - Getting and setting properties on primitives implicitly creates object wrappers

I was reading a book called Effective JavaScript: 68 Specific Ways to Harness the Power of JavaScript, Point 4 Prefer Primitives to Object Wrappers and came across this sentence.
Getting and setting properties on primitives implicitly creates object
wrappers
Does this create an object wrapper?
"hello".someProperty = 17;
EDIT
If the above statement create an object then please explain this behaviour.
var test = "foo";
test.bar = "new prop";
test.bar //this prints undefined.
"hello".someProperty = 17;
The above statement does create an object wrapper, but it is disposed of as soon as its task is done.
var hello = 'Hello';
hello.someProperty = 17;
console.log(hello.someProperty);
This explains why trying to assign properties to a primitive doesn't work, but also doesn't throw an error. Assigning the property succeeds, but the property is set on a wrapper object which is immediately destroyed. So when you go to look up the property later, there is nothing there anymore.
Internally, this of primitive type is object.
String.prototype.thisType = function () {
return typeof this;
};
var hello = "hello";
console.log(typeof hello);
console.log(hello.thisType());
Read more Here
Yes, it creates an intermediate object, which is discarded after use. So the statement
"hello".someProperty = 17;
will internally be executed like this:
var temp = new String("hello"); // or any other variable name
temp.someProperty = 17;
So, now temp (or whatever named variable is created by JavaScript) will not be accessible because it is created and discarded immediately.
you have to create String Object by new Keyword.
var str = new String("My String");
//Here str is looks like
//String {"My String"}
str .xyz=5
str
//now String {"My String", xyz: 5}

Javascript object property accessed via brackets assigned another property's value?

I know what the following code DOES, I'm just unable to wrap my head around the WHY.
var myObject = new Object();
var foo = new Object();
var bar = new Object();
myObject[foo] = 'foo';
myObject[bar] = 'bar';
console.log(myObject[foo]); // returns bar
console.log(myObject); // returns [object Object]: "bar"
console.log(myObject[blah]); // returns "blah not defined" error.
By this measure, how is myObject[blah] undefined yet myObject[foo] and myObject[bar] are defined - and not only defined, but set to the same value?
According to http://www.w3schools.com/js/js_objects.asp an object's properties can be accessed via object.property or object[property] however if I add in myObject.foo = "foobar"; before the console logs, myObject[foo] does not get set to "foobar" but myObject.foo does.
If I console.log myObject.Object or myObject.object or myObject[object] or myObject[Object] - it all comes back as undefined.
Both foo and bar have values of Object {}. So they aren't being set.
The problem is with types here.
foo is an object, you can't access a property of an object with another object as a key.
Although foo will be converted to a string and no error will occur, be aware that what will finally be evaluated is this:
myObject[foo] = 'foo';
myObject[bar] = 'bar';
Translated to
myObject["[object Object]"] = 'foo';
myObject["[object Object]"] = 'bar';
By this measure, how is myObject[blah] undefined yet myObject[foo] and
myObject[bar] are defined - and not only defined, but set to the same
value?
This message error does not tell you that the key does not exist, as it would not be an error. What it tells you instead is that blah is a variable you are trying to use whereas you never defined it before, thus throwing an undefined reference error.
Also, unrelated but {} syntax is always preferred to new Object()
You're referencing the variable blah which is not defined.
foo and bar are defined but it's very strange to use them as keys in another object. JavaScript doesn't support HashMaps by default, instead it will perform a to-string cast, this produces "[object Object]".
So myObject[foo] and myObject[bar] are both just myObject["[object Object]"]
Did you intend myObject["foo"] and myObject["bar"]"?
The syntax is either:
obj["property"];
// or
obj.property;
// or
var prop = "property";
obj[prop];
By this measure, how is myObject[blah] undefined
myObject[blah] is undefined because your trying to add the object blah which is not existing or undefined (thats what the interpreter is complaining when you open the console)
so if you would have said
var blah= new Object();
myobject[blah] would have worked fine.
yet myObject[foo] and myObject[bar] are defined - and not only defined, but set to the same value
The reason being similar to the above one, since you have defined foo and bar by declaring them as objects
var foo = new Object();
var bar = new Object();
the reason they have the same value is because you assigned them with those values
myObject[foo] = 'foo';
myObject[bar] = 'bar';
According to http://www.w3schools.com/js/js_objects.asp (Try to use MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Objects)... however if I add in myObject.foo = "foobar"; before the console logs, myObject[foo] does not get set to "foobar" but myObject.foo does.
This part has been answered well in the other two answers, but for the sake of completion.
when you say myObject.foo , it creates a new 'property' ,if not already present, called 'foo' for 'myobject'.
The other way when you say
myobject["foo"] //-> NOTE foo is a string. A property is created.
However when you have
var foo = new object();
myobject[foo] // this is not correct since foo is an object here not a string
//or a property. inshort adding objects as property not a good idea.
If I console.log myObject.Object or myObject.object or myObject[object] or myObject[Object] - it all comes back as undefined.
myObject.Object // there is no property called 'Object', 'object' in myobject
However, if you say
myObject.object = "added object property"; //OR
myObject["object"] = "added object property";
then try the above console.log commands it should work, but note that properties are case sensitive

Need direction for learning Object inheritance and code clean java script

I am really fixed with JS object related concepts. For ex:
Crockford says: Objects produced from object literals are linked to Object.prototype
Now on console when I type:
// input represented with >
> var a = {};
> console.log(Object.getPrototypeOf(a));
Object {} // <-- output
> console.log(a.prototype);
undefined
Crockford says:Function objects are linked to Function.prototype (which is itself linked to Object.prototype)
> function b(){};
> console.log(Object.getPrototypeOf(b));
function()
> console.log(b.prototype);
b{}
> console.log(b.prototype.prototype);
undefined
> console.log(Object.getPrototypeOf(b.prototype));
Object {}
When I do getPrototypeOf() I get the expected output, but when I try to use the prototype property I get undefined. Cant figure out the reason.
Also for line 5 return value is function(). Can some please explain does this say ? I expected an Object to be returned.
It would be great if someone please give me insight/good links/some class diagrams(as we have in java) to follow for understanding prototypal inheritance.
Okay. Here's the thing. There are some concepts in JS that seem really convoluted at the start, but are actually really straightforward. Let's have a look at a few of them.
1) function.prototype property
When you define a function, the JS engine creates an anonymous object and binds the two using property names prototype and constructor as follows:
function foo(){}
/* Performed by JS engine internally */
// foo.prototype = {};
// foo.prototype.constructor = foo;
Therefore, only functions have .prototype.
The .prototype is used only and only when the function is invoked using the new operator.
2) References
In JS, references can be used to pass along a variable, without creating a duplicate of it. Perhaps an example might help here:
var a = 1;
var b = { val: 1 };
var c = { val: 1 };
var x;
/*variable cloned*/
x = a;
x++;
console.log(a); // 1
console.log(x); // 2
/*variable refernced*/
x = b;
x.val++;
console.log(b); // { val: 2 }
console.log(x); // { val: 2 }
/*variable cloned*/
x = c.val;
x++;
console.log(c); // { val: 1 }
console.log(x); // 2
3) object.__proto__ property
Any object created by invoking a function with the new keyword, like var x = new foo();, will have a __proto__ property on it that is the object referenced by its constructor function's .prototype property. Re-assigning foo.prototype to somethings else will not affect objects that have already been created.
In other words,
function foo(){}
// foo.prototype = {};
// foo.prototype.constructor = foo;
var x = new foo();
console.log(x.__proto__ === foo.prototype); // true
Also, when you create an object like var x = {};, it is the exact same thing as:
var x = new Object();
Therefore, x.__proto__ is the object referenced by Object.protoype.
Conclusion
How does all this add up?
foo.prototype acts as a "blueprint" for the objects created using the function foo.
When we do create an object x = new foo(), JS engine stores a reference (link) to "the blueprint that was used to make x" as the __proto__ property.
When I do getPrototypeOf() I get the expected output, but when I try to use the prototype property I get undefined. Cant figure out the reason.
Object.getPrototypeOf(...) returns the __proto__ property, not prototype.
Also for line 5 return value is function(). Can some please explain does this say ? I expected an Object to be returned.
In JS, all data types have an associated "Wrapper" function.
Similar to how x = {} is the same as x = new Object(), doing function b(){} is the same as b = new Function()
since b was created invoking a function using new, it has a __proto__ property, that is the object referenecd by its constructor function's prototype. In this case, Function.prototype, which is also Function.
Still confused? I'd recommend having a good long read at http://www.javascripttutorial.net/

Declaring an object in JavaScript for later use - null or {}?

Simple question, What is the best practise, should I declare JavaScript objects, that will not be initialized until some later stage, with null or {}?
I think it really depends. If you just want to declare it early because you know it is "hoisted" to the beginning of the function anyway, and will initialize a few lines down below, then just use
var foo;
which makes foo undefined. Otherwise, if you need to do anything with foo being an object before your initialization, then it will be better to use
var foo = {};
Use the object literal {}. That way, you can immediately start using it as an object, when you have to, instead of having to initialize it again as an object, later on.
So:
var myObj = {};
// loads of code
myObj.someProperty = 'foobar';
Instead of:
var myObj; // undefined, or:
var myObj = null; // null
// loads of code
var myObj = {};
myObj.someProperty = 'foobar';
Makes sense, doesn't it?
You can use {}; as it makes your code more compact, and more readable. You may try it like this:
var x = {};
By this way you can start using x as an object without initializing it again.
Also to add
var x= {} //This is an object literal
var y= new Object() //This is the object constructor
Also {} syntax is shorter, neater,readable, and allows you to instantly populate the object inline

Javascript function properties

Why is it that I can do the following in javascript:
function a() {};
a.foo = 30;
Specifically, why can I set a property on the function a? After all, I cannot do this:
var a = 20;
a.foo = 30;
You really can't do this because it's a syntax error
function a = function() {};
I suppose you simply want to say:
function a() {}
Anyway. The reason that you cannot get a property out of a number, is that it is not a real Object.
a = 20;
a.foo = 30; // this works
alert(a.foo); // this alerts nothing
Believe it or not, the same goes for strings:
a = "ohai";
a.foo = 30; // this works
alert(a.foo); // this alerts nothing
However if it's String object, then it works as expected:
a = new String("ohai");
a.foo = 30; // this works
alert(a.foo); // this alerts 30
Or if it's an Number object. You get the point.
String and number literals are not objects in Javascript. That's the reason.
In JavaScript the dot (.) operator expects it's left value to be an object. And in JavaScript, functions are objects.
Basically, in JavaScript, there are four main datatypes:
Number
String
Boolean
Object
Objects encompasses functions, arrays, date objects, and (for lack of a better word) regular objects. The function object is unique in that it contains executable code, and can be invoked.
Numbers are primitives, and thus you cannot access/assign properties to/from them.
In Javascript, a function is an object, so you can set properties on it:
function a() {};
a.foo = 30;
a.foo; // evaluates to 30
A number literal however creates a primitive value (which has no properties) and not an object.
a = 20; // Create primitive value using number literal
When you set a property on a primitive value, in fact you create a wrapper object around the primitive value and set the property on the wrapper object, not the primitive value.
a.foo = 30; // wrapper object created and directly thrown away
(new Number(a)).foo = 30; // --> equivalent
When you read the property, again you create a wrapper object, whihch hasn't the property defined.
a.foo; // wrapper object created, has no foo property
(new Number(a)).foo; // --> equivalent, evaluates to undefined
In javascript functions are objects. Or they inherit from objects, or something.
try doing
a = function(){};
alert(typeof a.prototype);

Categories