Can a var use it's past self?


#1

So I was mulling over some cool things I could use in my code and I though of this would this command work?

var type = this.findEnemies();
type = type[0];

Would this var be able to use itself before it was defined I know that this would be decided by which occurs first would the check occur before the redefinition?


#2
var type = this.findEnemies();
type = type(0); // error: type is not a function

That’s what you would get.

Though yes, you should be able to reassign a value to a variable using the stored value. (Unless you use ES6’s const keyword…or if I’m misunderstanding your question.)


#3

Every example is separate.

// Does not work, a not defined
var a = a;  //ERROR!

//Does work
var a = 0;
a = a;

//You can also do computations
var a = 10;
a = 2*a + 1;  //a = 21

// Don't have to initialize variable immediately
var a;
a = 1;

//But can't use it before initialization
var a;
var b = a;  //ERROR!

I hope I didn’t forget anything and covered everything you wanted to know.


#4

Thank all for the help!

And JFBM I mean the third one down


#5

I believe a few of those examples are not quite correct regarding initialization. Here’s the actual output:

var a = a;
console.log(a); // undefined
var a;
var b = a;
console.log(b); // undefined

See var hoisting.
All var declarations are implicitly initialized to undefined upon entering the scope in which they’re defined, which even allows you to write some crazy code like:

console.log(a); // undefined
a = 1;
var a;
console.log(a); // 1

Is interpreted as:

var a = undefined; /* hoisted and implicitly initialized to undefined */
console.log(a);
a = 1;
console.log(a);

JavaScript’s var semantics are pretty confusing for beginners in my opinion, so of course it is better to just stick to the basics. Using a variable before it is defined (although it being perfectly valid code according to the spec.) is a terrible practice independent of your technical level, as it just makes the code harder to read. It is nice to know these little details though, so you can avoid common pitfalls.

If anyone is interested in further reading about the var semantics, check out the MDN and Adequately Good articles.

Thankfully, ECMAScript 2015 (the newest JavaScript specification edition, a.k.a. ES6)'s let and const declarations have much better and simpler semantics than var. They are block-scoped (var is function-scoped) and they actually throw an error if used before being declared (var-declared variables hoist and thus evaluate to undefined).


#6

@Feinty As for your initial code:

var type = this.findEnemies();
type = type(0);

The problem is that you’re using parentheses which try to call type as a function. You want to use square brackets (property access, a.k.a. “array index access”):

var type = this.findEnemies();
type = type[0];

You can also do it all in a single line:

var type = this.findEnemies()[0];

#7

In retrospect that was me confusing some language-concepts. It is indeed no error to use a variable before initialization, but not very useful either. Also of notice:

//Using variable without var results in error
if(enmy){ //just a small typo...
    //...
}

//Assigning late without var
loop{
    if(enemy) { /*...*/ }    //Error: enemy is not defined
    enemy = this.findNearestEnemy();
}

//Assigning without var
loop{
    enemy = this.findNearestEnemy();
    if(enemy) { /*...*/ }    //Works like a charm
}

To sum it all up: Initialize your variables once with var (if you want at the beginning of the code for example), check your assignments and conditions.

Sadly let is not available to us, as it is part of Javascript 1.7.


#8

Nice notes. :smile_cat:

Assigning to a variable that was not declared with var will result in implicitly creating a global variable, which often results in undesirable side effects (or even worse, throw an error if the code is in strict mode).

Sadly let is not available to us, as it is part of Javascript 1.7.

Note: “JavaScript 1.x” refers to Mozilla-specific language extensions. let was initially part of such a proprietary extension, but it has since been incorporated in the official specification of the ECMAScript (a.k.a. JavaScript) language, in ECMAScript 2015 (a.k.a. ES6).

It is also important noting that the TC39, the technical committee which steers the ECMAScript language specification, has decided against versioning the language. That is, all new spec. publications will always add to the language in a backwards compatible way, and browsers are already gradually shipping ES2015 features.

As for CodeCombat, it is possible to add support for let/const by improving Aether – it already has a compiling step which transforms ES2015’s generators into ES5-compatible code through Traceur, a tool for compiling JavaScript.next to JavaScript-of-today. So the core of what we need to support ES2015 features is already there, we only need to fix any issues with the rest of the Aether pipeline – e.g. tweaking the JSHint settings, check if there are issues with the logging, flow analysis and sourcemapping. I wonder whether @nick has already attempted this?

An issue though, is that due to the way CodeCombat/Aether implements the yielding logic, we don’t even have full ES5 support yet. So I believe a good plan would be to raise the bar gradually, by focusing on adding support for the missing ES5 features and then move to the next language spec. edition(s).


#9

Ah yes I see what you are pointing out I’ll fix that


#10

I haven’t done anything to support ES6 features because JS_WALA can’t handle them, although I think most or all of the other tools involved could do it. Updating JS_WALA myself for this doesn’t sound like a fun time. It’s possible that we could just drop the JS_WALA step and start handling more complicated subsets of JS in our Aether transforms, but I haven’t looked into how difficult that will be.


#11

Thanks for the insightful feedback. :smile:
Indeed, JS_WALA seems to be the only tool in the Aether pipeline which I’m not familiar with yet.
I have a pretty tight schedule, and I’m still just starting to explore the CodeCombat/Aether code bases while juggling between open source projects. Though, adding ES’15 (ES6) support is a very interesting medium-long term goal to explore.


#12

I think it would be appreciated to update to ES6, for both the users and the ideas that you are teaching a new set of programers who will use the new standards. Not that it will be easy, just showing my support of the idea.