Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'll admit it, I haven't yet mastered the language, but my experience with it tells me that Javascript is a highly flexible language, allowing prototypal inheritance, dynamic typing, functions as first class citizens and so many more cool stuff. I think such features bring some inconsistencies, but that's nothing new, most people would agree with me. I wanted to discuss specific examples that have been annoying me, like "for in" loops:

for(var role in rolesToAdd){
                if(rolesToAdd.hasOwnProperty(role)){
                    // for body
                }
}

Why should I need to do this? Doesn't this break the concept of classes and inheritance? I might not want to loop through the whole prototype, but what if I still need some of the attributes/methods from an object's direct parent, for example?

Also, I would be most grateful if someone could explain me why the interpreter doesn't allow synonymous global/local variables to share the same scope, when there is certainly a way it could distinguish one from the other. Like in:

var foo = function() {
        var wth = bar();
        var bar = wth;
        // body...
}();

function bar(){
    return 'bar mitzvah';
}

You can see that, even though our local bar has been declared after the call to our global bar, bar's value in foo's scope will always reflect the local bar, which will hold 'undefined'. Isn't that a strange behavior? I would love if senior Js programmers enlightened me on this and showed me what is gained from these seemingly strange features and if the disadvantages I mentioned here are valid.

share|improve this question
3  
Frankly, not all of the inconsistency is from high flexibility (as e.g in Python or Clojure); some is from poor design decisions. Unfortunately, we're stuck with JS since the time Netscape made it the de-facto standard in every browser. –  9000 May 15 '13 at 2:21
1  
relevant steve-yegge.blogspot.co.uk/2008/10/… –  jk. May 28 '13 at 14:28
add comment

2 Answers

Why should I need to this? Doesn't this break the concept of classes and inheritance? I might not want to loop through the whole prototype, but what if still need some of the attributes/methods from an object's direct parent, for example?

JavaScript is essentially a functional language that has imperative style. JavaScript can fake classes and inheritance, but they aren't well-supported first class concepts. As such, you'll naturally hit some walls when you want to express ideas that way. There are some good treatments of JavaScript as OOP around the Internet. Chances are good that if you're hitting your head against a wall with JavaScript, somebody else before you did as well.

Also, I would be most grateful if someone could explain me why the interpreter doesn't allow synonymous global/local variables to share the same scope, when there is certainly a way he could distinguish one from the other.

The dynamic type system means that the interpreter cannot say what the type of bar is. As a bonus side note, JavaScript also performs hoisting automatically.

When I executed your example code, I got a complaint because foo is an immediately invoked function expression, so bar isn't defined at that point.

TypeError: bar is not a function
var wth = bar();

But suppose that wasn't the case. When you assign wth to bar(), it sees that you're attempting to invoke bar as a callable. function bar() is almost syntactic sugar for var bar = function(). Note the link in Neil's comment for why it's "almost."

The type system cannot differentiate between var bar = 5; and var bar = function() { return 5; } because you can do evil things like the following:

var i = 5;
console.log(typeof i);
i = 'hello';
console.log(typeof i);
i = function() { return 'f'; }
console.log(typeof i);
console.log(typeof i());

The output will be:

number
string
function
string

This is what I mean by the dynamic type system cannot say what the type of bar is; a variable just holds data and the data has a type. So if you try to do something like:

var i = 5;
console.log(i());

You'll end up with a type error because i isn't a callable and you're trying to use it as one.

share|improve this answer
2  
To be precise, function bar() is not the same thing as var bar = function(). See here for more details. –  Neil May 15 '13 at 10:35
    
The type system isn't the issue in this case hoisting is, he can't call bar as a function there because it no longer is a function. Also on a pedantic note while classes aren't first class inheritance is. –  Calvin May 28 '13 at 20:43
add comment

It's assumed you want all the iterable properties of an object, you only need to use hasOwnProperty if you think there are methods or properties in the object or its prototype that should have been marked as non enumerated but weren't. You seem to be fighting against the language where it is assumed your going to want all the properties of the object your iterating including all of the ones it inherited. You need to remember that

JavaScript Does not have classes

this is important, you can simulate classes using libraries and classes may be added in ES6 but currently it has prototype based inheritance which which burn you if you try to pretend it's exactly the same as a class based one.

Your second issue relates to functional scoping,

var foo = function() {
    var wth = bar();
    var bar = wth;
    // body...
}();

function bar(){
    return 'bar mitzvah';
} 

is really.

var foo;

function bar(){
    return 'bar mitzvah';
} 
foo = (function() {
    var wth;
    var bar = wth;
    wth = bar();        
    // body...
})();//you want parentheses here I'm pretty sure.

The issue is that new variables are hoisted to the top of the local (functional) scope meaning that even though you haven't redefined bar yet, as far as the language is concerned you have.

I honestly don't know the advantage that were in mind when it was created, if you really want to know you should ask Brendan Eich (no seriously he has been known to answer those questions on twitter), it is a feature though that I'm not sure many people who use JavaScript necessarily like as much as deal with.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.