现代 JavaScript 术语表(下)

TL;DR: In the first part of the Glossary of Modern JS Concepts series, we learned about functional, reactive, and functional reactive programming. In Part 2, we'll gain an understanding of concepts like scope, closures, tree shaking, components, and more, as well as JavaScript application topics such as data flowand change detection.
Introduction
Modern JavaScript has experienced massive proliferation over recent years and shows no signs of slowing. Numerous concepts appearing in JS blogs and documentation are still unfamiliar to many front-end developers. In this post series, we'll learn intermediate and advanced concepts in the current front-end programming landscape and explore how they apply to modern JavaScript, JS frameworks, and JS applications.
Concepts
In this article, we'll address concepts that are crucial to understanding modern JavaScript and JS applications, including scope and closures, data flow, change detection, components, compilation, and more.
You can jump straight into each concept here, or continue reading to learn about them in order.
Scope (Global, Local, Lexical) and Closures
One-Way Data Flow and Two-Way Data Binding
Change Detection in JS Frameworks: Dirty Checking, Accessors, Virtual DOM
Web Components
Smart and Dumb Components
JIT (Just-In-Time) Compilation
AOT (Ahead-of-Time) Compilation
Tree Shaking

Scope (Global, Local, Lexical) and Closures
"Explain closures" is an infamous JavaScript technical interview question. The truth is that plenty of skilled JS developers have difficulty explaining closures, even if they conceptually understand (and even use) them. Let's back up and talk about the concepts necessary to explain a closure.
Scope
In order to grasp closures, we need to understand scope first. Scope is simply the context of our code: where variables and functions are accessible.
The following example demonstrates two scopes, global scope and local scope:
// Global scopevar globalVar = 'Hello, ';console.log(localVar); // Uncaught ReferenceError: localVar is not definedsomeFunction() { // Local scope var localVar = 'World!'; console.log(globalVar + localVar); // 'Hello, World!'}

Everything has access to the global scope. If we open an empty .js
file and type var globalVar
, this variable is accessible to anything else we'll create. If we executed the file in a browser, globalVar
's function scope would be window
.
Note: If we declare a new variable without the var
keyword, it will be placed in the global scope no matter where it is in the code. You may have encountered this before (perhaps accidentally).

The someFunction
function creates its own local scope. It also inherits access to the global scope. We can freely use globalVar
inside someFunction
. However, the global scope does not have access to nested contexts, such as someFunction
's local scope. If we try to log localVar
from the global scope, we will receive an error because localVar
is not defined in the global scope.
In a nutshell, nested functions have their own scope. Functions declared inside another function also have access to their parent functions' scopes. This is called the scope chain.
Lexical scope (or static scope) refers to the fact that every nested function can access the functions that contain it.
Consider this example:
// Lexical scope and scope chainvar a = 1;function outerFunc() { var b = 2; console.log(a + b); function middleFunc() { var c = 3; console.log(a + b + c); function innerFunc() { var d = 4; console.log(a + b + c + d); } innerFunc(); // logs 10 (1 + 2 + 3 + 4) } middleFunc(); // logs 6 (1 + 2 + 3)}outerFunc(); // logs 3 (1 + 2)

This code is available to run at this JSFiddle: JS Scope (open your browser's console to see results). innerFunc
is the innermost function. It is declared inside middleFunc
, which is in turn declared in outerFunc
.
The innerFunc
function can access variables declared in all of its parent scopes. Its scope chain allows access to:
a
from the global scope,
b
from outerFunc
,
c
from middleFunc
, and
d
from innerFunc
's own local scope.

This only works down the nested functions, not up. For instance, the locally scoped variable d
is declared in innerFunc
and is not accessible to middleFunc
, outerFunc
, or the global scope.
Closures
In the first part of the Glossary of Modern JavaScript Concepts, we learned about higher-order functions and functions as first-class objects. If this doesn't sound familiar, take a moment to review the section on Higher-order Functions.
Now let's revisit the following higher-order function example we saw in Part 1:
// Higher-order functionfunction whenMeetingJohn() { return function() { alert('Hi!'); }}var atLunchToday = whenMeetingJohn();atLunchToday(); // alerts "Hi!"

This is a function that returns another function. Let's update this example to add an argument (salutation
) and a greeting
variable to whenMeetingJohn
's local scope. We'll also name the previously anonymous returned function alertGreeting
so we can refer to it more easily:
// Closuresfunction whenMeetingJohn(salutation) { var greeting = salutation + ', John!'; function alertGreeting() { alert(greeting); } return alertGreeting;}var atLunchToday = whenMeetingJohn('Hi');atLunchToday(); // alerts "Hi, John!"whenMeetingJohn('Whassup')(); // alerts "Whassup, John!"

This code is available to run at this JSFiddle: JS Closures.
A closure is formed when a function (alertGreeting
) declared inside an outer function (whenMeetingJohn
) references variables from the outer function's local scope (such as the greeting
variable).
The term "closure" refers to the function and the lexical environment (any local variables that were in scope when the closure was created) in which that function was declared.
When we execute atLunchToday()
, we receive an alert with the argument we passed during assignment ('Hi'
in this case) and the greeting
variable that was accessible in alertGreeting
's lexical environment.
Note: We can also call the returned function (alertGreeting
) without assigning it. Doing so looks like this: whenMeetingJohn('Whassup')()
.

Hopefully you can see the value in closures when looking at this simple example. We can greet John with several different salutations. Each time, we create a closure with access to the particular salutation data in scope at the time of creation.
Another common example demonstrating closures uses a simple addition expression:
// Closuresfunction addCreator(x) { return function(y) { alert(x + y); }}var add1 = addCreator(1);var add5 = addCreator(5);add1(2); // alerts 3add5(2); // alerts 7

This code can be run at this JSFiddle: JS Closures - Adder.
Both add1
and add5
are closures with different lexical environments storing different values for the x
argument. These values are protected by the fact that they're "enclosed" in the lexical environment of each closure. We could use the addCreator(x)
factory function to create as many add_
functions as we needed.
Scope and Closures Takeaways
Scope is something that many JS developers learn early on, but may not have had to explain in words or with specific examples. Understanding scope is vital to writing good JavaScript.
Note: There is more to scope than we covered here. There are some great resources available to achieve greater understanding, especially with regard to the this
keyword
. See below for more links.

Closures associate data with a function utilizing the lexical environment the function was declared in.
To learn more about scope and closures (and this
), check out the following resources:
Everything you wanted to know about JavaScript scope
Explaining JavaScript Scope and Closures
Scope in JavaScript
What is lexical scope?
MDN: Closures
What is "this"?
MDN: this
Understand JavaScript's "this" With Clarity, and Master It
JavaScript: How does the "this" keyword work?

One-Way Data Flow and Two-Way Data Binding
With the proliferation of JavaScript frameworks and Single Page Applications (SPAs), it's important for JS developers to understand concepts like data flow / binding, and how the tools we're using manage this.
One-Way Data Flow
An application or framework with one-way data flow uses the model as the single source of truth. React is a widely recognized example of one-way data flow (or one-way data binding). Messages are sent from the UI in the form of events to signal the model to update.
Take a look at the following React example:
// One-way data flow with Reactclass OneWay extends React.Component { constructor() { super(); this.handleChange = this.handleChange.bind(this); // set initial this.state.text to an empty string this.state = { text: '' }; } handleChange(e) { // get new input value from the event and update state this.setState({ text: e.target.value }); } render() { return ( <div> <input type="text" onChange={this.handleChange} /> <p>Text: {this.state.text}</p> </div> ); }}

This code is available to run at JSFiddle: React One-Way Data Flow.
We can see that the state
object model is established in the constructor
function. The initial value of this.state.text
is an empty string. In our render()
function, we add an onChange
handler to our <input>
element. We use this handler to setState()
, signalling the state
object model to update the text
property with the new value of the input field.
Data is only flowing in one direction: from the model down. The UI input does not have direct access to the model. If we want to update state in response to changes from the UI, the input must send a message carrying the payload. The only way the UI can influence the model is through this event and the setState()
method
. The UI will never automagically update the model.
Note: In order to reflect changes from the model to the UI, React creates a new virtual DOM and diffs the old virtual DOM with the updated virtual DOM. Only the changes are then rendered in the real DOM. We'll talk more about this in the section on change detection.

Two-Way Data Binding
In two-way data binding, the data flows in both directions. This means that the JS can update the model and the UI can do so as well. A common example of two-way data binding is with AngularJS.
Note: In this article, AngularJS refers specifically to version 1.x of the framework while Angular refers to versions 2.x and up, as per the Branding Guidelines for Angular.

Let's implement the same example from above, but with AngularJS two-way data binding:
// AngularJS two-way data binding// script.js(function() { angular .module('myApp', []) .controller('MyCtrl', function($scope) { // set initial $scope.text to an empty string $scope.text = ''; // watch $scope.text for changes $scope.$watch('text', function(newVal, oldVal) { console.log(Old value: ${oldVal}. New value: ${newVal}); }); });}());

<body ng-app="myApp"> <div ng-controller="MyCtrl"> <input type="text" ng-model="text" /> <p>Text: {{text}}</p> </div></body>

This code is available to run at Plunker: AngularJS Two-Way Binding.
In our controller, we set up the $scope.text
model. In our template, we associate this model with the <input>
using ng-model="text"
. When we change the input value in the UI, the model will also be updated in the controller. We can see this in the $watch()
.
Note: Using $watch()
in a controller is debateable practice. We've done it here for example purposes. In your own AngularJS apps, take into consideration that there are alternatives to using $watch()
in controllers (such as events), and if you do use $watch()
, always deregister your watches $onDestroy
.

This is two-way binding in AngularJS. As you can see, we didn't set up any events or handlers to explicitly signal the controller that the model was updated in the UI. The text
data binding in the template automatically uses a watcher to display changes to the model. We can also $watch()
the model. Watching should generally be done in services or directive link
functions, not in controllers.
Note: AngularJS uses what's called the digest cycle (dirty checking) to compare a value with the previous value. You can read more about dirty checking in AngularJS in the section on change detection.

Aside: Two-Way Data Binding in Angular
But wait! Angular (v2+) has the "banana-in-a-box" [(ngModel)]
, right? On the surface, this may look like persistence of automagical two-way data binding. However, that is not the case. Angular's two-way binding [()]
syntax
simply shortcuts property and event binding in a template, and the ngModel
directive
supplies an ngModelChange
event for you. To learn more about this, check out this article on two-way binding in Angular.
The following are functionally equivalent and demonstrate the ngModel
directive:
// ngModel directive: two-way binding syntax<input [(ngModel)]="text" /><p>{{text}}</p>// ngModel property and event binding<input [ngModel]="text" (ngModelChange)="text=$event" /><p>{{text}}</p>

The Angular docs on two-way binding cover this syntax thoroughly.
Data Flow and Binding Takeaways
Many modern JavaScript frameworks and libraries utilize unidirectional data flow (React, Angular, Inferno, Redux, etc.). Why? One-way data flow encourages clean architecture with regard to how data moves through an application. Application state is also easier to manage, updates are more predictable, and performance can be better as well.
Although automagical two-way data binding was one of AngularJS's most popular demos back in 2009, Angular has left it behind. Some Angular developers lamented this at first, but ultimately, many found that performance gains and greater control outweighed automagic.
As we saw in the React example above, it's important to remember that one-way data flow does not mean that it's difficult to update the store from the UI. It only means that such updates are done deliberately, with specific instruction. It's less magical, but much more manageable.
Note: Generally when developers mention "implementing two-way data binding" in frameworks with one-way data flow (such as React), they are referring to the steps necessary to have UI changes notify the state that it should be updated. They are not looking for a way to implement automagical two-way binding.

To learn more about one-way data flow and two-way data binding, check out the following resources:
Video: Introducing One-Way Data Flow
Diagrams comparing one-way and two-way data binding
Why does React emphasize unidirectional data flow and Flux architecture?
Data binding code in 9 JavaScript frameworks (from 2015, but still worth a look)
Two-way Data Binding in Angular (v2+)
AngularJS Docs - Data Binding
Thinking in React

Change Detection in JS Frameworks: Dirty Checking, Accessors, Virtual DOM
Change detection is important for any dynamic JavaScript Single Page Application (SPA). When the user updates something, the app must have a way to detect and react to that change appropriately. Some kind of change detection is therefore vital to SPA frameworks.
At a fairly high level, let's explore a few methods of change detection used in popular JavaScript frameworks today.
Dirty Checking
Although Angular was released, AngularJS still accounts for multitudes of apps in production or development right now. AngularJS uses what's known as the digest cycle to detect changes in an application. Under the hood, the digest cycle is dirty checking. What does this mean?
Dirty checking refers to a deep comparison that is run on all models in the view to check for a changed value. AngularJS's digest cycle adds a watcher for every property we add to the $scope
and bind in the UI. Another watcher is added when we want to watch values for changes using $scope.$watch()
.
"AngularJS remembers the value and compares it to a previous value. This is basic dirty-checking. If there is a change in value, then it fires the change event."Miško Hevery, creator of AngularJS and Angular

The digest cycle is a loop. AngularJS runs through its list of watchers and checks to see if any of the watched $scope
variables have changed (aka, are "dirty"). If a variable has not changed, it moves on to the next watched variable. If it finds one that is dirty, it remembers its new value and re-enters the loop. When no new changes are detected in the entire watch list, the DOM is updated.
The major advantages of dirty checking are that it's simple and predictable: there is no extending of objects and there are no APIs involved. However, it's also inefficient. Whenever anything changes, the the digest cycle is triggered. Therefore, it's important that care is taken when creating watchers in AngularJS. Every time a $scope
property is bound to the UI, a watcher is added. Every time a $watch()
is implemented, another watcher is added. Many directives also add watchers, and so do scope variables, filters, and repeaters.
Though dirty checking is sufficiently fast in a simple app, we can easily see how this can get out of hand in a complex implementation. This has led to articles such as 11 Tips to Improve AngularJS Performance: 1. Minimize/Avoid Watchersand Speeding up AngularJS's $digest loop.
Note: Angular (v2+) no longer uses dirty checking.

Accessors
Ember and Backbone use data accessors (getters and setters) for change detection. Ember objects inherit from Ember's APIs and have get()
and set()
methods that must be used to update models with data binding. This enables the binding between the UI and the data model and Ember then knows exactly what changed. In turn, only the modified data triggers change events to update the app.
Note: In Backbone, this is done with Backbone models with get()
and set()
methods.

This method is straightforward and enforces that the application author be very deliberate regarding their data bindings. However, on the flipside of the same coin, it can occasionally lead to confusion because Ember.Object
s are only used when data binding to templates. If there is no UI data binding, updates do not use Ember.Object
s. This mixed approach can result in the developer scratching their head when things aren't updating because of a forgotten setter or getter.
Virtual DOM
Virtual DOM is used by React (and Inferno.js) to implement change detection. React doesn't specifically detect each change. Instead, the virtual DOM is used to diff the previous state of the UI and the new state when a change occurs. React is notified of such changes by the use of the setState()
method, which triggers the render()
method to perform a diff.
Virtual DOM (occasionally known as V-DOM) is a JavaScript data model that represents the real DOM tree. When a virtual DOM is generated, nothing is rendered to the browser. The old model is compared to the new model and once React determines which parts of the virtual DOM have changed, only those parts are patched in the real DOM.
Change Detection Takeaways
There are many ways that JavaScript frameworks manage change detection, including more that weren't covered here. They each have strengths and weaknesses, but the modern trend is toward more deliberate and less automagical methods, many utilizing observer pattern under the hood.
To learn more about change detection in JS frameworks, check out the following resources:
Change and its Detection in JavaScript Frameworks
Change Detection Overview
Dirty checking in AngularJS
The Digest Loop and Apply
Ember.Object Class
Accessors vs. Dirty Checking in JavaScript Frameworks
React.JS internals: Virtual DOM
The Difference Between Virtual DOM and DOM
React: Reconciliation
virtual-dom
VueJS: How Changes are Tracked
Polymer 2.0: Observers and Computed Properties
Understanding Angular 2 Change Detection
Angular Change Detection Explained

Web Components
Web components are encapsulated, reusable widgets based on web platform APIs. They are composed of four standards:
Custom Elements
HTML Templates
Shadow DOM
HTML Imports

Web components allow us to architect and import custom elements that automatically associate JS behavior with templates and can utilize shadow DOM to provide CSS scoping and DOM encapsulation.
Web components consist of a set of web platform APIs. There are libraries (such as Polymer) and polyfills (such as webcomponents.js) to bridge the gap between current browser support and future web API support.
Let's say we want to create a simple web component (my-component
) that shows some static text. We'd like to use HTML attributes to have the component change its text color and log something to the console. To display the <my-component>
custom element in our website or app, we might import and use it like so:
<html> <head> ... <script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/0.7.24/webcomponents.min.js"></script> <link rel="import" href="my-web-cmpnt.html"> </head> <body> <my-web-cmpnt color="red" log="Hello"></my-web-cmpnt> ...

To create the my-component
web component utilizing shadow DOM, our my-component.html
might look something like this:
<template> <style> .my-component { display: block; padding: 20px; } </style> <div class="my-component"> <p>This is a custom element!</p> </div></template><script> (function(window, document, undefined) { var doc = document; // my-component document var self = (doc._currentScript || doc.currentScript).ownerDocument; var template = self.querySelector('template').content; // ShadowCSS shim, if needed if (window.ShadowDOMPolyfill) { WebComponents.ShadowCSS.shimStyling(template, 'my-component'); } class MyComponent extends HTMLElement { constructor() { super(); } connectedCallback() { // get attributes var color = this.getAttribute('color'); var log = this.getAttribute('log'); // utilize shadow DOM var shadowRoot = this.attachShadow({mode:'open'}); var clone = doc.importNode(template, true); var myComponent; shadowRoot.appendChild(clone); myComponent = shadowRoot.querySelector('.my-component'); // style with color and output log myComponent.style.color = color; console.log(log); } } window.customElements.define('my-component', MyComponent); }(window, document));</script>

This code is available to run at Plunker: Web components.
The <template>
defines the element's CSS styling and HTML markup. Then, to take advantage of shadow DOM and JS functionality, we add a <script>
tag to our my-component.html
file after the closing </template>
tag and implement our desired custom element JS functionality to get the element's attributes and use them to change the text color and log our message.
When inspected with Chrome devtools, our component looks like this:


For a much more indepth tutorial, check out Web Components: How To Craft Your Own Custom Components.
Web components bring powerful, framework-like capabilities to browsers, and while the spec and support are still being finalized, the concepts have inspired frameworks such as Angular (which initially attempted to use Web API web components, but ended up with its own implementation). Many JS frameworks (Angular, React, Ember, Vue) leverage the concept of componetization with varying degrees of similarity to the web components API.
Web Components Takeaways
Web components allow us to create and use custom HTML elements with JS. They can also utilize the shadow DOM to provide CSS scoping and DOM encapsulation. By themselves, web components alone aren't a substitute for all the features of a SPA framework. However, their core concepts are heavily leveraged by many frameworks in use today and their future in the front-end landscape offers many opportunities for a growing community of resources.
To learn more about web components, check out the following resources:
W3C Web Components Current Status
webcomponents.org
Web Components: How To Craft Your Own Custom Components
MDN: Web Components
Using Web Components in React
Build Your First App with Polymer and Web Components
Are We Componetized Yet?
webcomponentjs on GitHub
Google Polymer

Smart and Dumb Components
As we talked about above, some modern JS frameworks are heavily component-based. This leads to concepts of component architecture and component communication. In some cases (such as in React and Angular), component architecture utilizes smart and dumb components. They are also referred to as "container" (smart) and "presentational" (dumb) components.
Smart Components
Also known as container components, smart components can manage interactions with the application's state and data. They handle business logic and respond to events emitted from children (which are often dumb components).
Dumb Components
Also known as presentational components, dumb components rely on inputssupplied by their parents and are ignorant of application state. They can be sometimes be considered pure and are modular and reusable. They can communicate to their parents when reacting to an event, but they don't handlethe event themselves.
Presentational and Container Components in React
Dan Abramov, the co-author of Redux, Create React App, React Hot Loader, and more, originally wrote about presentational and container components and their meaning in React, particularly when used with state management like Flux or Redux. In a nutshell, the concepts can be summarized as follows:
PRESENTATIONAL (AKA DUMB) COMPONENTS:
Focus on "How things look"
Allow containment with this.props.children

No dependencies on the rest of the app (ie., no Flux or Redux actions or stores)
Only receive data; do not load or mutate it
Are generally functional (with exceptions)

CONTAINER (AKA SMART) COMPONENTS:
Focus on "How things work"
Provide data and behavior to other components
Usually have no or very little DOM markup, and never have styles
Are often stateful data sources
Are generally generated from higher order components

Check out his article for more details and explanation.
Example: Smart and Dumb Components in Angular
For a quick example that doesn't involve a state container, let's look at some simple smart and dumb components using Angular.
Let's say we want a madlib-style feature where we apologize for lashing out while hungry, tired, or debugging. When we're done, it should look like this in the browser:

modern js glossary: Angular smart and dumb components
modern js glossary: Angular smart and dumb components

The smart (container) component looks like this:
// app/smart.component.tsimport { Component } from '@angular/core';import { DumbComponent } from './dumb.component';@Component({ selector: 'my-smart-cmpnt', template: <h1>I'm sorry for what I said when I was {{selectedOption}}.</h1> <my-dumb-cmpnt [options]="optionsArr" (changedOption)="onOptionChange($event)"></my-dumb-cmpnt>})export class SmartComponent { optionsArr = ['hungry', 'tired', 'debugging']; selectedOption = '______'; onOptionChange(e: string) { this.selectedOption = e; }}

This component manages all of the data necessary for this feature. It provides the options for the madlib (optionsArr
) and then handles when the user chooses an option (onOptionChange()
). It stores the selectedOption
, passes the possible options into the dumb component, and sets the selected option when the dumb component emits a changedOption
event.
// app/dumb.component.tsimport { Component, Input, Output, EventEmitter } from '@angular/core';@Component({ selector: 'my-dumb-cmpnt', template: <div *ngFor="let option of options"> <button (click)="select(option)">{{option}}</button> </div>})export class DumbComponent { @Input() options: Array; @Output() changedOption = new EventEmitter(); select(option) { this.changedOption.emit(option); }}

In turn, the dumb component accepts the options array as input and iterates over each item to create the buttons to select an option. When an option is clicked, the changedOption
event is emitted with the selected option as its payload. The parent smart component then handles this event and sets its selectedOption
for display in the UI.
This code is available to run at Plunker: Angular Smart and Dumb Components.
Smart and Dumb Components Takeaways
Smart (container) components manage data, implement business logic, and handle events. Dumb (presentational) components accept inputs and can emit events, which are handled by a parent smart component. Dumb components are modular and can be reused throughout an application due to their more stateless nature. When using a state container like Redux or ngrx/store, only smart components would dispatch actions or interact with the store.
To learn more about smart and dumb components, check out the following resources:
Container Components
Presentational and Container Components
Presentational vs container components
React at Preact: Smart Components
React at Preact: Dumb Components
Angular Smart Components vs Presentation Components: What's the Difference, When to Use Each and Why?
Managing State in Angular with ngrx/store

JIT (Just-In-Time) Compilation
Just-In-time (JIT) compilation is the process of translating code written in a programming language to machine code at runtime (during a program or application's execution). At runtime, certain dynamic information is available, such as type identification. A JIT compiler monitors to detect functions or loops of code that are run multiple times—this code is considered "warm". These pieces of code are then compiled. If they're quite commonly executed ("hot"), JIT will optimize them and also store the optimized, compiled code for execution.
When the compiler optimizes hot code, it makes assumptions about its types and shape based on consistency of previous executions. At any iteration, if those assumptions turn out to be inaccurate, the optimized code is discarded.
Browsers use JIT compilation to run JavaScript. In the modern JavaScript framework landscape, compilers in frameworks like Angular can use JIT to compile TypeScript and Angular code to JS to machine code at runtime during local development, compiling each file separately. This provides certain advantages, such as no need to rebuild the project when watching for code changes and a faster initial build time.
JIT Compilation Takeaways
JIT compilation is used by browsers to compile JavaScript at runtime, and by frameworks like Angular to provide a fast local development experience.
To learn more about JIT compilation, check out the following resources:
What does a just-in-time (JIT) compiler do?
JIT compiler overview
1/3 A cartoon intro to WebAssembly
2/3 A crash course in just-in-time (JIT) compilers
3/3 A crash course in assembly
The race for speed part 2: How JavaScript compilers work
Mozilla TraceMonkey
How the V8 engine works?
JIT vs AOT in Angular2 and how to use it

AOT (Ahead-Of-Time) Compilation
Ahead-Of-Time (AOT) compilation is the process of translating code written in a programming language to machine code before execution (as opposed to at runtime). Doing so reduces runtime overhead and compiles all files together rather than separately.
With regard to JavaScript application AOT, such as that used by Angular, this means inlining HTML and CSS and being able to deploy without the compiler, saving considerable size. The browser can also render the application immediately since it's precompiled.
There are several benefits to AOT for production builds:
Fewer asynchronous requests: templates and styles are inlined with JS
Smaller download size: the compiler doesn't need to be downloaded if the app is already compiled
Detect template errors earlier: compiler detects binding errors during build rather than at runtime
Better security: evaluation is already done, which lowers chance of injection

AOT also enables tree shaking. In the browser, an app compiled with AOT promotes a shorter total time to load and bootstrap due to being precompiled. Initial rendering time is also reduced because less code needs to be parsed.
However, AOT will have a longer initial build time than JIT and would require a full recompile of the entire app if any changes are made.
AOT Compilation Takeaways
AOT compilation takes place before runtime and bundles all files together. It enables tree shaking, smaller downloads, and improved security compared to JIT.
To learn more about AOT compilation, check out the following resources:
Angular: Is AOT Worth It?
Ahead-of-Time Compilation in Angular
Ahead-of-Time Comilation
IBM: The ahead-of-time compiler

Tree Shaking
Tree shaking is a JavaScript module bundling term that refers to the static analysis of all imported code and exclusion of anything that isn't actually used.
In a more literal analogy, consider a living tree. The tree is shaken and this causes the dead leaves to fall off, leaving behind the leaves the tree is actively using for photosynthesis. The concept behind tree shaking is live code inclusion: we include the parts that are needed to begin with, as opposed to removing the parts that are unneeded at the end (dead code elimination).
Tree shaking relies on ES2015 module import
and export
. The import
and export
statements compose an app's static module structure. When the modules are bundled for deployment, the tree shaker analyzes the static module structure so that unused exports can be excluded, reducing the size of the final bundle.
ES2015 enables us to specify explicit imports. For example, rather than importing the entire RxJS library, we can only import exactly what we want:
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

This differs from the dynamic require
statement used by CommonJS or AMD. Tree shaking uses this principle to walk the dependency graph and exclude things that aren't needed in order to reduce the size of deployment bundles.
The principle of tree shaking is not new, but it has recently been popularized by the rollup.js module bundler. Tree shaking is utilized in Webpack 2 as well. The concept of tree shaking and writing code that promotes it is also prevalent in Angular with AOT compilation.
Tree Shaking Takeaways
Tree shaking is term for JavaScript live code inclusion in module bundlers that use ES2015 static import
and export
to "shake out" unneeded dependencies on a more granular level.
To learn more about tree shaking, check out the following resources:
Tree-shaking versus dead code elimination
rollup.js
Tree Shaking with Webpack
Tree-shaking with webpack 2 and Babel 6
Angular Docs: Tree shaking
Kendo UI for Angular: Tree Shaking
How To Clean Up Your JavaScript Build With Tree Shaking

Aside: Learning and Implementing Authentication with Auth0
One of the most complex features to implement in an application is user authentication and identity management. Security for authentication and identity is an entire glossary unto itself.

Auth0 hosted login screen
Auth0 hosted login screen

If you need to implement a robust, highly customizable identity and access management system quickly and easily for your JavaScript SPAs and Node APIs, Auth0 can help. Auth0 provides Single Page Application QuickStart guides, an SDK for web, plenty of documentation, and this blog's articles and tutorials. You can sign up for a free Auth0 account here to get started.
Conclusion
With the swift rise of JavaScript Single Page Application frameworks and component-based paradigms, it's important to understand JS topics relating to scoping, data flow, components, compilation, and bundling.
With this glossary as a starting point, you can begin taking advantage of these concepts and programming paradigms to increase your JavaScript expertise. If anything is still unclear regarding these topics, please consult the links in each section for additional resources. You can also check out the first part of the Glossary of Modern JS Concepts to learn about the concepts necessary to understand functional programming, reactive programming, and functional reactive programming.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • **2014真题Directions:Read the following text. Choose the be...
    又是夜半惊坐起阅读 9,437评论 0 23
  • 昊宇低眸火柱栽,头插五兽众星呆。 高昂黄浦惊桑月,笑傲东方瞭望台。 (五兽:指天宫的五个区域) 竹影_张育清
    竹影_张育清阅读 960评论 1 7
  • 近几年时常联系的最早认识的同学,是好不容易找到的一个小学同学,高中的同学大概有一少半偶尔联系,大学的同学有一半在联...
    心沁轩阅读 251评论 0 0
  • 刚刚跑完步,这几天脑子里一直萦绕年级管理的几条意见,如果再不写出来那么我感觉自己就会神经错乱了。 第一,军训周让学...
    一星若月阅读 852评论 0 0