...

View Full Version : syntax issue involving ","



blaze4218
09-28-2011, 06:33 PM
So recently I ran some code through google's closure compiler and it combined multiple statements into one statement separated by a ','
I didn't really know what that accomplished, but I thought I would try it out a little and see the what happens...
I have been using it (for now) to combine all variable declarations into a single statement and it has been working. I got an error today with the following

StartArr = [], EndArr = [], var range=0, dif = 0, totalTimeInSeconds = 0;

Apparently it doesn't work when I use a throw in a local variable... So I'm thinking that I don't quite grasp what it's supposed to be doing :(
It would seem that I can't use it to combine just any statements.
I tried looking it up (not really knowing what it's called) and found the following http://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/ on the subject
I have come to the conclusion that I am using it to "separate members in a list"


//set 4 array elements
var arr = [1, 2, 3, 4];

//create an object with 2 properties
var obj = {
a: 22,
f: function() {return this.a*this.a}
}

//define 3 distinct variables
var a = 1, b = 2, c = 3;

//invoke a function passing 2 arguments
Math.max(4, 7);

Were the samples on that blog


My questions are
1)What am I really doing when I combine these var declarations into one statement?
2)What are the advantages of the second and third examples from above over creating each property/variable in a separate statement?
3)Why did my statement fail when I added the local scope to range?

And now I'm kinda wondering
4)What the heck is that "a: 22" ?? is that the same as "this.a = 22" ? Can I do the following:



var obj = {
a: 22,
f: function() {return this.a*this.a}
}
document.write(obj.a) //Output "22"

5)Why is "obj" declared as "var" and not "function"

I guess their are many ways of writing the same thing in javascript, I'm just trying to get a better grasp here.

Old Pedant
09-28-2011, 08:11 PM
The comma operator is a holdover from Java which held it over from C++ which held it over from C (which probably held it over from BCPL).

It basically means "ignore the expression up to this point".

So, for example, if you do

var n = 13, 7.33, "hello";

you get exactly the same thing as if you did


var n = "hello";

Now, that seems pretty useless, but the trick here is that you can have expressions *WITH SIDE EFFECTS* and ignore the values of those expressions.

So:


var n = blinkTheScreen(), makeTheBackgroundRed(), "hello";

and indeed those two function will run but will have no impact on the value of n which will still end up as "hello".

Another peculiarity of JS that comes from Java/C++/C is that the value of an assignment statement *is* the value that was assigned. Meaning it can then be assigned again.


var a = document.getElementById("foo").innerHTML = "bananas";

Ignoring the side effect on the innerHTML of foo, that produces the same effect on variable a as doing


var a = "bananas";


SO...


var ignored = StartArr = [], EndArr = [], dif = 0, totalTimeInSeconds = 0;

What do you think that does?

Yep.
It assigns an empty object (array) to StartArr. The value of that *is* the empty object.
But the comma says "throw that value away".
It assigns an empty object (array) to EndArr. The value of that *is* the empty object.
But the comma says "throw that value away".
It assigns the value 0 to dif.
But the comma says "throw that value away".
It assigns the value 0 to totalTimeInSeconds.
AND THAT is the overall value of the expression and THAT is what is assigned to the variable ignored.

Okay, so *remove* the var ignored = from that line.

STILL perfectly legal! Nobody ever said you *have* to assign the value of an expression to a variable!

Finally, then, why doesn't this work:


StartArr = [], EndArr = [], var range=0, dif = 0, totalTimeInSeconds = 0;
Quite simply, because you can't use the keyword var in the middle of an expression!!!

That is, for example, you couldn't do:


document.getElementById("foo").innerHTML = var range;

The keyword var *MUST* be the first thing in any statement it occurs in (ignoring for now the fact that it can be used in for ( var i = 0; ... )

Okay?

blaze4218
09-28-2011, 08:25 PM
Thanks again! As usual, your my goto guy Old Pedant. How about questions 4 & 5, any insight?

Old Pedant
09-28-2011, 08:39 PM
//set 4 array elements
var arr = [1, 2, 3, 4];

//create an object with 2 properties
var obj = {
a: 22,
f: function() {return this.a*this.a}
}

//define 3 distinct variables
var a = 1, b = 2, c = 3;



My questions are
2)What are the advantages of the second and third examples from above over creating each property/variable in a separate statement?

Very little. Space savings. Less typing. A little faster to compile.

But once compiled, the execution time will be the same. (Or so close as to be immeasurable.)

Primarily it's just "syntactic sugar" as one of my compiler-writing-expert friends is fond of saying. Not to say that "sugar" isn't good: If it makes the intent of the code clearer, it makes writing the code easier.



And now I'm kinda wondering
4)What the heck is that "a: 22" ?? is that the same as "this.a = 22" ? Can I do the following:


var obj = {
a: 22,
f: function() {return this.a*this.a}
}
document.write(obj.a) //Output "22"


Why didn't you just try it?

Yes.

And yes, they are the same thing. (Assuming you mean using this.a in a constructor.)

And you could do document.write( obj.f() ); of course, as well.

And doing obj.a = 73; is the same as obj["a"] = 73;, just to add to the confusion.



5)Why is "obj" declared as "var" and not "function"

Ummm...because it's not a function. A function has to have code that is executed when it is invoked. If you wrote

function obj() {
a: 22,
f: function() {return this.a*this.a}
}
what possible meaning would doing obj() have??? "Execute the code in the function obj...but there's no code there to execute!

An object has properties. A function has code.


I guess their are many ways of writing the same thing in javascript, I'm just trying to get a better grasp here.
TOO MANY! And join the crowd. <grin/>

blaze4218
09-28-2011, 08:58 PM
what possible meaning would doing obj() have???
I don't know... Prototyping? or constructor, or whatever that's called? I guess I thought was the reason behind "this.foo" inside a function. That's just the first time i saw it without a function...

Old Pedant
09-28-2011, 09:01 PM
Sorry, I'm lost.

I guess I thought was the reason behind "this.foo" inside a function. That's just the first time i saw it without a function... What are you referring to here???

blaze4218
09-28-2011, 09:09 PM
if "foo" represents a generic labeling device to be substituted for a more useful variable assignment (such as StartArr, or range)
Then what I'm saying is that I thought "this." in collusion with "foo" served the purpose of creating properties to an object for prototyping. And I have only seen that done when used as such:


function LengthOfSomething(){
this.from = 0;
this.to = 10;
}
obj = new LengthOfSomething()
document.write(obj.to)

Am I at least close?

Old Pedant
09-28-2011, 09:18 PM
I think maybe I see the issue.

Consider this:


var blaze = {
name : "Blaze",
salary : 98318.22
}

versus

function Employee( nm, pay )
{
this.name = nm;
this.salary = pay;
}
var blaze = new Employee("Blaze", 98318.22 );

Why would you use the second instead of the first form?

Simple: Because the first form only creates *ONE* object with the given structure.

With the constructor version you can go on to write


var bill = new Employee( "Bill", 1.98 );
var joan = new Employee( "Joan", 33200.00 );
var alfred = new Employee(
document.getElementById("name").innerHTML,
document.getElementById("salary").innerHTML );

But with the JSON notation version, what happens if you went on to write


var bill = {
moniker : "Bill",
pay : 1.98
}

???

Worse, what if you did this:


var employees = {
"emp1" : { name : "Blaze", salary : 98318.22 },
"emp2" : { moniker: "Bill", pay: 1.98 }
};

If you then tried to do something like this:


for ( var emp in employees )
{
document.write( "We pay " + emp.name + " a salary of " + emp.salary );
}

It works fine for "emp1" but *KABLOOEY* on "emp2".

Where as if we do


var employees = {
"emp1" : new Employee("Blaze",98318.22),
"emp2" : new Employee("Bill",1.98)
};

we are guaranteed that the structure of each of the employees objects will be the same.

So...

Pays your money, takes your choice.

ironboy
09-28-2011, 09:20 PM
It's important to remember that functions are first-class members in JavaScript (i.e. can be treated as objects). This makes for a lot of fun... And even more ways to do things ;)

Old Pedant
09-28-2011, 09:21 PM
There's nothing really magic about this. It simply is shorthand for "the current object".

So when you use it in a constructor, you are just saying "the object being constructed."

blaze4218
09-28-2011, 09:49 PM
Once again you lost me at "JSON Notation" :(

Are you saying this won't work?

var bill = {
moniker : "Bill",
pay : 1.98
}

Why would you change from name/salary to moniker/pay in

var employees = {
"emp1" : { name : "Blaze", salary : 98318.22 },
"emp2" : { moniker: "Bill", pay: 1.98 }
};

ironboy
09-28-2011, 10:26 PM
1. Unprotected objects...

No one would go about changing "name" to "moniker" under normal circumstances. But you can never be sure who tampers with your objects in javascript.

That is about to change - in ECMA5 you can "seal and "freeze" objects (this is already implemented in many browsers):
http://ejohn.org/blog/ecmascript-5-objects-and-properties/http://ejohn.org/blog/ecmascript-5-objects-and-properties/

2. JSON is nothing strange or new to a JavaScripter

JSON is just a subset of javascript.
Sometimes we say "JSON notation" when we really mean "written as an object literal".


{
name: 'Ironboy',
age: 'old'
}

Actually that's not JSON because JSON is slightly stricter with its quotes:

{
"name": "Ironboy",
"age": "old"
}

But both of the above is valid JavaScript...

3. Constructors, new, this and all that

The use of function's as constructor's for "classes" in JavaScript is one of the worst ideas with the language (since it is not class based - it is prototype based).

It is slowly being phased out and replaced with:

newObj = Object.create(obj)
where newObj is a new object with obj as prototype.

Read more here:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/create

This is good - easy to understand and in line with JavaScript's nature.
It is quite easy to write an Object.create emulation in browser's that doesn't support it natively:http://javascript.crockford.com/prototypal.html

Old Pedant
09-29-2011, 12:25 AM
Sometimes we say "JSON notation" when we really mean "written as an object literal"
Actually, that's what I mean all the time except when discussing JSON notation sent back via AJAX or similar.

It's just a lot easier to write "JSON" and most people don't know what "written as an object literal" means. <grin/>

Old Pedant
09-29-2011, 12:36 AM
It is slowly being phased out and replaced with:


newObj = Object.create(obj)

where newObj is a new object with obj as prototype.


Which I, personally, think is almost as ugly a notation as new Name().

Seems to me, if obj is indeed a prototype, then why not

var newObj = obj.create( );

Plus, that would allow you to continue the practice of passing in arguments that help populate the new instance:

var emp31 = Employee.create( "ironboy", 39.95 );


Ahh...interesting...in the Examples section of the page Ironboy pointed us to, we see this:

function Constructor(){}
o = new Constructor();
// is equivalent to:
o = Object.create(Constructor.prototype);
// Of course, if there is actual initialization code in the Constructor function,
// the Object.create cannot reflect it

In other words, if you *need* the capabilities of a constructor with arguments, Object.create is worthless.

Ah, well...

ironboy
09-29-2011, 01:42 AM
The JavaScript community as a whole are very afraid of extending the Object prototype - hence Object.create not someObject.create...

You'll learn to love it, or at least live it :D

And you really don't need constructors. Look at this "mini-library":
Object.build = (function(){
var constr = function(){};
var creator = Object.create || function(obj){
constr.prototype = obj;
return new constr
};

/**
* @param protoObject protoObject to inherit from
* @param ownProps The objects own properties
* @return new object
*/
var builder = function(protoObject,ownProps){
var obj = creator(protoObject);
for(var i in ownProps){obj[i] = ownProps[i]};
return obj;
};
return builder
})();

This lets you do:

newObj = Object.build(oldObj,{name:'Ironboy',age:'old'})

ironboy
09-29-2011, 01:51 AM
Hm, actually this is how Mozilla describes that Object.create should work... - the second argument is the object's own properties...
So if it always take the second argument with properties in all browsers where it is implemented natively - I could change the "mini-library" around slightly to replace Object.create only when it does not exist...

ironboy
09-29-2011, 01:56 AM
Nope, Microsoft does not agree on the second parameter, they want ECMA5 descriptors to go here instead:
http://msdn.microsoft.com/en-us/library/ff925952(v=vs.94).aspx

ironboy
09-29-2011, 02:06 AM
Ok, Mozilla's decription (that I linked to) must be outdated - after some tests in different browsers it seems to me that all of them, including Firefox, expects ECMA5 descriptors as the second argument...

Old Pedant
09-29-2011, 05:28 AM
Sorry, I see no reasonable correspondence between ECMA5 descriptors and constructor arguments.

Sure, I can pass additional properties. But I can't initialize *KNOWN* properties already in the prototype. Worse, the notation is horribly clumsy compared to passing a list of arguments.

It's just as bad as the name vs. moniker example I gave, but probably worse. It hides things even more.

Don't get me wrong, I see uses for it. But it does *NOT* replace the extreme simplicity and reliability of constructors.

ironboy
09-29-2011, 05:35 AM
I understand what you mean, in a way.

Still I think traditional constructors are ugly - hiding away the real prototypical potential of the language - making peoply "inherit" in all horrible sorts of ways - outside the prototypical scopy - take jQuery's extend function as an example.

I think we can leverage things like Object.create and descriptors to build a new cleaner foundation for object handling. Chances are there will be less "clumsy" ways of handling descriptors in the future - coercing JavaScript into being a less of a "wild west".

Old Pedant
09-29-2011, 08:34 PM
Well, you can always do it the way VBScript does.

It, too, provides no constructor. So the tradition is to create an INIT method for each class that you use immediately after creating the object. Unfortunately, that name is not required/enforced, but we could presumably change the rules in JS to require it. Or at least provide for it.

So then you could do:


var newObj = Object.create(somePrototype).init(list,of,values);

But that gets back to my original question: Why couldn't we require that prototypes provide a create method so that you could write


var newObj = somePrototype.create(list,of,values);

I could support that code pattern much more readily.

Fun discussion. I tend to think that the JS driving committee is too focused on purity and not enough on practicality. I'd really *like* to see some more "syntactic sugar".

ironboy
09-29-2011, 09:44 PM
I agree on both points: Fun discussion and syntactic sugar in the right amount is good for you ;)

There is an object prototype and it already has som native methods so why not add one more (non-enumerable of course)...



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum