You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Eric Elliott advocates prototypal inheritance as one of the two pillars of JavaScript (the other one is functional programming).
In the article How to Escape the 7th Circle of Hell he addressed that classical inheritance suffers from the Gorilla/Banana problem ("You wanted a banana but what you got was a gorilla holding the banana and the entire jungle."), the too-tight coupling between parent and child, and your ending up building new classes for subtle differences.
In class inheritance, instances inherit from a blueprint (the class), and create sub-class relationships. In other words, you can’t use the class like you would use an instance. You can’t invoke instance methods on a class definition itself. You must first create an instance and then invoke methods on that instance.
In prototypal inheritance, instances inherit from other instances. Using delegate prototypes (setting the prototype of one instance to refer to an examplar object), it’s literally Objects Linking to Other Objects, or OLOO, as Kyle Simpson calls it. Using concatenative inheritance, you just copy properties from an exemplar object to a new instance.
As a quote from Design Patterns: Elements of Reusable Object-Oriented Software says, "favor object composition (assembling smaller functionalities, thinking can-do, has-a, or uses-a relationships) over class inheritance (is-a)".
Three Different Kinds Of Prototypal OO
There are three kinds of prototypal OO according to Eric and he built stampit (factory) as a sugar & abstraction on top of prototype. They are implemented as a factory - a function that creates and returns objects (but NOT a constructor).
A delegate prototype is an object that serves as a base for another object. Method delegation is a fantastic way to preserve memory resources, because you only need one copy of each method to be shared by all instances.
varproto={hello: function(){return'Hello, my name is '+this.name}}vargeorge=Object.create(proto)// the factory creates an instancegeorge.name='George'// JS has dynamic object extensiongeorge.hello()// 'Hello, my name is George'
Object.create() - creates a new object with the specified prototype object and properties.
2. Cloning / Concatenative Inheritance / Mixins - States
Prototype cloning copy the properties from one object to another WITHOUT retaining a reference between the two objects.
varsomeone=Object.create(proto)vargeorge=Object.assign(someone,{name: 'George'})george.hello()// 'Hello, my name is George'
Object.assign() - [ES6] copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.
Closure prototypes are functions that can be run against a target object in order to extend it. It’s a function prototype. Think of it as an alternative to a constructor or init function.
Concatenative inheritance is the easiest way to achieve JavaScript’s simplified form of object composition (this is what most people mean by "mixins" in JavaScript).
The process of inheriting features directly from one object to another by copying the source objects properties. In JavaScript, source prototypes are commonly referred to as mixins. Since ES6, this feature has a convenience utility in JavaScript called Object.assign(). Prior to ES6, this was commonly done with Underscore/Lodash’s .extend()jQuery’s $.extend(), and so on ...
JavaScript has function-level scope, which is radically different from the C family. Blocks, such as if statements, do not create a new scope. Only functions do.
On runtime, all var and FunctionDeclarationsfunction foo() {...} are moved by the interpreter to the beginning of each function (its scope) - this is known as Hoisting.
So the good practise is:
functionfoo(a,b,c){varx=1// declare all the vars altogether on the first linevarbarvarbaz="something"}
if you want your module to be of a specific object type, use module.exports; if you want your module to be a typical module instance, use exports.
-- ref
exports is the recommended object unless you are planning to change the object type of your module from the traditional 'module instance' to something else.
As long are you don't overwrite the module.exports object with an assignment operation, anything attached to module.exports and exports will be available in the 'required' module.
If you want the root of your module's export to be a function (such as a constructor) or if you want to export a complete object in one assignment instead of building it one property at a time, assign it to module.exports instead of exports. -- nodejs api
Node.js uses multiple threading strategies. The libuv thread pool size equals to the number of logical CPU cores.
Node.js has many different queues. When the thread pool exceeds, each additional IO tasks is appended to the queue (FiFO).
A slow Node.js app rarely has something to do with thread pool size.
setTimeout( {...}, 0) trick moves the slow code to the end of the message queue, allows other code to execute before our slow code blocks everything else, thus speed up synchronous code execution.
As a developer just work with the Event Loop which is single threaded and non-blocking. It's Node's responsibility to delegate the blocking tasks to worker threads.
Advanced JavaScript
bind(), apply() & call()
It's all about this.
All three methods can set this value for a function.
bind()
fun.bind(thisArg[, arg1[, arg2[, ...]]])
The key of
bind()
is that it creates a new function for later calls, or no immediate invocation.window.setTimeout()
apply() & call()
These two methods call a function with a given this value and arguments.
Prototypal Inheritance
Eric Elliott advocates prototypal inheritance as one of the two pillars of JavaScript (the other one is functional programming).
In the article How to Escape the 7th Circle of Hell he addressed that classical inheritance suffers from the Gorilla/Banana problem ("You wanted a banana but what you got was a gorilla holding the banana and the entire jungle."), the too-tight coupling between parent and child, and your ending up building new classes for subtle differences.
As a quote from Design Patterns: Elements of Reusable Object-Oriented Software says, "favor object composition (assembling smaller functionalities, thinking can-do, has-a, or uses-a relationships) over class inheritance (is-a)".
Three Different Kinds Of Prototypal OO
There are three kinds of prototypal OO according to Eric and he built stampit (factory) as a sugar & abstraction on top of prototype. They are implemented as a factory - a function that creates and returns objects (but NOT a constructor).
1. Delegation / Differential Inheritance - Methods
A delegate prototype is an object that serves as a base for another object. Method delegation is a fantastic way to preserve memory resources, because you only need one copy of each method to be shared by all instances.
Object.create() - creates a new object with the specified prototype object and properties.
2. Cloning / Concatenative Inheritance / Mixins - States
Prototype cloning copy the properties from one object to another WITHOUT retaining a reference between the two objects.
Object.assign() - [ES6] copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.
3. Closure Prototypes / Functional Inheritance - Encapsulation / Privacy
Closure prototypes are functions that can be run against a target object in order to extend it. It’s a function prototype. Think of it as an alternative to a
constructor
orinit
function.Takeaways
Just don't use
new
,constructor
,super
and ES6class
.Three types of prototypal OO:
The stampit form:
(Here's the demonstration using stamps, but API outdated, see the lastest.)
Concatenative Inheritance
Objects can be built by adding properties to existing instances ad-hoc.
Dynamic object extension is the foundation of concatenative inheritance.
Middleware & Decorator
From this blog. Also Aspect-oriented Programming AOP.
Middleware
The most flexible/controlled way.
More famous examples: express, and Redux
Monkey Patching
Others
Misc
Scoping and Hoisting (Ref)
JavaScript has function-level scope, which is radically different from the C family. Blocks, such as if statements, do not create a new scope. Only functions do.
On runtime, all var and FunctionDeclarations
function foo() {...}
are moved by the interpreter to the beginning of each function (its scope) - this is known as Hoisting.So the good practise is:
Immediately-Invoked Function Expression (IIFE)
So,
function foo(){ /* code */ }();
would causes aSyntaxError: Unexpected token )
.The most widely accepted way to fix this is just to wrap it in parentheses, because in JavaScript, parens can’t contain statements.
This is useful for saving state with closures.
Read this for more detail.
(module.)exports
exports
is the recommended object unless you are planning to change the object type of your module from the traditional 'module instance' to something else.module.exports
object with an assignment operation, anything attached tomodule.exports
andexports
will be available in the 'required' module.(Non-)Blocking of Node.js
From hashnode
setTimeout( {...}, 0)
trick moves the slow code to the end of the message queue, allows other code to execute before our slow code blocks everything else, thus speed up synchronous code execution.Operator Precedence
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
Hacks
source
!!
+
connected && login()
||
array.length
in the loop (avoid large array length recalculation)in
str.replace(/this/g, 'that')
arr1.push.apply(arr1, arr2)
instead ofarr1.concat(arr2)
(to save memory)arr.sort(() => Math.random() - 0.5)
Parameters Handling
http://exploringjs.com/es6/ch_parameter-handling.html
Resources
Hub
News feed
Free eBooks
A complete list can be found at jsbooks
Selected
Node
The text was updated successfully, but these errors were encountered: