6 ms·
It is not clear, if you want to learn programming, or you alerady know it, and want to learn a new language. It takes years to become good at programming. Once
by IvanK_net 7y ago
It is not clear, if you want to learn programming, or you alerady know it, and want to learn a new language.
It takes years to become good at programming. Once you know programming, it usually takes hours to learn a new (procedural) programming language.
- pansa2 7y ago> it usually takes hours to learn a new (procedural) programming language. Really? I feel like I’ve spent longer than that just trying to get my head around JavaScript’s prototypal inheritance. I’m even more confused by Promises.
- jimmyspice 7y agoPrototypical inheritance is not something I really understand in too much detail (and maybe I was late to the game, since I've never really felt I missed anything). Now js has 'classes' which I think are sugar over proto, can't remember. You can think of a prototype as 'cloning' an object (but not quite), distinct from classes in OOP, which are typically created afresh, i.e. no entanglement occurs between instance 1 and 2 of the same class (unless of course explicitly specified in a constructor). If I have `var a = {one: 1, two: 2}`, I can use that as a 'live template' to stamp out other 'instances' that prototypically inherit from that ancestor. Any attribute lookups that are not specified directly on an object created with a prototype recursively look up the prototype ancestry chain until it is found. So if c -> b -> a (where a -> b means a prototypically inherits from b), looking up a property on c will try to look for the property on c first, failing that b, then a. If nothing is found, `undefined` is returned. Let's open our inspector and have a play: ``` var a = {one: 1, two: 2}; var b = Object.create(a); // create b, based on prototype a var c = Object.create(b); console.log(c.one) // 1, how, when this wasn't even defined! We looked up the p. chain until we found it b.three = 3; console.log(a.three) // undefined, a's only prototype is Object console.log(c.three) // 3, wow, c knew about something that happened to b! This is different from OOP. 'instances' share data defined at runtime. ```
- jimmyspice 7y agoAnd now for promises. Why promises? Before promises, js code often used an error first callback strategy to communicate when an asynchronous process has finished. It's important to write blocking code as little as possible, since your computer can and should spend time doing 'compute' stuff, whilst waiting for a resource, such as a network request or disk etc.. which can take an unbounded amount of time. Back to how callbacks look: ``` function myExpensiveSuccessfulFn(cbFn) { setTimeout(() => { cbFn(null, 'success'); // pretend we did something useful }, 60 * 1000) // time waste for a minute } function myExpensiveFailingFn(cbFn) { setTimeout(() => { cbFn('oh no'); // pretend we tried to do something useful }, 60 * 1000) // time waste for a minute } function myCallback(err, data) { console.log(`err: ${err}`); console.log(`data: ${data}`); } myExpensiveSuccessfulFn(myCallback); // after 1 minute: err: null, data: 'success' myExpensiveFailingFn(myCallback); // after 1 minute: err: 'oh no', data: undefined ``` Awesome. We can wait for some result and be notified whenever it finishes. Have a play in your inspector as before. Immediately after calling our expensive functions, we can execute code straightaway (try logging anything immediately after calling an expensive function) Now callbacks start to get unwieldy when those same callbacks also want to do things that require something else asynchronously. There are better examples online, but I'll write something with anonymous functions to give you an idea: ``` function addSomethingSoon(a, b, cbFn) { // in 5 seconds, return the sum of two numbers setTimeout(() => { cbFn(a + b)// no err first style in this example }, 5 * 1000); } // now let's get the sum of four numbers: addSomethingSoon(1, 2, (result1) => { addSomethingSoon(result1, 3, (result2) => { addSomethingSoon(result2, 4, (finalResult) => { console.log(`1+2+3+4=${finalResult}`); }); }); }); ``` Only 3 operations, and things are getting quite ugly. Contrived, but let's see how we can do better. Enter the promise. A promise is a 'promise' of a future result. It's like if you went to a fast food restaurant, made an order and got a ticket in return. Once you are given a ticket, they'll call out your number and give you your food, since you are holding the ticket (the promise of food in the future). Let's have a play: ``` function getFoodIn5(menuItem) { // don't worry about the syntax here. You'll likely not be creating promises with 'new' often. You'll likely get given them from a library, say a http call or similar. return new Promise((onComplete) => { setTimeout(() => { onComplete(`fresh ${menuItem}`); }, 5 * 1000) }); } const promiseOfFood = getFoodIn5('burger'); console.log(promiseOfFood) // depends on your browser, nothing very useful, and definitely NOT our burger.... promiseOfFood.then((food) => { console.log(food); // fresh burger, yes, it tastes so good! }); ``` So we got our burger, pretty fast too. Unfortunately they just hired a few trainees: ``` function burntFoodIn5(menuItem) { // don't worry about the syntax here. You'll likely not be creating promises with 'new' often. You'll likely get given them from a library, say a http call or similar. return new Promise((onComplete, onError) => { setTimeout(() => { onError(`burnt ${menuItem}`); }, 5 * 1000) }); } const promiseOfFood = burntFoodIn5('burger'); console.log(promiseOfFood); promiseOfFood.then((food) => { console.log(food); // ... :( nothing }).catch((mistake) => { console.log(mistake) // burnt burger, you don't want to eat this. }); ``` that is promises in a nutshell. doesn't seem very useful now, but they are composable: ``` function add2(a, b) { // return a promise NOW, that will give us the sum of two numbers in 5 return new Promise((onComplete) => { setTimeout(() => { add2(a + b) }, 5 * 1000); }); } add2(1, 2).then((result1) => { return add2(result1, 3); }).then((result2) => { return add2(result2, 4); }).then((finalResult) => { console.log(`1+2+3+4=${finalResult}`); }); ``` Now we don't have the masses of indentation of callback hell. Note that will take the same amount of time to run as the callback example. Promises don't make anything faster, they just help us to write synchronous looking code. The next step to bring us back to imperative looking code is async/await. But that's for another time. Finally, the best way to learn is to do. Get a hold of VSCode, and get the Quokka extension. You can then `Ctrl+Shift+P` or `Cmd+Shift+P` and `Quokka: new javascript file`, and get a real time repl where you can mess around and log to your hearts content to get a feel of things.