Predicts Script Loader Tech will see a renissance
-
HTTP 2.0
- Exists in all the browsers being used
- HTTP 2.0 -> everything we learned about optimizing page load performance and combining it all into one file turns out the worst possible way in HTTP 2.0
- Persistent Socket Protocol. Downloads everything in Parallel -> want as many small chunks as possible.
- Might switch back to script loading as this becomes more mainstream.
-
GRIPS (Templating Engine)
- 2 extremes
- 1 -> Very little logic (ie. Mustache [dont want business logic in templates])
- In practice…we need to massage data in controllers because the expressive templating doesnt exist
- Really need to understand view to write controller and vice versa
2 - I do need some logic -> lets do a whole programming language.
- ie. PHP / Ruby - leads to a lot of // todo fix comment - now you have business logic leaked into template
Browser Versions Are Dead Talk - Worth Watching browserversionsaredead.com - Worth Talking about on your team
- Lies and misconceptions have forced ideas and dictate how the platform should work, not how it actually works. Professionals should be asking more difficult questions.
1st Lies -> Browser Version Matters - We should be talking about what features we require and support. Eg. We shouldnt rely on production feature, we should test for it.
2nd Lies -> Site or application works/feels same on all platforms. Its a ludicrous concept in any other software discipline. Different features get turned on/off. Eg. File upload on mobile. Simply hide feature.
Questions professionals really should be pushing back and living 10 years in the past.
- Javascript Patterns
- Youdontknowjs.com
- developer.mozilla.org/en-us/docs/Javscript
MDN Open public wiki Goes unknown that its public
- github.com/rwldrn/idiomatic.js
- If you dont have style guide -> implement this.
- Some point look in the ECMAScript Specification to confirm if something explained is correct.
- You can also check out where the language is going
You can write JS for a long time and not fully understand how things actually work.
Focus is practical takeaways
Coverage Scope
- Nested Scope
- Hoisting
- this (potentially strange in discussion of scope)
- Closure
You can understand JS and Node at different levels.
- Whose doing the looking?
1st Misconception
-> Javascript is stated thats its interpreted
-> Javascript is compiled.
-
Not quite the same as Java or C++
-
We dont distribute the binary compiled form, like C++ or Java with byte code to JVM
-
Compiled every single time its run
-
Compiled Vs. interpreted
- Bash is interpreted
- When running line 3 -> doesn't know line 4
- Compiler does initial pass through code then looks at line 4
- Compilier will look for blocks of scope
- At the moment, smallest atomic unit is function
-
Finding declarations of variables and declarations, thats teh important compiler step
-
Rather than var foo = “bar”; as 1 operation
-
There is actually two steps ->
-
- Declaration var foo;
- Initialization -> foo = ‘bar'
- Happen at totally different times with different mechanisms in the engine
- Compiler does pass looking for variable and function declarations
- JIT (just in time) -> function bar not compiled skipped over and compiled when necessary
- Hot Swap Function compilation
- Because of all differences of types. Compiler makes best guess on how you will use function
- Many engines make guess… then let function run a couple dozen times monitor guess. If guess was wrong hot swap in new function
- Recursively descend into function
- execution phase
- var doesnt exist in
var foo = ‘bar’
after initialization
LHS -> Left Hand Side RHS…
Of an assignment in this case an = operator
var foo = ‘bar' foo is an LHS reference ‘bar’ is the RHS
the terms come from the initial looking at the equals. Assignments can occur in other cases without a visible LHS/RHS
LHS is the target RHS is the source
LHS ref to variable, where does variable exist? We ask the scope manager. Hey global scope I have LHS ref for foo, scope manager responds, yes happened in initialization.
If RHS was variable. We’d do a lookup etc.
let’s execute function bar() - Execute line 4 -> have you seen scope of bar I have LHS ref for foo, have you heard? - Created refrence
lexical scoping can lead to global variables non strict mode compiler goes and creates variable
if not declared its undeclared -> We cant fulfill requirement to find a LHS ref in any scopes we have access to.
undeclared !== undefined
undeclared is when no present variable is declared in scope
in undefined he was defined but he has a special value called undefined, more akin to uninitialized
- Hey global scope I have a declaration for foo
- Hey global scope I have a function called bar. I’d like to register it in the global scope
- now we compile scope of bar
- Hi scope of bar I’d like to
- scope of bar I have a declaration for a function baz
- Hey scope of baz I have a declaration for an identifier called foo.
function declaration or function expression
- whether or not the function keyword is first word in statement. Not first in line. first in statement
Line 1 function bar() not firstthing in statmeent so its a function expressions.
-
function expressions with names bar 1-9 is scoped to itself.
-
Named versus unnamed. Anon function expressions 3 major things occur. (function expressions are great) anonymous function expression are not so great.
- If bar did not exist. We have no way to refer to ourself from within. No recusion now etc. With named bar we can. (THIS keyword is not a reference to itself). Name is self referential.
- Lots of function errors in minified code. anonymous functions dont play well in debugging. really difficult when minified.
- Self documentation. You give it a nice descriptive name and it makes the code a littl more understandable.
As of ES3 with try catch -> catch is blocked scope.
Lexical Scope Model -> predominant scope model Dynamic Scope -> bash script for example
Lexical scope -> Compile time scope.
What dynamic scope looks like? Lexical -> like looking at first floor of building. Look higher Look higher, etc.
Nested scope bubbles. Layers of bubbles for lexical scope. Nested strictly within each other.
-
way to cheat lexical scope model eval
- evaluates string
When line 5 executed. we pass in variable declaration. We pretend line existed at compile time. Adds new declaration of foo at runtime. When you cheat these optimizations in the JS engine it has to assume and cant optimize. even if not modifying, it disables some optimizations.
As of strict mode, variable inside of eval will make whole new scope inside and allows engine to continue to do optimizations.
strict mode code will make it run faster.
"never use eval statement"
-
Some argue against this. If you have to ask whether or not its ok to use eval. answer is no. If you ever ask about eval. No
-
even worse way to cheat lexical scope.
-
avoid settimeout with string syntax for this similar reason
with keyword
shorthand the obj
problems with with is line 13
d = 3 ? actually the with is lexically scoped. Hey scope of with statement obj do you have ref d.
Hey global scope I have LHS ref… I have just created it for you.
with is more evil than eval. Whereas eval modifies existing scope. with creates new scope. with keyword disables many optimizations. with keyword is disallowed in strict mode.
why the parens? Want to hide 5-6 in scope. we can create scope.
you could do this in line 3 with named function but you pollute global scope.
3-8 we wrap in parens to create a function expression. It can be anon or named. var foo is now attached to current scope.
This is very popular pattern.
Immediately Invoked Function Expression IIFE
Most common solution. You can wrap IIFE and make all functions IIFE. Hide 99 that didn't need to be public.
we can pass values to IIFE
pass in window object but can call it global. Can give alias to global object.
As of ES6 we have block scope via let
var is cousin to let. It will implicitly hijack scope and add.
let keyword is like var. it attaches it to the block rather than the function
if it finds let it attaches to block
why var in for ? i is only intended for for loop. let me put it directly on the for loop.
Line 2 -> attach bar to baz in scope of if statement hijack implicitly.
Basically any 2 pairs of curly braces. Allows varaible declarations as close as possible to anything. variable reuse, etc.
- var available to whole function let to block scope.
Problems exist with let.
let does not hoist.
- If you didnt declare let till the middle of a block it wouldnt exist prior.
- Creates extra mental task for refactoring. you cant just arbitrarily create new blocks with let.
- When you talk about implicit block scoping.
let statements
explicit block for let only within that block. Preferred form.
This syntax does not exist in ES6.
You can create blocks
Can we reformat code? coffeescript transpiles. Can we create transpiler. let-er
looks for entire codebase and transpiles any let blocks into something else and leaves everything else alone. Lets you write let blocks no standard. How is this accomplished?
If dynamic scoping existed we'd look to call stack instead of lexical scoping.
If you had only ever done lexical it wouldn't seem so strange. Lexical is 99.9% of all languages. Key comparison in dynamic scope is a run time decision as opposed to author time.
-
What tpye of scoping rules does JS have? Exceptions? - JS has lexical scoping - with and eval cheat lkexical
-
What are dif ways you can create a new scope? - functions - curly braces with let
-
Undeclared vs undefined? - undefined is a value - undeclared hasnt been declared yet - if it was declared but no value it is undefined otherwise refernece errror
Hoisting is a mental construct to explain JS behaviours It's compiled prior to execution
a; b;
actually var a; var b;
declarations of functions and variables are "hoisted to the top"
every function while executing has ref to own current execution context called this
this keyword is unique to JS. The four rules defenceable from the spec.
Go to the call site and look at these 4 rules
- Implicit Binding Rule
- (6,7) have refs to same foo function. In JS everything is ref to object or function. 2 dif refs to foo function. On 10 o2.foo() when call site looks like object prop ref to ref. that object at call site becomes this binding so in this case this == o2
- Default Binding Rule Applies
-
- when just function gets called. This applies to IIFE’s
- If you are in strict default this == to undefined / if not strict applies this == global binding. Strict is scope applied.
-
No such thing as Javascript classes new keyword has nothing to do with instantiating classes
new in front of anything function call and acts as constructor call
4 Things Occur when new keyword occurs
- Brand new object is created out of thin air
- ( *object gets linked to another object)
- brand new poof object gets bound to this for purposes of function call
- implicitly bind object poof brand new object gets returned
any old function with new and you have hijacked this call as a constructor call. It will also now do those 4 things.
4 Things of Post it Note and never forget this binding
- Was the function called with
new
? (hijacks this) - Was it called with
call
orapply
specifiying an expkicit this - Was the function called via containing/owning object (context)
- DEFAULT: global object (except strict mode)
- Closures come from lambda calculus.
- Closure is when a function remembers its lexical scope even when the function is executed outsie that lexical scope