CHUCK:
We’re trying to maintain a clean rating, so if you can help it that will be nice.
JOACHIM: All right, well I am naked. [Laughter]
CHUCK: Aaaah! That’s like Avdi in his gold bikini.
JOACHIM: Obviously I’m not just going to you know, blurt it out.
JAMISON: I can actually hear that you are naked on the podcast. So you might wanna edit that. I can tell it through your voice.
JOACHIM: I’ll eventually, hang on.
JAMISON: Oh, gosh. [Laughter]
CHUCK: Hey everybody, welcome to the JavaScript Jabber podcast. This is Episode 5. This week on our panel, we have AJ O’Neal.
AJ: Hey, guys!
CHUCK: We also have Yehuda Katz.
YEHUDA: Hey, hey.
CHUCK: We have Jamison Dance.
JAMISON: My name is Jamison Dance and I have a problem.
CHUCK: [Chuckles]
JAMISON: Oh, wrong podcast. Hi.
CHUCK: And we also have Joachim Larsen.
JOACHIM: Hey all.
CHUCK: And I’m Charles Max Wood from teachmetocode.com. Real quick, I've been accused of not letting people know that I have other podcasts, so I’m just going to tell you really quickly; we also do rubyrogues.com that’s the Ruby Rogues podcast, where we talk about Ruby; and rubyfreelancers.com where we talk about freelancing -- same format as this one. So anyway, this week we are going to be talking about “Objects in JavaScript,” which is kind of not as straightforward as you might think or want it to be. And since I’m not the expert here, I’m going to let somebody else go ahead and jump in and start us out.
AJ: What do you wanna know?
CHUCK: [Chuckles] Well, okay so—
JAMISON: Everything.
CHUCK: Okay so basically, I've been reading ‘JavaScript: The Good Parts’ and so the first thing he talks about is your general objects which most people kind of equate to do a dictionary or a hash, but it’s not exactly the same thing. It’s actually quite a bit different from that because the attributes and stuff that are there, I mean, you can have attributes of functions and attributes that are data and stuff like that, and then you also can define objects in a way with functions because functions are closures and so they capture the… (What am I trying to say…) the context of everything around them. And so—
JOACHIM: Variables, yeah.
CHUCK: Right, so you can set them up to kind of remember certain things about certain things and so, it’s kind of confusing. And then on top of that, you also get the prototype stuff and so you don’t actually necessarily define the class, but you kind of inherit the prototype of another object. And so it’s all kind of confusing as to how it sticks together. And so, I thought we could just get in and talk a little bit about how it all works. And maybe we should start with general objects and prototypes and how that kind of works and then we can move in to some of the other stuff.
AJ: Okay, so objects are hashmaps, right?
YEHUDA: They used to be hashmaps. Now they are hashmaps with a bunch of extra stuff as of ES5 and more stuff with ES6, but it’s a good starting point for sure.
AJ: Okay, well the basic premise of it is as it is in Python and Ruby and tons of languages -- associative arrays or hashmaps, or whatever you wanna call it -- and they got some additional features, but you can use the literal syntax to create an object which is just two brackets. So, var foo = { } and then you got yourself an object. Or you can do something fancier like… I’ve never actually called new object but I think you can do that. [Chuckles] And then you just throw stuff into it.
CHUCK: Right. But new object, you create a function around the object? Or something like that.
YEHUDA: So basically what's happening is when you use the “new” keyword on something, you are calling it on a function; that function serves as a constructor. So, I'll say pretend that you already know what a constructor is in another language. So when you say “new” some function, that function serves as constructor, JavaScript internally makes an object, base an empty hash and then it gives that object to the constructor, then the constructor can do whatever it wants inside of that constructor is the object that was just created and then you get back the object. So, that’s basically what new was doing. New was very… I’m actually not someone who likes to… I know there's a group of JavaScript programmers who like to pretend that ‘new’, it doesn’t exist and was mistake, but I think it’s cool. I like it.
AJ: Generally what I do is I create a function… I've seen this kind of pattern that I really like, where people check to see if this is a new object and if it isn’t, then they recall the function with new, so that if someone naively uses it the wrong way, it still does the correct thing. And another way is to append the method onto a… let’s call it a function class; all functions can kind of be classes like we are saying here. So, say you do function foo then you can do foo.create=another function return new foo. And so I kind of like that pattern. And one thing I
wanna point out with the new syntax is if you are not using es5 or strict mode, which I can’t see any reasons why you wouldn’t want to, but if you— [Crosstalk]
YEHUDA: If you want ‘arguments.callee’ that then you might want to keep using old mode.
CHUCK: Say that again Yehuda?
YEHUDA: If you want arguments.callee, that’s a feature that isn’t really fixed in ES5, so you might— [Crosstalk]
JOACHIM: Basically arguments that is going to go away completely.
YEHUDA: So basically, if you are stuck in a world where you have to support old and new API and for some reasons you need arguments.callee or arguments in general, you might be forced to stay at a strict mode, especially as strict mode becomes stricter.
AJ: And an important point I think to note about that is that is going to be generally just the case of fire buck, like your average applications aren’t going to use that and then they are not going to need it. And when you use it writing your own new code, it’s not going to affect you. It would be if you were to try to take legacy code or try to take a large library that is debug-driven; so a debugger library would be the kind of thing that uses that callee not minimal code.
YEHUDA: So the old SproutCore -- so not Ember but Old SproutCore – used arguments.callee to implement super; we don’t do that anymore but that’s how it used to work. So there are definitely reasons why people would have wanted to use arguments.callee before that might still exist.
AJ: Yeah but there's definitely work-arounds where you can just—
YEHUDA: Absolutely.
AJ: Put a… if you think you need callee, usually what you can do is create an object and then assign your function to a property of the object; that way you have a reference to the name of the function when you need it later on.
YEHUDA: Absolutely.
CHUCK: All right, so we talked about constructors and basically what Yehuda said was that it creates kind of an empty object and passes it to the constructor and then the constructor does stuff on it, adding stuff to the prototype or adding attributes to it, is that how that works?
YEHUDA: Not to the prototype. So basically the way prototypes work is really straightforward. So when JavaScript goes to look up a property in an object, the first thing it does is it looks it up in the object and then there's a secret property called internal [[Prototype]], but sometimes its exposed as __proto__ and that property is what JavaScript looks at next. So if you basically… if JavaScript fails to find the property on an object, it doesn’t stop there; it goes and looks at the prototype of that object and then goes to look at the prototype of that object etc. And one of the things that happen when you use the ‘new’ keyword is that the internal prototype of the object that you are creating is the ‘functions.prototype’ property. So what basically that means is that if you have a prototype property on a function, and you call new on that, after JavaScript finishes looking at the object that you just created for properties, it will go look at the function.prototype and then possibly that thing might have its own internal prototype.
CHUCK: Okay. So that leads me to another question and that is, if you change that function prototype later on, is I referenced or is it copied?
YEHUDA: It is not copied; it’s basically just internally it’s pointed to that object. So JavaScript is basically just walking the prototype chain looking for the properties, so if you change any of the element of the prototype chain, it will find it just fine.
CHUCK: Okay.
YEHUDA: Internally, there's obviously a lot of caching magic that JavaScript does to make things fast, but you don’t have to worry about that.
JAMISON: And that explains a little bit about why people get grumpy about changing object.prototype, like you can do it and some people do. I think Ember does it. Doesn’t it?
YEHUDA: No definitely not. Absolutely not.
JAMISON: No it doesn’t? Okay. Y
EHUDA: Absolutely not.
JAMISON: Anyways, there are some… I can’t remember what it is but…
JOACHIM: prototype.js? [Crosstalk]
JAMISON: [Inaudible] prototype and people get upset about that because it changes the prototype which is like the final chain in the prototype chain… the final link of the prototype chain for everything in the whole runtime. So that’s kind of why people don’t like that.
YEHUDA: So I think there's definitely… there's a larger discussion that exist about overriding native prototypes. So like should you override array? And then within that, there's should you override array to polyfill old features? Like should you add map if it doesn’t exist in IE, versus should you add totally stuff? And then there's like, should you add stuff to object.prototype? I just think object.prototype is a disaster because a lot of developers try to iterate over objects without specifically limiting the iteration to the properties that are in… just on that object. So if you just use the hash just like an options hash and you start iterating over it, you’ll get the things that were on object.prototype.
AJ: Right. And that problem applies to the ‘for x in object’ approach. Object.keys approach which is available in everything from Internet Explorer 9 and then browsers as well, [chuckles] will work just fine.
YEHUDA: So I don’t know, I haven’t done benchmarks; I would imagine that objects.keys would be slower because you have to iterate it twice. But I don’t know if that’s true or not.
JOACHIM: We actually did recently on the Node.js mailing list, there was a bunch of benchmarks done on that, and FireFox and Chrome have vastly different results for that, where Chrome has really good results for ‘for each’, while FireFox I believe does keys really well.
CHUCK: Interesting.
AJ: And so the thing to keep in mind is never pre-optimize. If you find that something is slow, fix it but don’t choose to use older methods that are less safe because you think that maybe it will be faster or slower. I mean, I had a case where changing a few things resulted in the difference between about three seconds to about 80 milliseconds, but I was iterating over… it was a very specific process involving converting a raw binary image that was custom charset, get request. I mean it was a very edge case.
YEHUDA: That’s obviously different in my code in framework.
JOACHIM: I mean my point of view about objects; I try not to use them. I mean, basically whenever I have a lot of objects I use an array and I use hashes and I just iterate over the hashes and then I have functions on top of that to kind of pull stuff out. And I guess it’s kind of like… I kind of grew up where I learned… from education background I do oriented programming, there always seemed like something that was because programming is hard so you need a one to one mapping between the real world and you know, how you are going to make programs and stuff like that. But I find that you add all these layers to it for no reason in many cases, I find.
AJ: Yeah and with the prototype, you don’t have a whole lot of layers anyway because like Yehuda saying, where you jump up the prototype chain, so it does makes sense to keep layers to a minimum.
CHUCK: Right.
YEHUDA: I guess I come from the code sharing school of thought and it’s useful to use prototype chains to share code, just like it is in classical oriented programs. But there’s for sure another school of thought which is like, the Lisp school of thought which is like, “I [inaudible] make functions that operate on y hashes.” I don’t know. I can’t say I’m in that school of thought, but I know people who are.
JAMISON: So my thing with that is you still some way to combine those common functions that operate on that stuff, don’t you? ‘Cause I don’t know, it just seems really messy if you did a decomposition as just the function, then you have tons of functions scattered all over the place.
YEHUDA: Yeah so you could obviously… so basically what ends up happening is that you structure things in namespaces, but then I start to wonder if you are just rebuilding classes with—
JOACHIM: Yeah that’s fair. You know, that’s fair. I guess it depends if you are talking about frameworks or if you are talking about applications themselves where you are not really kind of seeing this kind of third party sharing. But I will say that for what we are talking about in terms of sharing, I think it’s much more important to have events, like have a consistent and kind of like an established event system rather than objects. Like I’m seeing all these stuff in discuss about we need to have object constructor and stuff like that, and I’m kind of curious who cares if we can share objects from one place from one library to another if they don’t talk the same way internally; whereas with the consistent event system I think we could get a lot more done.
AJ: What do you mean by “event system”?
JOACHIM: So basically that you… the same as in Node.js that you fire events and-- [Overlapping talks] Right, right, exactly. But if you do that in the client, then you can have much wider kind of reuse and cooperation between components.
AJ: You mean as opposed to using callbacks all over the place, do events where it makes sense?
JOACHIM: Well to my mind, events are kind of like callbacks in sense because you have a handler but you just put the callback in the handler for that listener. But I mean instead of using, you know, this is my public function and this is my member function, member method, public method and then you need to kind of call this by name whereas you can just emit events and where the ones who grab them and listen to then can use them.
YEHUDA: Yeah. So I’m actually a big proponent of events have been historically, and there's definitely a win when you have one to many events. I’m not sure why you are saying that that isn’t already true about the browser environment though.
JOACHIM: Well, because I don’t see it; I don’t see many framework or many like you know, I don’t see many shareable libraries or sharable bits of code that are based around events.
YEHUDA: So I think there's a reason for that though. I think… so there are definitely are events, but it’s definitely clunkier to be firing events as opposed to calling methods. I think that there's a lot of libraries, (Ember included) that uses events a lot internally after you trigger… like you call methods. So I think there's more new ones going on in practice. For sure like the browser environment is heavily evented, so anybody who writes like jQuery almost all that is going to be using events and jQuery itself exposes a custom event API that’s pretty popular, I think for regular objects. JQuery has supported custom events on arbitrary objects since like 1.3 maybe or earlier.
JOACHIM: Well I’m just thinking like, I mean personally, I like to use ES3, it uses a lot of events as well. I’m just curious as to why es-discuss is so kind of... so focused on objects, so focused on object constructor.
YEHUDA: Because es-discuss is about the language and events are basically a library, right? So maybe it makes sense if es-discuss standardize events—
AJ: Oh, definitely.
YEHUDA: So that’s fine. I’m not against that. But I don’t think it’s fair to say that the environments that have JavaScript don’t have events. They all do. They all have event systems. It will probably be nice if there was one of them that work in Node in the browser, but I think that’s sort of a… that’s a library issue.
JOACHIM: Right. But I mean then you can say well, everyone has objects right? So why do we need to standardize them?
YEHUDA: Well, it’s not standardizing objects, its standardizing new syntax to make writing common object oriented patterns more easy.
AJ: So I think it’s kind of the thing with events is it wasn’t standardized in language probably as well because back from the beginning, we didn’t use them so much and it wasn’t… we didn’t realize the importance of it. But in relation to what was said earlier, I find it that a lot of times, where callbacks are the only pattern in a library for exchanging data, it becomes really cumbersome really quickly and using something like… for all my code, I use Node event emitter that I've made like a two line change to so it works in the browser. And I find that definitely helps me to organize the code a lot better in general.
CHUCK: All right, well I’m going to bring this back around to objects and object creation.
AJ: Haha.
CHUCK: I’m a little bit curious—
JAMISON: (Thanks Chuck!)
CHUCK: [Chuckles] No problem. So, one thing that I've seen is that it seems like a lot of people like the ‘new’ function syntax but then a lot of people are saying, “No, don’t do that. Use this other method where you basically create a function that creates an object somehow or creates another function that acts like another object,” or something like that. What is the other approach rather than using ‘new’?
AJ: So there's basically three paradigms; there's ‘new’, there's ‘literals’ and then there's having a function that's called ‘new foo’ or ‘create foo’.
CHUCK: Uh-huh.
AJ: And the advantages and disadvantages I see are that when use just the prototype, you don’t have as much privacy over the data, so everything that you modify has to be modified in this and this whatever on this, its public. And one of the problems in the non-strict mode with that method is that this is implicitly global, so you can accidentally fudge up the global context, whereas in strict mode, that will be null. If you do the create method, you get the data privacy because you can declare var… basically your object is your closure, right? And so whatever you return is what's public. But whatever you don’t return stays private in the closure and you can have methods that modify things privately. But then that is going to take up more memory. And in most cases, I think that’s not a problem, but there was one case where I had like 10,000 objects and to use it on a mobile device, it’s more efficient to use a prototype and have a function that gets an item out of an array or something, and then the last type is just creating object literals. I don’t really understand that method as well but I've seen used a lot in things like jQuery, whether it’s just big, huge object literal and it always references this to get any functions or properties in that.
CHUCK: Okay so.
YEHUDA: I don’t think that’s a correct analysis of what's happening in jQuery. So jQuery for sure uses the prototype system. When you call the jQuery method, its basically just like the create approach, like you normally— [Crosstalk]
AJ: I admit the code of jQuery like when you look in the jQuery code itself, it’s got like this huge object literal with like every function that’s in jQuery— [Crosstalk]
YEHUDA: Well, that object literal is defining a prototype.
AJ: Ok. Yeah, I didn’t realize that.
YEHUDA: So there's like a ‘jquery.fn.init’ which is like a constructor and thing has a prototype on it which is what everything is defining and what happens… and that really is the jquery.fn… jquery.fn.prototype is the alias to jquery.fn. So every time you do like jquery.fn.blah, you are basically extending the prototype of things that the jQuery function creates.
CHUCK: Oh, interesting.
YEHUDA: Which is why you can have plugins so easily because basically you are using the prototype system.
CHUCK: So, when you use the function newX() principle, I’m a little bit curious as to how the private data works. It’s all saved in the closure, right?
AJ: In the constructor.
CHUCK: Okay.
JAMISON: So if your constructor is a function, then inside that function you just define variables and functions and stuff and those become private data, right? And then you can return just an object literal with— [Overlapping talks]
JAMISON: Sorry, what was that?
AJ: If you are using new, then you can’t return anything. The only thing you can return ‘undefined’ otherwise— [Crosstalk]
YEHUDA: I think it’s worth noting that there's of course a hybrid approach; where mostly your stuff is on a prototype but you want some private data that's passing through the constructor and you add a few methods on an object. I personally really like the prototype approach because it makes it easy for modifications to be made if necessary. I think the people who like the constructor approach have an over obsession with privacy. I mean I like privacy, I’m Ruby person; I use the private feature in Ruby, but I like the fact that in Ruby, private is like advisory. You could be like, “Actually, I don’t like you. I'm going to change your mind about privacy.” In JavaScript, if someone decides to make something private, by making it closure, it’s like actually private -- sealed. And I think people who like to have an over obsession with privacy, I think it will be superior to just make things public and then just let people… make some convention makes it hard to make mistakes about what people do things that they need to.
AJ: I think you are right in a lot of cases too because your module that your using is going to have its prototype sent in as probably enclosed in a function anyway, so it’s not like another API that’s being included on the pages is going to be able reach in to that closure of your module.
YEHUDA: Exactly. So one thing that we do in Ember -- like all the time -- is every single file is by the built system wrapped in a closure. So what that means is that, we can like use local variables there that are used inside of the prototypes at will. So we’ll like, here is a constant we would like to use over and over again. Here's a function that we would like to use. And those aren’t like on an object anywhere, they were just hanging out in that file but because gets wrapped in a closure, we can do that.
AJ: Right and that’s common with I think every built system that I've seen.
YEHUDA: Exactly. Correct. So basically if your file is getting wrapped in closure, you have automatic space to do whatever you want. You can’t do per object private stuff, but again I've had enough trouble with trying to deal with people who have made things per object private stuff, where was like, “Actually I need to change that because I need to get something done.” And that’s just my aesthetic is that, I don’t think that when I make a library, I’m perfect, I think I sometimes make mistakes like the fact that in Java some things are final and it’s like, “Sorry, its final, you can’t ever change it.” Like maybe those things are mistakes and you now are stuck.
AJ: And I haven’t worried too much about it myself -- the privacy -- but I do realize that you’ve got a Facebook thing on the page, you got Twitter thing, you got ads on the page and so, if you do expose something that gets into the global scope, everything’s got free rain to modify the prototype of it or whatever it will.
YEHUDA: Yeah.
JAMISON: I think part of the difference too is kind of like aesthetics, right? Sometimes, to me at least, it feels weird that I’m defining this object and all of its properties are kind of defined outside of it. I don’t know, maybe that’s just something I need to get over, but like it seems like it’s not… It’s just weird to not have it all self-contained, you know.
YEHUDA: That’s the reason for the class syntax. For the es-discuss class syntax, specifically to make a syntax that shows that that’s what's happening.
JAMISON: Yeah.
YEHUDA: I think that’s good. Just to sort of go back to something that we said earlier, I actually think it’s very important for the TC39 to wield syntax and for that to be the main thing that they do, because everything else can be done without TC39’s approval. JavaScript community has done stuff, Node adds things, DOM people add things, browsers add things but syntax is not something that anybody can add without approval. So I think to the extent of problems like what you just said, like A. it’s really hard to do prototypes; it’s really esthetically weird to prototypes because now you can’t see it as part of one thing, and people are doing all these things all the time and everyone obviously syntax needs to be wield carefully because its forever, but I think that is a good thing for them to be working on.
CHUCK: Yup. So really quickly, when we are talking about private data, it’s always contained within the closure and not necessarily within the object that’s being returned, right?
YEHUDA: I’m sorry, can you repeat the question?
CHUCK: So basically, when you have some object with “private data”, basically that's all within a closure that’s connected somehow to the object, right?
YEHUDA: So it’s exactly the same as in jQuery if you have like a click handler and you have some data in the closure that you only have access to in the click handler. So basically if you have something in the constructor and then you expose a public thing on that object that has access to that internal data, obviously, that's the way to get access to the internal data because it’s hidden from the world in the closure.
CHUCK: Right. So when you have some constructor function that creates an object with this kind of private data, then how do you set it up so that that kind of gets carried along with it? Do you return an object with functions that reference that data?
YEHUDA: So, like the canonical example to this would be let’s say you have an object that is an incrementer or and you don’t want to expose the number for some reason, like you only want to expose the ability to increment it. So what you do is inside of the constructor you say like var i = 0 and then you say this.incur = function i++.
CHUCK: Right.
YEHUDA: And imagine that there's another function that like uses that “i” to do something else so you can say like, this got some other function = function like print i. So you don’t want to expose people’s ability to modify i directly. So this will be an example of a case where you want i to be available for some reason but you don’t want someone going in and saying foo.i = 12.
CHUCK: Right.
YEHUDA: So you say var i = 0 and you provide a way to modify i in a sanctioned way and you probably provide another thing that exposes i in a way that you find important and now you have a private i.
CHUCK: “You have a private i”. I love that.
YEHUDA: No pun intended.
CHUCK: [Chuckles] Right, where you can inspect. Anyway, so then I guess the “i” variable is then stored in the closure for each of those functions?
YEHUDA: Exactly. So every one of them would get its own i. So the prototype way of doing it would be that you would say the thing.prototype or constructor.prototype = [i0] which would also get every single one its own i, but not every object has i exposed as a property i. And you would say this.i everywhere.
CHUCK: Mh-hm.
YEHUDA: And that means that you are allowing people to modify and the sort of compromised hybrid way is that you do something like _i which says like, “This is public in case i screwed up and it’s important for you to modify it. But hey, if you do that, you are messing with something that I’m asserting as private.”
CHUCK: And is that a common convention or is it just something that you generally do?
YEHUDA: I think it’s common. AJ, do you think that’s common?
AJ: Oh, I’m sorry what was that?
YEHUDA: Using the underscore as like indication that something is kind of private like, “Please don’t mess with this.”
AJ: Oh, yeah. I've definitely seen that a lot. I know JSLint complains about it.
YEHUDA: Really?
AJ: It doesn’t like you to have underscores, which is something I don’t like about JSLint because I think that the underscore is a pretty good indicator.
YEHUDA: Like in Ruby we have a private signifier which basically says like, “If you call this method, there will be warning,” right? And underscore essentially does the same… I think Python does the same thing. The Underscore is in notion of like the person is telling you that if call this think about it before you do that because if you do it, you are violating the expectation of the library.
CHUCK: Right.
YEHUDA: I think that’s fine. I think expressing expectation in the library is the most important thing and if someone goes in and reads all your code and says, “I know that I can monkey patch this thing and it will be fine,” then that’s ok. I’m okay with people doing that. Although they are taking the risk on their own hands at that point.
CHUCK: Yeah.
AJ: I think that’s a good pattern to apply when you wanna have the prototypes and allow people to have the public access to it but then, it’s very clear that they shouldn’t been private if it had been in a closure for example.
YEHUDA: Yeah someone told me that they like recently came over to me and told me that they overrode the destroy method to not do anything in Ember. Like for subclass in Ember and I was like, essentially felt the same way, I was like, “Fine. If you feel like that’s fine but just FYI I did not reasoned about that case at all, so if you do that, you are essentially… things may break that I didn’t think about,” and that’s basically underscore, right? Underscore is, “I have not thought about what happens if this something different, but if you wanna take that risk, seems good.”
CHUCK: All right cool. So one other thing that I want to point out because this is kind of a basic concept to JavaScript, really quickly, can I get one of you guys to define a “closure”?
YEHUDA: So a closure is basically a… you could think of it as an object which has all the current local variables in them as slots and that object is stored off and whenever any function inside of that same scope gets called, although that object gets reanimated. So basically all the local variables are stored off somewhere so whenever the callback gets called, those local variables returned from deep freeze and made available to that function. AJ probably has a better explanation.
AJ: So— [Crosstalk]
JOACHIM: You have the context of when the function was defined. How you say that? Like, what do people— [Crosstalk]
CHUCK: That’s basically how I understand it.
AJ: If you think of another language where there are global variables and there are local variables; and inside of a function, if you modify the global variable, when you call that function the next time the global variable is still modified, so local function or local variables exist for the derivation of the function but the global variables persist forever, right? Makes sense?
CHUCK: Uh-huh.
AJ: So then take that a step further where you can have nested scopes. So it’s kind of like every time you have a new function that you've created, any variable inside of that function is global to anything below it. So anything that visually can look at it, and see that here's a function and another nested function, and another nested function, and another nested function, if a variable is declared at the top scope, its quasi-global for everything below -- and that's what we mean by closure. Additionally, closures extend through time. So if you have a callback, even though one function has returned, that callback function may have or will have access to all the data that existed at the time the first highest level function was called.
JOACHIM: So it’s kind of like a quantum superposition of all variables that were in that scope.
JAMISON: Oh yeah, everybody understands “quantum superposition”. [Laughter] [Overlapping talks]
CHUCK: Does that give you a Quantum of Solace?
JAMISON: I think I have to think about that for like half an hour and then maybe it’ll make sense to me.
CHUCK: [Laughs]
YEHUDA: I think what AJ just said is the most important thing, which is that the variables are always available to every invocation of any callback. So if you have… lets go back to i, If you have an i that you define i=0 instead of function and then there's callback inside of there that gets called over and over again, like a click handler, it’s always referring to that same i, it’s not referring to… it doesn’t get a new copy every time or it doesn’t become null or $undefined; it’s always referring to whatever it was when it started and then any modifications also affect future things that look at it.
AJ: On that note, so JavaScript doesn’t have threads, but it does have callbacks and so you run into the same shared memory problems more or less than you would with threads, with callbacks and closure.
YEHUDA: Thank you so much for saying that. So I don’t know if this a thing that people still say, but back when Node was just getting popular, a lot of people were like, “Because of event, that means that there are no shared memory problems, evented is awesome.” And like my initial reaction was, “I've been doing JavaScript for a while and closure has actually made the problem worse,” right? Because basically, when you have closures, you have a ton of shared state, and there's no reasoning about it. So any callback that gets called can modify any state that’s upstream of it and if you end up with a lot of nested callbacks, you end up with a lot of callbacks that are modifying the same shared state. That doesn’t mean it’s bad, it’s just means it doesn’t actually solve the new text problem.
AJ: But that’s why I say always put your functions in the highest scope possible. If you’ve got a function that’s reusable, don’t put it down in a nested scope where its 7 functions in because you will have that problem much more often.
YEHUDA: Exactly.
AJ: And I try to make a habit of not using anonymous functions. I don’t entirely avoid them but I take a good hard look every time I think about using anonymous functions as to whether or not that’s really a good practice.
YEHUDA: Yeah I think… in Ember, we always almost encourage people to use methods on classes for callbacks and that’s one of the big reasons for it is that methods on classes don’t actually accidentally enclose some scope that’s going to be changed; where anonymous functions… just because, especially when you get deep into multiple anonymous functions, it’s easy to forget. You get these like very, very big scopes like we were saying before like entire files or scopes, right? You get these very, very big scopes and then you can lose track, and you have a common word that you use by accident. JS once was good for this but there's definitely a problem of events that can happen at any time and they can be “global scope”.
AJ: Yeah and so one of the things I found is there's a couple patterns that help reduce that thing; the kind of the waterfall pattern where when one function ends, you call the next and then you call the next so you can keep them in a straight line, you know, if you are looking in your editor all your functions are pretty much in the same indentation level, but they call each other when they are done or you can use some sort of Futures type library where it allows you to do sequential function addition or to join functions together or something like that.
YEHUDA: Yeah all our events have a target action semantic. I think most events are basically like, “Give me a function and then if you want to do something, you want to use [inaudible].bind. In Ember, all the functions… all the events are basically target action to make it really easy to do this pattern. So if you wanna say like, “the callback this, call this.block.” It’s sort of like the equivalent of the binding parameter to all iterators for events.
CHUCK: Right. So one other thing that I want to dig into a little bit is that every… I don’t know if I wanna call them “primitive type,” but every native type has a prototype. Are there any implications to that that people should be aware of other than don’t modify them unless you absolutely have to?
AJ: I would like to bring up one that’s very important, which is there's no such thing as arrays in JavaScript. There's an array syntax, which will create an object that inherits a particular prototype but don’t go thinking that if you put stuff in arrays, it’s going to be more efficient because all its doing is turning zero into a string and then looking it up in the hash table and then returning object at that position.
YEHUDA: So newer JavaScript engines absolutely do smarter things for arrays?
CHUCK: So they optimize it somehow?
YEHUDA: So newer JavaScript engines… so they are not allowed to let you in on the secret, right? Like V8 for instance, absolutely if it sees an array and it sees that you are not doing .a=blah, and maybe even if you are, goes and puts in an array and those lookups. The bigger consequence of that which is totally visible is that in JavaScript, every key can only be a string. So object key can only be a string; which means that in array, the fact that you are looking something up by index 0 is actually looking it up by index string 0.Now again, there's optimizations to make this fast if you don’t happen to use crazy features. But if you go and make an array and look it up by string zero, you will get back the first element.
CHUCK: Huh.
YEHUDA: So basically, semantically what's happening is that the zero gets coursed into a string because when you look up a property on any object, by anything… so you can like do make an object which has like object, object [object object] as a key and then do look something up by any object inside of there, and it will give you value because basically the semantics are whatever you put into the look up gets coursed into a string and that’s what is looked up by. And that semantic is very important for arrays. So you can’t for instance use an array and be like, “I’m going to stash some extra properties on this and use a string version of a number,” because that’s basically going to be the same thing as the number itself. Semantically, it’s exactly the same.
CHUCK: All right cool. My understanding is also if you try and store something in like spot 1,000 and you only have ten things in the array, doesn’t it fill out the array all the way out to 1000 or whatever?
AJ: No, it wouldn’t stringify.
YEHUDA: So conceptually, there is a length of a thousand and there is a lot of undefines in there, but I don’t think modern JavaScript engines are actually putting those undefines in the slot.
AJ: And even the old ones they are not really putting it in there. It’s really treated as an object.
CHUCK: Right.
AJ: It just has different prototypes; like the for each on an array is the same as calling object.keys on the array and then filtering out the length property or any properties you might have added on or any non-numeric properties.
CHUCK: All right. Sounds good.
YEHUDA: Just to be clear, what I said about optimization is purely an internal optimization hack, and AJ is from a semantic perspective. It’s exactly identical to as it was an object. And if they ever let the lie lose and show you that it’s an array, they are doing it wrong. So you can assume that that’s true.
AJ: And I personally have not seen arrays any faster than objects, because I didn’t some naïve things like a year ago where I’m like, “Oh, it’s an array therefore its faster.” And I did things a little bit wonky because I thought, “Well if I can get these objects to iterate quicker or something,” I can’t remember exactly what it was but then it turned I was just wasting my time.
CHUCK: Right. All right. Well at this point we are going to need to get to the picks. We have two people that have kind of a hard stop in about 8 minutes. So, this has been really… it’s clarified qualified a few things for me and hopefully it will qualify some things for our newer JavaScript people. So let’s do the picks and we’ll start with Yehuda.
YEHUDA: I just have one this week and it’s not technical. The show “Once Upon a Time” is really good. It’s in the fantasy genre, but probably more of the fairy tale genre. I think the story is innovative and I've been enjoying watching it. The first time in a long time that I've been like, “Oh, it is Monday, I should check to see if there's a new episode of Once Upon a Time.” For the last multiple years, I've been just like, “Oh I guess I watch this show,” every like couple of months, I'll see if there's new episodes. So I think people who watched Lost felt the same way.
CHUCK: Yeah. It’s written by the same writers who wrote Lost and yeah, my wife and I really been enjoying it.
YEHUDA: Yeah it’s pretty awesome.
CHUCK: All right. Jamison, what are your picks?
JAMISON: Mine is like a story time too. So there's a podcast called “Pseudopod”; it’s like a horror, kind of fantasy podcast. I think its more horror than fantasy. And it comes out every week, every couple weeks and they just have really good stories that are narrated by great narrators. So they have a couple hundred of them in their back log. There's also ones for science fiction and fantasy too. I think “Escapepod” is the Sci-Fi one. I don’t remember the fantasy one. But I've been listening to a lot of Pseudopod when I work out – that’s my only one. My other one is my nose. I pick my nose.
CHUCK: [Laughs] Thanks. Joachim, what are your picks?
JOACHIM: Well, I’m going to be a little bit boring, I’m going to pick eloquentjavascript.net, and it’s basically an online tutorial -modern introduction to programming in JavaScript. And it’s a great read and yeah it’s good. And one more, I’m going to take JSFiddle.net, which is good thing to work with if you guys have problems -- the listeners, you guys wanna work with arrays and objects you can do it on JSFiddle and yeah.
YEHUDA: Yeah totally. JSFiddle was like life-changing for me.
CHUCK: All right, cool.
JAMISON: It’s great for if you are talking on IRC too and someone has a problem and they are like just trying to explain it in words if you can just get them or you yourself just make a JSFiddle. It’s a lot easier to help other people and explain concepts. [Overlapping talks]
YEHUDA: Basic part of the process for submitting bugs for Ember is like, “If you have a bug, please make a JSFiddle and show us the bug.” It’s like so much better than—
CHUCK: So what exactly is it then?
YEHUDA: Basically that’s HTML, CSS and JavaScript into a window and then it shows you the output, so you can be like, “Here is the HTML and JavaScript and here are some libraries and look, it’s broken.”
CHUCK: Okay. Cool. AJ, what are your picks?
AJ: So one is Carrabba’s Italian restaurant. They have a pasta that is about 3 quarters down on the right side of the menu, that it’s got real olives in it, like they are called black olives but they are not the American olives, they are real olive’s flavor and like artichoke and stuff. I can’t recall—
JAMISON: And you put them on your fingers?
AJ: Yeah sure if you want to. And so it’s just like the best I ever had and it was only like $12 if you don’t get it with chicken or shrimp. So that's definitely one pick. Another is I found out recently about this program called “Requiem” and I guess it was black marketed I don’t know if am even allowed to talk about that kind of thing, if the mpa will come get me, but so I like to buy my music and my movies but one thing that has caused me to pirate them more often is when I can only get a version that is DRM and of course I won’t be able to use it on my devices. But I recently found out about Requiem, which is a decrypting tool for iTunes. So if you’ve legally purchased it, it will allow you to decrypt it. If you are trying to like take somebody else’s movie file and decrypt it, it won’t work. So now I’m legally purchasing my movies through iTunes because I have a way to get them DRM-free and high quality.
CHUCK: Nice. All right. So I’m going to try and condense this down as much as I can, but I got a lot of request form people to know what my podcasting set up is. And so I’m going to run through about five or six things really fast and tell you what I got and then I might make some other suggestions about some things that you can get if you are not up for spending this amount of money. So the first that I have, my microphone is a PR-40, it’s Heil PR-40 and it’s a
super nice microphone. I think the retail on it is like $400, but I think you can get it on Amazon for quite a bit less; and its really nice, it’s the microphone that Leo Laporte uses. And anyway, I like the way it makes my voice sound and it tends to kill a lot of the background noise that’s out there. So then that goes into my mixer, my mixer is a Behringer Xenyx 802 and like I said, I’ll have links on the show notes to where you can get all these stuff. But basically that's an 8-channel mixer; works really well and it has everything you need, unless you need more inputs than that. I’m only using 3 or 4 of the channels here; so that’s doing that. And then to bring the computer stuff in, I’m actually using an iMic, which it’s really an inexpensive USB sound card. Anyway the only other things that I use, I have an Edirol R-09HR, which they don’t make anymore, the new model is the Roland R-05 and it’s a digital audio recorder, it has microphones on the top so if you wanna just like take it for a walk and talk in to it, you can do that. It’s a pretty versatile little thing and it collects all of the sound, you can record in wave which is what I do, so it’s totally lostless and then I condense it down with a
compressor in Adobe Audition and so that’s my final pick is the Adobe Audition. Now, if you don’t wanna spend as much, I think Yehuda is using the microphone that that I recommend if you are getting USB and that is the Blue Snowball Mic.
YEHUDA: I hear it’s not working too well though.
CHUCK: Well, the Heil PR-40 is a dynamic mic, which means that you pretty much have to be right on top of it in order for it to pick you up. The Blue Snowball is actually a condenser mic, and so it will pick up more of the ambient noise. But if you want a rather inexpensive or relatively inexpensive USB mic, then that one I hear works really well and you actually sound pretty good on it. So the other if you want a dynamic mic like the Heil PR-40, you can get the Shure SM68 and that’s about $99 and it’s an XLR mic, so it doesn’t plug in to the USB port but you can get a USB XLR converter and plug it in to your computer anyway. So that’s pretty much it. That’s what I use; and hopefully if you are looking at starting a podcast and you wanna spring for that stuff, then you can go ahead and get some of that stuff.
AJ: And maybe for the links we can just have a couple of different links to Amazon or whatever with these different mics.
CHUCK: Yeah I'll have it all in the show notes so you can look at them and see which one you wanna get. But anyway, that’s all I've got here. One other thing that I wanna point out, I have moved all of my uservoice forums -- which is where we take all of our suggestions -- over under one account. So rather than going to jsjabber.uservoice.com, if you come to the website and you click on “pick a topic” it will open up a dialog where you can suggest ideas of things you want us to talk about. It will also take you to the website if you want to where you can vote up ideas that you wanna hear. And that should really help us kind of get an idea what you wanna hear about. Other than that we are in iTunes, we got a lot of traffic from our last episode and that got us into the “New and Noteworthy” under technology in iTunes, which is actually really hard to do. So I really appreciate all of the people who were talking about it. And if you have any feedback for us, then we definitely wanna hear it.
JAMISON: Do you wanna mention what we are doing next week, Chuck? Or is that not done yet?
CHUCK: I don’t know, is it nailed down Yehuda?
YEHUDA: I don’t know. I’m in the process. I hope we get Paul Irish on next week.
CHUCK: Okay.
YEHUDA: He had said yes and I’m just working on nailing down the exact timing.
CHUCK: Okay so we are talking to Paul Irish about coming on to the show and hopefully we will either have him next week or we will know more next week.
YEHUDA: I’m hoping that we get to talk to him about the Chrome Developer Tools because I think that those things are vastly underutilized. Often people come and watch me in my daily workflow and they are like, “Oh my god, I didn’t know all these things,” and he knows more things than me.
CHUCK: Yeah. I would love to get into that because I use them and I know I don’t know enough what's there.
YEHUDA: All right.
CHUCK: So we will catch you all next week. And thank you for listening!