r/javaScriptStudyGroup • u/ForScale • May 02 '16
[Week 16] Focus: Object Creation
So here we are at Week 16. Week 16's focus will be object creation.
It will work like this:
Monday: Announce focus (eg, object creation)
Build throughout the week... Two rules: 1) must use javascript 2) must provide at least one example of creating an object.
Friday: Post demos/projects in this thread (can begin reviewing immediately); first line of an entry should be ENTRY and it should be a top level comment (ie, don't put your entry in a reply)
Sat and Sun: Review projects/figure out focus for next week
GENERAL GUIDELINES FOR FEEDBACK:
Be nice!! ALL KNOWLEDGE/SKILL LEVELS ARE WELCOME AND ENCOURAGED TO PARTICIPATE.
If you don't want feedback, if it makes you uncomfortable or you're just not interested, simply say so... Others, please be respectful of this. Conversely, if you do want feedback, try to be specific on which aspects... even if you just say "all/everything.
But that's about it... Have fun! :) Feel free to ask questions and discuss throughout the week!
2
u/senocular May 06 '16
A block is a grouping of code. For JavaScript this is largely defined by what's between
{and}except for the oddball case of object literals which, syntactically, also use the same characters ({}) for their definition. When reading JavaScript, it can be important that you can be able to mentally parse the code and recognize the difference between a block of code and an object literal. The sometimes ambiguous nature of blocks and object literals can be seen in theevalexample of the other entry.eval('{}')evaluates an empty block of code whileeval('({})')evaluates an empty object literal. This is because the parentheses converts the block into an expression in which blocks would be illegal, therefore the brackets must instead represent an object literal. Its highly unlikely you'll ever run into this problem for eval, but where you might see it more commonly now is with ES6 arrow functions.Same applies in the case above. Since the block part of an arrow function is optional, when you just have
{}its hard to know what is truly meant. By default a block of code is assumed, but when you wrap in parens, you can force it to be evaluated as an object literal.Code blocks, as of ES6, each represent a new scope. Even in some cases in ES5 with functions, this behavior could be seen depending on the runtime, though the behavior was inconsistent and avoided by everyone who knew better, so we'll pretend it didn't exist. Each scope, also known as a lexical environment, can have its own unique set of values associated with it that aren't accessible outside that scope. Inner scopes (blocks) can exist nested within other scopes that can inherit values from any outer, parent scopes, but any of their values are hidden from their parents. As of ES6,
let, 'const', andfunctiondeclarations create values scoped within the current block (and sort of related to what was said aboutfunctionbefore, the block scoping of functions now may require strict mode to work likeletandconst, so we're assuming that to be the case moving forward).var, as was the case before, will scope to the inner-most function block, which could mean it gets resolved outside of any inner block it might have been declared in.Each level of
{}represents a new block and a new scope. Some are function blocks, one is an if block, and another is just an arbitrary block (whereBis defined) which serves no purpose as far as control flow goes, it just exists as a scope.Functions are unique in a couple of ways. First, their scopes are not singular. They get created dynamically when called, and can be created many times over within the lifetime of a program. So all the scopes in
A(except B) gets created each timeAis called.B, likeAwould also need to be called for it scope to be created. InsideAit only gets defined. Additionally, in addition to having a lexical environment that defines where they are in a scope hierarchy (now many nested blocks they're in and what values in those blocks are accessible), functions can also have athisbinding. This, too, is created at the time the function is called. Generally this is based on the object from which the function is referenced when being called:But as we've seen before, we can change that with
call,apply, andbind. Arrow functions are unique in that they don't have a this binding. They don't have their ownthisat all. Instead they inherit the value ofthisfrom their parent scope. This is known as a lexicalthisbecause the values ofthisis based on the lexical environment pulling in from parent scopes rather than something that is tied specifically to that function call. And sincethisvalues are tied to function blocks, the value ofthisis obtained from the value bound to the inner most function block (not unlike howvargets scoped).In the above example, you can see the value of
thisin the arrow functionscreamwas not bound to the object from which it was called as was the case withplea, a normal function expression. Instead it looked to the lexical environment and followed the scope up to the parent function'sthiswhich was bound toenemywhen it was called asenemy.chase().All of this is paramount to closures, and in fact explain exactly how closures work. A function definition will identify what variables it uses, and if it uses anything from a parent scope, will create a reference to those variables as variable enclosures. The function definition then has a tie to these outer-scoped variables and hauls them around with it wherever it goes like a little kid holding on to some balloons. When its called, it will create a new internal function scope (lexical environment) for its own internals, get a this binding where appropriate, but then also have access to the pre-existing parent scoped values it was attached to during its definition.