From a4785d757fbb4c10efe2e725e7060a2fbd55c8c5 Mon Sep 17 00:00:00 2001 From: gdut-yy Date: Wed, 26 Aug 2020 00:20:25 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=8C=E3=80=81=E4=B8=89=E7=BA=A7=E6=A0=87?= =?UTF-8?q?=E9=A2=98=20ch6--ch10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ch10.md | 30 +++++++++++----------- docs/ch6.md | 58 +++++++++++++++++++++--------------------- docs/ch7.md | 48 +++++++++++++++++------------------ docs/ch8.md | 72 ++++++++++++++++++++++++++-------------------------- docs/ch9.md | 32 +++++++++++------------ 5 files changed, 120 insertions(+), 120 deletions(-) diff --git a/docs/ch10.md b/docs/ch10.md index f9307b9..057ad36 100644 --- a/docs/ch10.md +++ b/docs/ch10.md @@ -11,7 +11,7 @@ Node modules using require() ES6 modules using export, import, and import() -10.1 Modules with Classes, Objects, and Closures +## 10.1 Modules with Classes, Objects, and Closures Though it may be obvious, it is worth pointing out that one of the important features of classes is that they act as modules for their methods. Think back to Example 9-8. That example defined a number of different classes, all of which had a method named has(). But you would have no problem writing a program that used multiple set classes from that example: there is no danger that the implementation of has() from SingletonSet will overwrite the has() method of BitSet, for example. The reason that the methods of one class are independent of the methods of other, unrelated classes is that the methods of each class are defined as properties of independent prototype objects. The reason that classes are modular is that objects are modular: defining a property in a JavaScript object is a lot like declaring a variable, but adding properties to objects does not affect the global namespace of a program, nor does it affect the properties of other objects. JavaScript defines quite a few mathematical functions and constants, but instead of defining them all globally, they are grouped as properties of a single global Math object. This same technique could have been used in Example 9-8. Instead of defining global classes with names like SingletonSet and BitSet, that example could have been written to define only a single global Sets object, with properties referencing the various classes. Users of this Sets library could then refer to the classes with names like Sets.Singleton and Sets.Bit. @@ -62,7 +62,7 @@ const stats = (function() { // And here is how we might use the module stats.mean([1, 3, 5, 7, 9]) // => 5 stats.stddev([1, 3, 5, 7, 9]) // => Math.sqrt(10) -10.1.1 Automating Closure-Based Modularity +### 10.1.1 Automating Closure-Based Modularity Note that it is a fairly mechanical process to transform a file of JavaScript code into this kind of module by inserting some text at the beginning and end of the file. All that is needed is some convention for the file of JavaScript code to indicate which values are to be exported and which are not. Imagine a tool that takes a set of files, wraps the content of each of those files within an immediately invoked function expression, keeps track of the return value of each function, and concatenates everything into one big file. The result might look something like this: @@ -104,14 +104,14 @@ s.insert(30); let average = stats.mean([...s]); // average is 20 This code is a rough sketch of how code-bundling tools (such as webpack and Parcel) for web browsers work, and it’s also a simple introduction to the require() function like the one used in Node programs. -10.2 Modules in Node +## 10.2 Modules in Node In Node programming, it is normal to split programs into as many files as seems natural. These files of JavaScript code are assumed to all live on a fast filesystem. Unlike web browsers, which have to read files of JavaScript over a relatively slow network connection, there is no need or benefit to bundling a Node program into a single JavaScript file. In Node, each file is an independent module with a private namespace. Constants, variables, functions, and classes defined in one file are private to that file unless the file exports them. And values exported by one module are only visible in another module if that module explicitly imports them. Node modules import other modules with the require() function and export their public API by setting properties of the Exports object or by replacing the module.exportsobject entirely. -10.2.1 Node Exports +### 10.2.1 Node Exports Node defines a global exports object that is always defined. If you are writing a Node module that exports multiple values, you can simply assign them to the properties of this object: const sum = (x, y) => x + y; @@ -140,7 +140,7 @@ const stddev = d => { // Now export only the public ones module.exports = { mean, stddev }; -10.2.2 Node Imports +### 10.2.2 Node Imports A Node module imports another module by calling the require() function. The argument to this function is the name of the module to be imported, and the return value is whatever value (typically a function, class, or object) that module exports. If you want to import a system module built in to Node or a module that you have installed on your system via a package manager, then you simply use the unqualified name of the module, without any “/” characters that would turn it into a filesystem path: @@ -174,12 +174,12 @@ const { stddev } = require('./stats.js'); // This is nice and succinct, though we lose a bit of context // without the 'stats' prefix as a namspace for the stddev() function. let sd = stddev(data); -10.2.3 Node-Style Modules on the Web +### 10.2.3 Node-Style Modules on the Web Modules with an Exports object and a require() function are built in to Node. But if you’re willing to process your code with a bundling tool like webpack, then it is also possible to use this style of modules for code that is intended to run in web browsers. Until recently, this was a very common thing to do, and you may see lots of web-based code that still does it. Now that JavaScript has its own standard module syntax, however, developers who use bundlers are more likely to use the official JavaScript modules with import and export statements. -10.3 Modules in ES6 +## 10.3 Modules in ES6 ES6 adds import and export keywords to JavaScript and finally supports real modularity as a core language feature. ES6 modularity is conceptually the same as Node modularity: each file is its own module, and constants, variables, functions, and classes defined within a file are private to that module unless they are explicitly exported. Values that are exported from one module are available for use in modules that explicitly import them. ES6 modules differ from Node modules in the syntax used for exporting and importing and also in the way that modules are defined in web browsers. The sections that follow explain these things in detail. First, though, note that ES6 modules are also different from regular JavaScript “scripts” in some important ways. The most obvious difference is the modularity itself: in regular scripts, top-level declarations of variables, functions, and classes go into a single global context shared by all scripts. With modules, each file has its own private context and can use the import and export statements, which is the whole point, after all. But there are other differences between modules and scripts as well. Code inside an ES6 module (like code inside any ES6 class definition) is automatically in strict mode (see §5.6.3). This means that, when you start using ES6 modules, you’ll never have to write "use strict" again. And it means that code in modules cannot use the with statement or the arguments object or undeclared variables. ES6 modules are even slightly stricter than strict mode: in strict mode, in functions invoked as functions, this is undefined. In modules, this is undefined even in top-level code. (By contrast, scripts in web browsers and Node set this to the global object.) @@ -189,7 +189,7 @@ ES6 modules have been in use on the web for years with the help of code bundlers And meanwhile, having pioneered JavaScript modularity, Node finds itself in the awkward position of having to support two not entirely compatible module systems. Node 13 supports ES6 modules, but for now, the vast majority of Node programs still use Node modules. -10.3.1 ES6 Exports +### 10.3.1 ES6 Exports To export a constant, variable, function, or class from an ES6 module, simply add the keyword export before the declaration: export const PI = Math.PI; @@ -218,7 +218,7 @@ It is legal, but somewhat uncommon, for modules to have a set of regular exports Finally, note that the export keyword can only appear at the top level of your JavaScript code. You may not export a value from within a class, function, loop, or conditional. (This is an important feature of the ES6 module system and enables static analysis: a modules export will be the same on every run, and the symbols exported can be determined before the module is actually run.) -10.3.2 ES6 Imports +### 10.3.2 ES6 Imports You import values that have been exported by other modules with the import keyword. The simplest form of import is used for modules that define a default export: import BitSet from './bitset.js'; @@ -248,7 +248,7 @@ A module like this runs the first time it is imported. (And subsequent imports d Note that you can use this import-nothing import syntax even with modules that do have exports. If a module defines useful behavior independent of the values it exports, and if your program does not need any of those exported values, you can still import the module . just for that default behavior. -10.3.3 Imports and Exports with Renaming +### 10.3.3 Imports and Exports with Renaming If two modules export two different values using the same name and you want to import both of those values, you will have to rename one or both of the values when you import it. Similarly, if you want to import a value whose name is already in use in your module, you will need to rename the imported value. You can use the as keyword with named imports to rename them as you import them: import { render as renderImage } from "./imageutils.js"; @@ -271,7 +271,7 @@ export { Keep in mind that, although the curly braces look something like object literals, they are not, and the export keyword expects a single identifier before the as, not an expression. This means, unfortunately, that you cannot use export renaming like this: export { Math.sin as sin, Math.cos as cos }; // SyntaxError -10.3.4 Re-Exports +### 10.3.4 Re-Exports Throughout this chapter, we’ve discussed a hypothetical “./stats.js” module that exports mean() and stddev() functions. If we were writing such a module and we thought that many users of the module would want only one function or the other, then we might want to define mean() in a “./stats/mean.js” module and define stddev() in “./stats/stddev.js”. That way, programs only need to import exactly the functions they need and are not bloated by importing code they do not need. Even if we had defined these statistical functions in individual modules, however, we might expect that there would be plenty of programs that want both functions and would appreciate a convenient “./stats.js” module from which they could import both on one line. @@ -306,7 +306,7 @@ And finally, to re-export the default export of another module as the default ex // The average.js module simply re-exports the stats/mean.js default export export { default } from "./stats/mean.js" -10.3.5 JavaScript Modules on the Web +### 10.3.5 JavaScript Modules on the Web The preceding sections have described ES6 modules and their import and export declarations in a somewhat abstract manner. In this section and the next, we’ll be discussing how they actually work in web browsers, and if you are not already an experienced web developer, you may find the rest of this chapter easier to understand after you have read Chapter 15. As of early 2020, production code using ES6 modules is still generally bundled with a tool like webpack. There are trade-offs to doing this,1 but on the whole, code bundling tends to give better performance. That may well change in the future as network speeds grow and browser vendors continue to optimize their ES6 module implementations. @@ -328,7 +328,7 @@ Another important difference between regular scripts and module scripts has to d Some programmers like to use the filename extension .mjs to distinguish their modular JavaScript files from their regular, non-modular JavaScript files with the traditional .js extension. For the purposes of web browsers and