Node.js:
Unfortunately, Node.js doesn’t support for fascinating import and export in ES6 currently from this and this
AWESOME article – appreciate the words: “I am not content, nor should you be, at stopping once something just works, and not really knowing why.” from this
Concepts review (in JavaScript, but it’s more suitable to create ‘em here):
- Statement vs Expression
- Variable vs Value
- Expression statement vs Call expression statement
- Intepreter vs Compiler (the stunning part)
- Primitive values
- Loose equal vs Strict equal
- Comments (One of rule of thumbs: “Comments should explain why, not what.”)
- Static typing (type enforcement) vs Weak typing
- Scope (Lexical scope) – many thanks to this post
// Oops, we dont have 'use strict' here ... function foo() { qoo(); function qoo() { b = 123; } } function zoo() { coo(); function coo() { console.log(b); } } foo(); // VS zoo() then foo() zoo();
// Consider following code from https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch2.md#eval // Well, actually, if not mentioned, code blocks in the following come from You-Dont-Know-JS function foo(str, a) { eval(str); // We cheat that we author some code like 'var b = 3;' here console.log(a, b, gg); // Just a small modification here } var b = 2; var gg = 12; foo("var b = 3; var gg = 123;", 1); // 1 3 123
// This is soqq function thats gonna recursively add 1 till 10 var a = 1; (function soqq() { if (a < 10 ) { a += 1; soqq(); } else { console.log(a); } })(); soqq(); // Should throw Ref err -- soqq is not defined in this (this case, global) scope
// Compare the following err stack of each ill-coded codes (A, B, C) // A (function soqq() { if (a < 10 ) { a += 1; soqq(); } else { console.log(a); } })(); // B setTimeout( function(){ console.log(a, "I waited 1 second!"); }, 1000 ); // C setTimeout( function waitAMinQuestionMark(){ console.log(a, "I waited 1 second!"); }, 1000 );
var a = 2; var imSoGlobal = { a: a, }; (function IIFE(global){ var a = 3; console.log(a); // 3 console.log(global.a); // 2 })(imSoGlobal); console.log(a); // 2
- Built-in type-methods
- Lexicolgraphical order
- Auto-global variable declaration
foo(); // This 'foo' works cauz of 'hoisting' effect function foo() { bar(); function bar() { // VS 'use strict' a = 1; // VS var/let/const a = 1 } } console.log('Im sorry that you got an a like:', a); // This a is accessible cauz 'auto-global'
- Block scoped (with, try/catch, let, const)
- Immediately Invoked Functions Expressions (IIFEs)
- Closure VS Class
function biggerThan(x) { function isBiggerThan(y) { return y > x; } return isBiggerThan; } const isBiggerThan10 = biggerThan(10); console.log(isBiggerThan10(9)); // Should be false
- arguments
- this is (quoted from the page) “When a function is invoked, an activation record, otherwise known as an execution context, is created. This record contains information about where the function was called from (the call-stack), how the function was invoked, what parameters were passed, etc. One of the properties of this record is the this reference which will be used for the duration of that function’s execution. … this is actually a binding that is made when a function is invoked, and what it references is determined entirely by the call-site where the function is called.”
- Call-site
// Whats this? function foo() { console.log( this.a ); } var obj2 = { a: 42, foo: foo }; var obj1 = { a: 2, obj2: obj2 }; obj1.obj2.foo(); // 42
// OK ... Which is T? "bar references to obj referencing to foo" OR "bar references to foo, thats it" function foo() { console.log( this.a ); } var obj = { a: 2, foo: foo }; var bar = obj.foo; // function reference/alias! var a = "oops, global"; // `a` also property on global object bar(); // "oops, global"
// We simply wanna build a helper (which is 'bind' here) that can: // - bind a targeting fn with another designated obj // And also note this: 'Since hard binding is such a common pattern, it's provided with a built-in utility as of ES5: Function.prototype.bind' -- quoted from https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md#hard-binding function foo(something) { console.log( this.a, something ); return this.a + something; } // simple `bind` helper function bind(fn, obj) { return function() { return fn.apply( obj, arguments ); }; } var obj = { a: 2 }; var bar = bind( foo, obj ); var b = bar( 3 ); // 2 3 console.log( b ); // 5
- Implicit Binding VS Explicit Binding VS ‘New’ Binding (And ordery?)
- prototype
const foo = { a: 42, }; // create `bar` and (prototype-)link it to `foo` var bar = Object.create(foo); console.log('Here "bar" right after prototype-linking', bar); var barbara = foo; bar.b = 'hello world'; // VS barbara.b = 'hello world' console.log('Here "bar" right after assigning "b" property', bar); console.log('Here "barbara"', barbara, 'should be the same as "foo"', foo); console.log('This is bar, I can fall back to foo.a, which is (processing ...) bar.a: ', bar.a); bar.a = 123; console.log('This is foo after assignment of a in bar', foo); console.log('This is bar after assignment of a in me', bar); // A feeling of inheritance
foo(); function foo() { console.log( a ); // undefined var a = 2; // VS a = 2; Do you see the difference? Hint: Compiler + Declaration Hoisting + RHS }
foo(); // TypeError ------\ bar(); // ReferenceError -/ You see the difference? Wt if these two lines are put after function expression 'var foo = ...' block? var foo = function bar() { // ... };
// Who's first hoisted? Who's been ignored? // Read (https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch4.md#functions-first) if confused foo(); // 1 var foo; function foo() { console.log( 1 ); } foo = function() { console.log( 2 ); };
// Expectation of log? console.log('top', i); var i = 0; console.log('after assignment', i); for (var i = 1; i <= 5; i++) { console.log('looping --', i); setTimeout(() => { // Es-lint complains that, and I quote: Don't make functions within a loop console.log('soTimeout', i); }, 0); } i = 100; console.log('bot', i);
// VS for (let i = 0; ...) <-- is 'i' gonna be declared for each iteration? // In case you missed this: https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch3.md#let-loops for (var i=1; i<=5; i++) { let j = i; // yay, block-scope for closure! setTimeout( function timer(){ console.log( j ); }, j*1000 ); }
- Closure
// The reason why the following will work -- closure var qq = 1000; // This qq shouldn't be used in the following code due to the rule of lexical-scope searching rule function foo() { var qq = 0; function addBy1() { qq += 1; } function minusBy1() { qq -= 1; } function qqlog() { console.log('yDoUcallMe -- from qq', qq); } return { // vvv Has the lexical scope closure over inner scope's of foo addBy1: addBy1, minusBy1: minusBy1, qqlog: qqlog, }; } var baibaodai = foo(); // GC of foo never happens here baibaodai.addBy1(); baibaodai.addBy1(); baibaodai.qqlog(); baibaodai.minusBy1(); baibaodai.qqlog(); // GC of foo never happens before here, too
- Lexical Scope (JavaScript) VS Dynamic Scope (Bash scripting)
- Non-javascript
- Principle of Least Privilege (Least Exposure)
- Refactoring
- (Browser’s built-in) Debugger
- Construction Calls of Functions VS Constructor Functions (Which one truly exists in JavaScript? Herher …)
Takeaways – say when you’re tracing codes and get pretty confused with some identifier’s val, you should consider:
- Lexical scope that’s defined in code-editing phase, which should be
- Q0: Is the (global) scope covered by ‘use strict’?
- Yes – No need to consider auto-global-declaration from LHS look-up,
- Q1: Is there any function calls, such as eval and with(highly deprecated), that could invoke dynamic code generations (thus change lexical scope at runtime)?
- Consider hoisting, Q0, and Q1, where was the identifier born?
- Is the current function function expression or function declaration?
- Is there any weird repetitive declaration of the current token name?
- Yes – remember that its more natural that the compiler take the latest declaration of function over whatever previous function declaration over whatever variable declaration
- Is there any function calls in closure status that you are not aware of?
Takeaways – say when you’re adding new features to the current project:
- How many APIs should be open? Consider minimum privilledge exposure …
- Should the current function involked multiple times?
- No – then try IIFE (be able to not even pollute its enclosing scope) with function name assigned (useful in debugging)
- Make explicit blocks (parentheses) and consider the code’s refactory capability
Takeaways – other rules you’d be aware of:
- Repetitive declarations through var’s gonna be ommitted by compiler, whereas let declaration after var on the same token name will lead to (only tested on Nodejs) SyntaxError – that is, not even pass the compiler.
- (Common) Error sequence: SyntaxError (happens when your code did something illegal in the sense of syntax, e.g. qq a = 1; the corresponding result is that your code doesnt even pass compiler) -> ReferenceError (happens when engines try to do a RHS look-up indicated by the corresponding machine code but there’s no targeting identifier declared in any scope through lexical scope searching rule) -> TypeError (happens when the engine wants to use some property that doesnt belong to current identifier)
- Global variables (i.e. identifiers declared at global scope) are exactly the properties of the global object window
- The reason why we reject with and eval is thak they make lower readibility of codes and refuse the code optimization in compiler phase
- The lexical scope of an identifier (variable or function) only maters in where its been declared.
- Lexical Scope can be divided into function scope (scope created by function) and block scope (let some identifier stick to current block; catch constraint the error; we dont care about with, right?)
- Least exposure of your APIs – collisions avoidance && module management
- Named functions benefit in debugging && recursion calls
- Explicit brackets/parentheses for blocking imroves refactory capability and gc
- View let’s usage in for loop as repetitive assignment to the identifier created by let – thus multiple individual scopes is created by each iteration
- Closure is a status/ability that a function that will follow the (enclosing) lexical scope when it’s declared (even if it’s executed outside of that scope).
OS:
How may Heroku help me/others as Paas?
Murmur:
- Atwood’s Law: Any application that can be written in JavaScript, will eventually be written in JavaScript.
- An interesting comment from this, and I just quote here, “Serious developers in other languages expect to put in the effort to learn most or all of the language(s) they primarily write in, but JS developers seem to stand out from the crowd in the sense of typically not learning very much of the language.”
- Gosh, the articles here really literally clarify most of my questions (mostly happen in some weird conditions though) – I thirst for magic!
- And if my promise is unreturned. Before the day is over I will depart – so insightful from James Blunt!
- Closures happen as a result of writing code that relies on lexical scope. They just happen.
Songs:
- Into the dark
- The world as I see it – Jason mraz – to capture the messages from compiler, engine, function calls, and the previous me