久久精品中文字幕av,av.涩涩涩涩涩涩涩涩,亚洲国产日韩欧美精品成人久久久,成人福利电影免费在线观看,日产国产原创av,日韩av午夜激情,bt天堂中文字幕,超级碰人妻在线视频,欧美老熟妇久久一区二区

ThinkChat3.0新版上線,打造企業(yè)超級(jí)智能體和OPC神器,直接交付工作成果而非僅僅是給出答案,送30W Token,即刻開啟你的AI之旅 廣告
## Chapter 10 # Modules > [](http://eloquentjavascript.net/10_modules.html#p_PJiK2g1JXC)A beginning programmer writes her programs like an ant builds her hill, one piece at a time, without thought for the bigger structure. Her programs will be like loose sand. They may stand for a while, but growing too big they fall apart. > > [](http://eloquentjavascript.net/10_modules.html#p_OfZWeuo+oF)Realizing this problem, the programmer will start to spend a lot of time thinking about structure. Her programs will be rigidly structured, like rock sculptures. They are solid, but when they must change, violence must be done to them. > > [](http://eloquentjavascript.net/10_modules.html#p_fFMEGH1dk3)The master programmer knows when to apply structure and when to leave things in their simple form. Her programs are like clay, solid yet malleable. > > Master Yuan-Ma,?The Book of Programming [](http://eloquentjavascript.net/10_modules.html#p_1aMUBkVbPd)Every program has a shape. On a small scale, this shape is determined by its division into functions and the blocks inside those functions. Programmers have a lot of freedom in the way they structure their programs. Shape follows more from the taste of the programmer than from the program’s intended functionality. [](http://eloquentjavascript.net/10_modules.html#p_NOETmtvWWx)When looking at a larger program in its entirety, individual functions start to blend into the background. Such a program can be made more readable if we have a larger unit of organization. [](http://eloquentjavascript.net/10_modules.html#p_07zdYJYQ1M)*Modules*?divide programs into clusters of code that, by?*some*?criterion, belong together. This chapter explores some of the benefits that such division provides and shows techniques for building modules in JavaScript. ## [](http://eloquentjavascript.net/10_modules.html#h_0DSW4+9YVh)Why modules help [](http://eloquentjavascript.net/10_modules.html#p_ovuaejexnJ)There are a number of reasons why authors divide their books into chapters and sections. These divisions make it easier for a reader to see how the book is built up and to find specific parts that they are interested in. They also help the*author*?by providing a clear focus for every section. [](http://eloquentjavascript.net/10_modules.html#p_QxCtWUR2zJ)The benefits of organizing a program into several files or modules are similar. Structure helps people who aren’t yet familiar with the code find what they are looking for and makes it easier for the programmer to keep things that are related close together. [](http://eloquentjavascript.net/10_modules.html#p_4vnN7lCDZy)Some programs are even organized along the model of a traditional text, with a well-defined order in which the reader is encouraged to go through the program and with lots of prose (comments) providing a coherent description of the code. This makes reading the program a lot less intimidating—reading unknown code is usually intimidating—but has the downside of being more work to set up. It also makes the program more difficult to change because prose tends to be more tightly interconnected than code. This style is called*literate programming*. The “project” chapters of this book can be considered literate programs. [](http://eloquentjavascript.net/10_modules.html#p_Ou/d4KbIy/)As a general rule, structuring things costs energy. In the early stages of a project, when you are not quite sure yet what goes where or what kind of modules the program needs at all, I endorse a minimalist, structureless attitude. Just put everything wherever it is convenient to put it until the code stabilizes. That way, you won’t be wasting time moving pieces of the program back and forth, and you won’t accidentally lock yourself into a structure that does not actually fit your program. ### [](http://eloquentjavascript.net/10_modules.html#h_NitCO6r9Hn)Namespacing [](http://eloquentjavascript.net/10_modules.html#p_8S/+Hon3uA)Most modern programming languages have a scope level between?*global*(everyone can see it) and?*local*?(only this function can see it). JavaScript does not. Thus, by default, everything that needs to be visible outside of the scope of a top-level function is visible?*everywhere*. [](http://eloquentjavascript.net/10_modules.html#p_QMB7RIsBay)Namespace pollution, the problem of a lot of unrelated code having to share a single set of global variable names, was mentioned in?[Chapter 4](http://eloquentjavascript.net/04_data.html#namespace_pollution), where the`Math`?object was given as an example of an object that acts like a module by grouping math-related functionality. [](http://eloquentjavascript.net/10_modules.html#p_bBKNVkrywA)Though JavaScript provides no actual module construct yet, objects can be used to create publicly accessible subnamespaces, and functions can be used to create an isolated, private namespace inside of a module. Later in this chapter, I will discuss a way to build reasonably convenient, namespace-isolating modules on top of the primitive concepts that JavaScript gives us. ### [](http://eloquentjavascript.net/10_modules.html#h_UuxJID5Z2e)Reuse [](http://eloquentjavascript.net/10_modules.html#p_0MwF7DbAP0)In a “flat” project, which isn’t structured as a set of modules, it is not apparent which parts of the code are needed to use a particular function. In my program for spying on my enemies (see?[Chapter 9](http://eloquentjavascript.net/09_regexp.html#ini)), I wrote a function for reading configuration files. If I want to use that function in another project, I must go and copy out the parts of the old program that look like they are relevant to the functionality that I need and paste them into my new program. Then, if I find a mistake in that code, I’ll fix it only in whichever program that I’m working with at the time and forget to also fix it in the other program. [](http://eloquentjavascript.net/10_modules.html#p_n5Itkf6SsY)Once you have lots of such shared, duplicated pieces of code, you will find yourself wasting a lot of time and energy on moving them around and keeping them up-to-date. [](http://eloquentjavascript.net/10_modules.html#p_zwgHmRoxk9)Putting pieces of functionality that stand on their own into separate files and modules makes them easier to track, update, and share because all the various pieces of code that want to use the module load it from the same actual file. [](http://eloquentjavascript.net/10_modules.html#p_D2yYhnbA9K)This idea gets even more powerful when the relations between modules—which other modules each module depends on—are explicitly stated. You can then automate the process of installing and upgrading external modules (*libraries*). [](http://eloquentjavascript.net/10_modules.html#p_3ED8vjm59N)Taking this idea even further, imagine an online service that tracks and distributes hundreds of thousands of such libraries, allowing you to search for the functionality you need and, once you find it, set up your project to automatically download it. [](http://eloquentjavascript.net/10_modules.html#p_8hHGZUvmtE)This service exists. It is called NPM ([*npmjs.org*](http://npmjs.org/)). NPM consists of an online database of modules and a tool for downloading and upgrading the modules your program depends on. It grew out of Node.js, the browserless JavaScript environment we will discuss in?[Chapter 20](http://eloquentjavascript.net/20_node.html#node), but can also be useful when programming for the browser. ### [](http://eloquentjavascript.net/10_modules.html#h_qJacYNwWWL)Decoupling [](http://eloquentjavascript.net/10_modules.html#p_BIr3LxVodJ)Another important role of modules is isolating pieces of code from each other, in the same way that the object interfaces from?[Chapter 6](http://eloquentjavascript.net/06_object.html#interface)?do. A well-designed module will provide an interface for external code to use. As the module gets updated with bug fixes and new functionality, the existing interface stays the same (it is?*stable*) so that other modules can use the new, improved version without any changes to themselves. [](http://eloquentjavascript.net/10_modules.html#p_B3JCtLjLbo)Note that a stable interface does not mean no new functions, methods, or variables are added. It just means that existing functionality isn’t removed and its meaning is not changed. [](http://eloquentjavascript.net/10_modules.html#p_vcubl5qb7a)A good module interface should allow the module to grow without breaking the old interface. This means exposing as few of the module’s internal concepts as possible while also making the “l(fā)anguage” that the interface exposes powerful and flexible enough to be applicable in a wide range of situations. [](http://eloquentjavascript.net/10_modules.html#p_jT10dBy1PO)For interfaces that expose a single, focused concept, such as a configuration file reader, this design comes naturally. For others, such as a text editor, which has many different aspects that external code might need to access (content, styling, user actions, and so on), it requires careful design. ## [](http://eloquentjavascript.net/10_modules.html#h_FIe+oM6Cvt)Using functions as namespaces [](http://eloquentjavascript.net/10_modules.html#p_Qi0v4Dtc05)Functions are the only things in JavaScript that create a new scope. So if we want our modules to have their own scope, we will have to base them on functions. [](http://eloquentjavascript.net/10_modules.html#p_TJhIvzABX+)Consider this trivial module for associating names with day-of-the-week numbers, as returned by a?`Date`?object’s?`getDay`?method: ~~~ var names = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; function dayName(number) { return names[number]; } console.log(dayName(1)); // → Monday ~~~ [](http://eloquentjavascript.net/10_modules.html#p_lljN2eMCck)The?`dayName`?function is part of the module’s interface, but the?`names`?variable is not. We would prefer?*not*?to spill it into the global scope. [](http://eloquentjavascript.net/10_modules.html#p_NKmpNxgsFg)We can do this: ~~~ var dayName = function() { var names = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; return function(number) { return names[number]; }; }(); console.log(dayName(3)); // → Wednesday ~~~ [](http://eloquentjavascript.net/10_modules.html#p_wFyqiGP0o5)Now?`names`?is a local variable in an (unnamed) function. This function is created and immediately called, and its return value (the actual?`dayName`function) is stored in a variable. We could have pages and pages of code in this function, with 100 local variables, and they would all be internal to our module—visible to the module itself but not to outside code. [](http://eloquentjavascript.net/10_modules.html#p_XMMYXbTqGr)We can use a similar pattern to isolate code from the outside world entirely. The following module logs a value to the console but does not actually provide any values for other modules to use: ~~~ (function() { function square(x) { return x * x; } var hundred = 100; console.log(square(hundred)); })(); // → 10000 ~~~ [](http://eloquentjavascript.net/10_modules.html#p_NhLZMeErEJ)This code simply outputs the square of 100, but in the real world it could be a module that adds a method to some prototype or sets up a widget on a web page. It is wrapped in a function to prevent the variables it uses internally from polluting the global scope. [](http://eloquentjavascript.net/10_modules.html#p_TMPi6xxW7Y)Why did we wrap the namespace function in a pair of parentheses? This has to do with a quirk in JavaScript’s syntax. If an?*expression*?starts with the keyword`function`, it is a function expression. However, if a?*statement*?starts with`function`, it is a function?*declaration*, which requires a name and, not being an expression, cannot be called by writing parentheses after it. You can think of the extra wrapping parentheses as a trick to force the function to be interpreted as an expression. ## [](http://eloquentjavascript.net/10_modules.html#h_tbrMjRcajd)Objects as interfaces [](http://eloquentjavascript.net/10_modules.html#p_jaxyyZ13ux)Now imagine that we want to add another function to our day-of-the-week module, one that goes from a day name to a number. We can’t simply return the function anymore but must wrap the two functions in an object. ~~~ var weekDay = function() { var names = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; return { name: function(number) { return names[number]; }, number: function(name) { return names.indexOf(name); } }; }(); console.log(weekDay.name(weekDay.number("Sunday"))); // → Sunday ~~~ [](http://eloquentjavascript.net/10_modules.html#p_67L/Eo8MtL)For bigger modules, gathering all the?*exported*?values into an object at the end of the function becomes awkward since many of the exported functions are likely to be big and you’d prefer to write them somewhere else, near related internal code. A convenient alternative is to declare an object (conventionally named?`exports`) and add properties to that whenever we are defining something that needs to be exported. In the following example, the module function takes its interface object as an argument, allowing code outside of the function to create it and store it in a variable. (Outside of a function,?`this`refers to the global scope object.) ~~~ (function(exports) { var names = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; exports.name = function(number) { return names[number]; }; exports.number = function(name) { return names.indexOf(name); }; })(this.weekDay = {}); console.log(weekDay.name(weekDay.number("Saturday"))); // → Saturday ~~~ ## [](http://eloquentjavascript.net/10_modules.html#h_ryZfYeSnJy)Detaching from the global scope [](http://eloquentjavascript.net/10_modules.html#p_AfCtO+ifwZ)The previous pattern is commonly used by JavaScript modules intended for the browser. The module will claim a single global variable and wrap its code in a function in order to have its own private namespace. But this pattern still causes problems if multiple modules happen to claim the same name or if you want to load two versions of a module alongside each other. [](http://eloquentjavascript.net/10_modules.html#p_Y2ejGOe+u4)With a little plumbing, we can create a system that allows one module to directly ask for the interface object of another module, without going through the global scope. Our goal is a?`require`?function that, when given a module name, will load that module’s file (from disk or the Web, depending on the platform we are running on) and return the appropriate interface value. [](http://eloquentjavascript.net/10_modules.html#p_6BOb5Vhxc7)This approach solves the problems mentioned previously and has the added benefit of making your program’s dependencies explicit, making it harder to accidentally make use of some module without stating that you need it. [](http://eloquentjavascript.net/10_modules.html#p_qsfTCs+Kiu)For?`require`?we need two things. First, we want a function?`readFile`, which returns the content of a given file as a string. (A single such function is not present in standard JavaScript, but different JavaScript environments, such as the browser and Node.js, provide their own ways of accessing files. For now, let’s just pretend we have this function.) Second, we need to be able to actually execute this string as JavaScript code. ## [](http://eloquentjavascript.net/10_modules.html#h_oeOkEDaadU)Evaluating data as code [](http://eloquentjavascript.net/10_modules.html#p_jvij1au4eP)There are several ways to take data (a string of code) and run it as part of the current program. [](http://eloquentjavascript.net/10_modules.html#p_sQ1ASk7W7E)The most obvious way is the special operator?`eval`, which will execute a string of code in the?*current*?scope. This is usually a bad idea because it breaks some of the sane properties that scopes normally have, such as being isolated from the outside world. ~~~ function evalAndReturnX(code) { eval(code); return x; } console.log(evalAndReturnX("var x = 2")); // → 2 ~~~ [](http://eloquentjavascript.net/10_modules.html#p_dJLBESQexx)A better way of interpreting data as code is to use the?`Function`?constructor. This takes two arguments: a string containing a comma-separated list of argument names and a string containing the function’s body. ~~~ var plusOne = new Function("n", "return n + 1;"); console.log(plusOne(4)); // → 5 ~~~ [](http://eloquentjavascript.net/10_modules.html#p_8DGWg5jk7v)This is precisely what we need for our modules. We can wrap a module’s code in a function, with that function’s scope becoming our module scope. ## [](http://eloquentjavascript.net/10_modules.html#h_v/XE3QWFpP)Require [](http://eloquentjavascript.net/10_modules.html#p_hpfd8nPIk6)The following is a minimal implementation of?`require`: ~~~ function require(name) { var code = new Function("exports", readFile(name)); var exports = {}; code(exports); return exports; } console.log(require("weekDay").name(1)); // → Monday ~~~ [](http://eloquentjavascript.net/10_modules.html#p_JrILpUgcrH)Since the?`new Function`?constructor wraps the module code in a function, we don’t have to write a wrapping namespace function in the module file itself. And since we make?`exports`?an argument to the module function, the module does not have to declare it. This removes a lot of clutter from our example module. ~~~ var names = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; exports.name = function(number) { return names[number]; }; exports.number = function(name) { return names.indexOf(name); }; ~~~ [](http://eloquentjavascript.net/10_modules.html#p_B75dGyOs9V)When using this pattern, a module typically starts with a few variable declarations that load the modules it depends on. ~~~ var weekDay = require("weekDay"); var today = require("today"); console.log(weekDay.name(today.dayNumber())); ~~~ [](http://eloquentjavascript.net/10_modules.html#p_5GfcRhlMLC)The simplistic implementation of?`require`?given previously has several problems. For one, it will load and run a module every time it is?`require`d, so if several modules have the same dependency or a?`require`?call is put inside a function that will be called multiple times, time and energy will be wasted. [](http://eloquentjavascript.net/10_modules.html#p_zLUwyIBMDV)This can be solved by storing the modules that have already been loaded in an object and simply returning the existing value when one is loaded multiple times. [](http://eloquentjavascript.net/10_modules.html#p_Ylx5bX6l+o)The second problem is that it is not possible for a module to directly export a value other than the?`exports`?object, such as a function. For example, a module might want to export only the constructor of the object type it defines. Right now, it cannot do that because?`require`?always uses the?`exports`?object it creates as the exported value. [](http://eloquentjavascript.net/10_modules.html#p_RwxY5rq2Qj)The traditional solution for this is to provide modules with another variable,`module`, which is an object that has a property?`exports`. This property initially points at the empty object created by?`require`?but can be overwritten with another value in order to export something else. ~~~ function require(name) { if (name in require.cache) return require.cache[name]; var code = new Function("exports, module", readFile(name)); var exports = {}, module = {exports: exports}; code(exports, module); require.cache[name] = module.exports; return module.exports; } require.cache = Object.create(null); ~~~ [](http://eloquentjavascript.net/10_modules.html#p_Dv+TulRay7)We now have a module system that uses a single global variable (`require`) to allow modules to find and use each other without going through the global scope. [](http://eloquentjavascript.net/10_modules.html#p_rvZ9T+1c9y)This style of module system is called?*CommonJS modules*, after the pseudo-standard that first specified it. It is built into the Node.js system. Real implementations do a lot more than the example I showed. Most importantly, they have a much more intelligent way of going from a module name to an actual piece of code, allowing both pathnames relative to the current file and module names that point directly to locally installed modules. ## [](http://eloquentjavascript.net/10_modules.html#h_A4LDSlASUo)Slow-loading modules [](http://eloquentjavascript.net/10_modules.html#p_isvKkfyGNv)Though it is possible to use the CommonJS module style when writing JavaScript for the browser, it is somewhat involved. The reason for this is that reading a file (module) from the Web is a lot slower than reading it from the hard disk. While a script is running in the browser, nothing else can happen to the website on which it runs, for reasons that will become clear in?[Chapter 14](http://eloquentjavascript.net/14_event.html#timeline). This means that if every?`require`?call went and fetched something from some faraway web server, the page would freeze for a painfully long time while loading its scripts. [](http://eloquentjavascript.net/10_modules.html#p_Ce7X8+/o7v)One way to work around this problem is to run a program like?[*Browserify*](http://browserify.org/)?on your code before you serve it on a web page. This will look for calls to?`require`, resolve all dependencies, and gather the needed code into a single big file. The website itself can simply load this file to get all the modules it needs. [](http://eloquentjavascript.net/10_modules.html#p_L9zjrOe2Un)Another solution is to wrap the code that makes up your module in a function so that the module loader can first load its dependencies in the background and then call the function, initializing the module, when the dependencies have been loaded. That is what the Asynchronous Module Definition (AMD) module system does. [](http://eloquentjavascript.net/10_modules.html#p_69ZNnLLNhP)Our trivial program with dependencies would look like this in AMD: ~~~ define(["weekDay", "today"], function(weekDay, today) { console.log(weekDay.name(today.dayNumber())); }); ~~~ [](http://eloquentjavascript.net/10_modules.html#p_/aD387r6Uv)The?`define`?function is central to this approach. It takes first an array of module names and then a function that takes one argument for each dependency. It will load the dependencies (if they haven’t already been loaded) in the background, allowing the page to continue working while the files are being fetched. Once all dependencies are loaded,?`define`?will call the function it was given, with the interfaces of those dependencies as arguments. [](http://eloquentjavascript.net/10_modules.html#p_w7/Slpc0XV)The modules that are loaded this way must themselves contain a call to`define`. The value used as their interface is whatever was returned by the function passed to?`define`. Here is the?`weekDay`?module again: ~~~ define([], function() { var names = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; return { name: function(number) { return names[number]; }, number: function(name) { return names.indexOf(name); } }; }); ~~~ [](http://eloquentjavascript.net/10_modules.html#p_GARnQl+u0i)To be able to show a minimal implementation of?`define`, we will pretend we have a?`backgroundReadFile`?function that takes a filename and a function and calls the function with the content of the file as soon as it has finished loading it. ([Chapter 17](http://eloquentjavascript.net/17_http.html#getURL)?will explain how to write that function.) [](http://eloquentjavascript.net/10_modules.html#p_xNPCNpRiIX)For the purpose of keeping track of modules while they are being loaded, the implementation of?`define`?will use objects that describe the state of modules, telling us whether they are available yet and providing their interface when they are. [](http://eloquentjavascript.net/10_modules.html#p_/Unllb03Bv)The?`getModule`?function, when given a name, will return such an object and ensure that the module is scheduled to be loaded. It uses a cache object to avoid loading the same module twice. ~~~ var defineCache = Object.create(null); var currentMod = null; function getModule(name) { if (name in defineCache) return defineCache[name]; var module = {exports: null, loaded: false, onLoad: []}; defineCache[name] = module; backgroundReadFile(name, function(code) { currentMod = module; new Function("", code)(); }); return module; } ~~~ [](http://eloquentjavascript.net/10_modules.html#p_r9NqByjA7c)We assume the loaded file also contains a (single) call to?`define`. The`currentMod`?variable is used to tell this call about the module object that is currently being loaded so that it can update this object when it finishes loading. We will come back to this mechanism in a moment. [](http://eloquentjavascript.net/10_modules.html#p_lX37OjlA5W)The?`define`?function itself uses?`getModule`?to fetch or create the module objects for the current module’s dependencies. Its task is to schedule the`moduleFunction`?(the function that contains the module’s actual code) to be run whenever those dependencies are loaded. For this purpose, it defines a function?`whenDepsLoaded`?that is added to the?`onLoad`?array of all dependencies that are not yet loaded. This function immediately returns if there are still unloaded dependencies, so it will do actual work only once, when the last dependency has finished loading. It is also called immediately, from`define`?itself, in case there are no dependencies that need to be loaded. ~~~ function define(depNames, moduleFunction) { var myMod = currentMod; var deps = depNames.map(getModule); deps.forEach(function(mod) { if (!mod.loaded) mod.onLoad.push(whenDepsLoaded); }); function whenDepsLoaded() { if (!deps.every(function(m) { return m.loaded; })) return; var args = deps.map(function(m) { return m.exports; }); var exports = moduleFunction.apply(null, args); if (myMod) { myMod.exports = exports; myMod.loaded = true; myMod.onLoad.forEach(function(f) { f(); }); } } whenDepsLoaded(); } ~~~ [](http://eloquentjavascript.net/10_modules.html#p_T+RexzI7A0)When all dependencies are available,?`whenDepsLoaded`?calls the function that holds the module, giving it the dependencies’ interfaces as arguments. [](http://eloquentjavascript.net/10_modules.html#p_8Neb8ba81Q)The first thing?`define`?does is store the value that?`currentMod`?had when it was called in a variable?`myMod`. Remember that?`getModule`, just before evaluating the code for a module, stored the corresponding module object in`currentMod`. This allows?`whenDepsLoaded`?to store the return value of the module function in that module’s?`exports`?property, set the module’s?`loaded`property to true, and call all the functions that are waiting for the module to load. [](http://eloquentjavascript.net/10_modules.html#p_KBR+VgwyVz)This code is a lot harder to follow than the?`require`?function. Its execution does not follow a simple, predictable path. Instead, multiple operations are set up to happen at some unspecified time in the future, which obscures the way the code executes. [](http://eloquentjavascript.net/10_modules.html#p_uewjoUxlIw)A real AMD implementation is, again, quite a lot more clever about resolving module names to actual URLs and generally more robust than the one shown previously. The?*RequireJS*?([*requirejs.org*](http://requirejs.org/)) project provides a popular implementation of this style of module loader. ## [](http://eloquentjavascript.net/10_modules.html#h_4266RdeHYR)Interface design [](http://eloquentjavascript.net/10_modules.html#p_IUZ7uTWwwd)Designing interfaces for modules and object types is one of the subtler aspects of programming. Any nontrivial piece of functionality can be modeled in various ways. Finding a way that works well requires insight and foresight. [](http://eloquentjavascript.net/10_modules.html#p_KweUtWCb7f)The best way to learn the value of good interface design is to use lots of interfaces—some good, some bad. Experience will teach you what works and what doesn’t. Never assume that a painful interface is “just the way it is”. Fix it, or wrap it in a new interface that works better for you. ### [](http://eloquentjavascript.net/10_modules.html#h_D19q+FXBVd)Predictability [](http://eloquentjavascript.net/10_modules.html#p_2adqTW0fxP)If programmers can predict the way your interface works, they (or you) won’t get sidetracked as often by the need to look up how to use it. Thus, try to follow conventions. When there is another module or part of the standard JavaScript environment that does something similar to what you are implementing, it might be a good idea to make your interface resemble the existing interface. That way, it’ll feel familiar to people who know the existing interface. [](http://eloquentjavascript.net/10_modules.html#p_6l6v5cakoT)Another area where predictability is important is the actual?*behavior*?of your code. It can be tempting to make an unnecessarily clever interface with the justification that it’s more convenient to use. For example, you could accept all kinds of different types and combinations of arguments and do the “right thing” for all of them. Or you could provide dozens of specialized convenience functions that provide slightly different flavors of your module’s functionality. These might make code that builds on your interface slightly shorter, but they will also make it much harder for people to build a clear mental model of the module’s behavior. ### [](http://eloquentjavascript.net/10_modules.html#h_+NeFt8aXxf)Composability [](http://eloquentjavascript.net/10_modules.html#p_9Nt/796F0G)In your interfaces, try to use the simplest data structures possible and make functions do a single, clear thing. Whenever practical, make them pure functions (see?[Chapter 3](http://eloquentjavascript.net/03_functions.html#pure)). [](http://eloquentjavascript.net/10_modules.html#p_qicKwwcIoO)For example, it is not uncommon for modules to provide their own array-like collection objects, with their own interface for counting and extracting elements. Such objects won’t have?`map`?or?`forEach`?methods, and any existing function that expects a real array won’t be able to work with them. This is an example of poor?*composability*—the module cannot be easily composed with other code. [](http://eloquentjavascript.net/10_modules.html#p_XJefBK7ici)One example would be a module for spell-checking text, which we might need when we want to write a text editor. The spell-checker could be made to operate directly on whichever complicated data structures the editor uses and directly call internal functions in the editor to have the user choose between spelling suggestions. If we go that way, the module cannot be used with any other programs. On the other hand, if we define the spell-checking interface so that you can pass it a simple string and it will return the position in the string where it found a possible misspelling, along with an array of suggested corrections, then we have an interface that could also be composed with other systems because strings and arrays are always available in JavaScript. ### [](http://eloquentjavascript.net/10_modules.html#h_vguoN2JlWc)Layered interfaces [](http://eloquentjavascript.net/10_modules.html#p_gVRzuTdJxo)When designing an interface for a complex piece of functionality—sending email, for example—you often run into a dilemma. On the one hand, you do not want to overload the user of your interface with details. They shouldn’t have to study your interface for 20 minutes before they can send an email. On the other hand, you do not want to hide all the details either—when people need to do complicated things with your module, they should be able to. [](http://eloquentjavascript.net/10_modules.html#p_UAqdlcM0M6)Often the solution is to provide two interfaces: a detailed?*low-level*?one for complex situations and a simple?*high-level*?one for routine use. The second can usually be built easily using the tools provided by the first. In the email module, the high-level interface could just be a function that takes a message, a sender address, and a receiver address and then sends the email. The low-level interface would allow full control over email headers, attachments, HTML mail, and so on. ## [](http://eloquentjavascript.net/10_modules.html#h_ErccPg/l98)Summary [](http://eloquentjavascript.net/10_modules.html#p_hGwRhRocwV)Modules provide structure to bigger programs by separating the code into different files and namespaces. Giving these modules well-defined interfaces makes them easier to use and reuse and makes it possible to continue using them as the module itself evolves. [](http://eloquentjavascript.net/10_modules.html#p_G2usOklg33)Though the JavaScript language is characteristically unhelpful when it comes to modules, the flexible functions and objects it provides make it possible to define rather nice module systems. Function scopes can be used as internal namespaces for the module, and objects can be used to store sets of exported values. [](http://eloquentjavascript.net/10_modules.html#p_0LAk7BPgRr)There are two popular, well-defined approaches to such modules. One is called*CommonJS Modules*?and revolves around a?`require`?function that fetches a module by name and returns its interface. The other is called?*AMD*?and uses a`define`?function that takes an array of module names and a function and, after loading the modules, runs the function with their interfaces as arguments. ## [](http://eloquentjavascript.net/10_modules.html#h_TcUD2vzyMe)Exercises ### [](http://eloquentjavascript.net/10_modules.html#h_Ft63zbY95i)Month names [](http://eloquentjavascript.net/10_modules.html#p_dU0pnoSPR9)Write a simple module similar to the?`weekDay`?module that can convert month numbers (zero-based, as in the?`Date`?type) to names and can convert names back to numbers. Give it its own namespace since it will need an internal array of month names, and use plain JavaScript, without any module loader system. ~~~ // Your code here. console.log(month.name(2)); // → March console.log(month.number("November")); // → 10 ~~~ ### [](http://eloquentjavascript.net/10_modules.html#h_3j/KaVGNV2)A return to electronic life [](http://eloquentjavascript.net/10_modules.html#p_+royQ52RxC)Hoping that?[Chapter 7](http://eloquentjavascript.net/07_elife.html#elife)?is still somewhat fresh in your mind, think back to the system designed in that chapter and come up with a way to separate the code into modules. To refresh your memory, these are the functions and types defined in that chapter, in order of appearance: ~~~ Vector Grid directions directionNames randomElement BouncingCritter elementFromChar World charFromElement Wall View WallFollower dirPlus LifelikeWorld Plant PlantEater SmartPlantEater Tiger ~~~ [](http://eloquentjavascript.net/10_modules.html#p_qH0Xj8v2nH)Don’t exaggerate and create too many modules. A book that starts a new chapter for every page would probably get on your nerves, if only because of all the space wasted on titles. Similarly, having to open 10 files to read a tiny project isn’t helpful. Aim for three to five modules. [](http://eloquentjavascript.net/10_modules.html#p_fDzWqQqyw8)You can choose to have some functions become internal to their module and thus inaccessible to other modules. [](http://eloquentjavascript.net/10_modules.html#p_XYYo0/YDOl)There is no single correct solution here. Module organization is largely a matter of taste. ### [](http://eloquentjavascript.net/10_modules.html#h_E/zWqBFdy8)Circular dependencies [](http://eloquentjavascript.net/10_modules.html#p_/LVNV6+2SH)A tricky subject in dependency management is circular dependencies, where module A depends on B, and B also depends on A. Many module systems simply forbid this. CommonJS modules allow a limited form: it works as long as the modules do not replace their default?`exports`?object with another value and start accessing each other’s interface only after they finish loading. [](http://eloquentjavascript.net/10_modules.html#p_BFm3QczrDZ)Can you think of a way in which support for this feature could be implemented? Look back to the definition of?`require`?and consider what the function would have to do to allow this. > The trick is to add the exports object created for a module to require's cache before actually running the module. This means the module will not yet have had a chance to override module.exports, so we do not know whether it may want to export some other value. After loading, the cache object is overridden with module.exports, which may be a different value. > But if in the course of loading the module, a second module is loaded that asks for the first module, its default exports object, which is likely still empty at this point, will be in the cache, and the second module will receive a reference to it. If it doesn’t try to do anything with the object until the first module has finished loading, things will work.
亚洲精品熟女中文字幕| 亚洲欧美av在线观看| 精品人妻一区二区三区人妻视频| 色播五月激情四射| 亚洲成人日韩丶av| 日本av都有哪些系列| 五月天色婷婷av在线| 欧洲av偷拍亚洲av偷拍| 亚洲欧美日韩偷拍综合| 久操免费福利在线视频观看视频| 久久精品视频在线国国| 日韩av在线点播| 欧美人妻系列,中文字幕| 国产中文字幕在线91| 中文字幕国产在线观看| 久久久久国产精品夜夜夜| 91高级会所在线播放| 麻豆中文字幕av在线| 亚洲熟妇av熟妇在线| 99国产在线拍91揄自揄视| 十八禁久久久久久久久久久久久久| 亚洲天堂黄色免费| 久久久久久人妻无码| 精品欧美乱子伦一区二区三区 | 亚洲欧美日韩一二三四五六七区| 精品日韩色国产在线观看| av成人教育在线播放| 日韩欧美三级一区二区在线观看| 玖玖玖玖日在线视频| ass日本丰满熟妇pics| 亚洲av微乳在线| 高潮久久久久久久av免费| 日韩少妇视频在线直播| 综合激情伊人久久| 日韩欧美 国产精品| 亚洲av色图com| 亚洲 欧美 制服 人妻| sepapa自拍偷拍| 国产剧情高清在线观看| 亚洲精品久久久久久无几年桃| 中文字幕av最新资源| 一区二区三区内射美女毛片| 欧美老熟妇重口另类xxx| 日韩av电影在线观看的| 真实玩弄白嫩丰满人妻少妇三级| 高清视频在线观看一区二区三区| 国产成人精品视频免费网站| 免费精品国产日韩热久久| 亚洲天堂网av中文字幕| 久久成人福利视频资源| 国产三级久久久999111| 日本18禁片免费久久| 国产精品久久久久久久久久网站| 日韩人妻插舔激情午夜| 久久视频黄色观看网站| 亚洲欧美日韩一二三四五六七区| 亚洲情欲大片在线观看| 伊人久久婷婷av| 天天色天天干天天舔| 午夜精品久久久久久久久二区三区 | 少妇惨叫久久久久久久| 欧美日韩成人精品视频| 91精品久久久久久五月天| 日韩av在线观看卡一卡| 国产乱人妻精品久久久| 一级片一级片久久精品电影网电影 | 青青91免费视频| 中文国产成人精品久久一| 亚洲五月婷婷激情图片| 久久久精品99国产国产精| 日本高清不卡视频在线播放| 丰满人妻一区二区三区av| 国语一区二区在线观看| 久久久久久久黄色午夜精品| 亚洲一线产区二线产区区| av日韩在线免费观看网站| 中文字幕人妻一区二区在线看| 欧美三级中文字幕久久精品| 性欧美另类sex极品free| 先锋资源站中文字幕| 十八禁久久久久久久久久久久久久| 亚洲欧洲国产一区二区| 色噜噜狠狠躁夜夜躁| 麻豆丝袜美女人妻中文| 成人av激情网一区二区三区| 天天日天天干天天色| 亚洲情色av网站| 精品国产久久久久99| 91麻豆精品91久久久久同性| 日韩av电影免费在线播放| 大香蕉久草网一区二区三区| 久久精品人妻中文字幕一区| 亚洲一级av大片| 日韩精品综合视频在线| 久久视频这里都是精品| 自拍偷拍 亚洲 在线| 日韩在线免费视频精品| 久久草免费在线视频| 日韩美女夜夜爽av| 蜜桃视频在线观看一区精品| 亚洲成人av久久久久| 人妻夜夜爽天天爽麻豆| 亚洲av狠狠地操你| 日韩中文字幕在线网站| 影音在线精品免费国产资源| 久久人人爽爽人人爽av| 婷婷亚洲免费基地| 99久久999久久久精品综合| 日韩不卡一级成人免费视频| 国产精品久久久久久久漫画| 精品蜜臀久久久久抄底| 亚洲av色图com| 99re在线精品国产欧美久久 | 色婷婷精品午夜在线播放| 久久国产精品人妻酒店| 亚洲中文字幕成人久久| 日韩在线中文字幕不卡| 搡老熟女一区二区三区四区视频| 香蕉久久a v一区二区三区| 国产精品欧美日韩五月香蕉| 少妇人妻成人在线| 久久亚洲 欧美 综合aⅴ| 久久伊人亚洲综合网| 蜜臀av 麻豆av| 少妇人妻成人在线| 亚洲欧美国产另类91综合| 日韩 美女 在线观看| 日韩一区二区三区水蜜桃| 日本av男优巧克力| 国产乱人妻精品久久久| 亚洲国产精品综合久久2007| 日本中文国产字幕| 999精品插丰满少妇人妻| 香蕉久久a v一区二区三区| 亚洲男人天堂久久| 牛牛成人手机视频在线| 久久国产精品人妻酒店| 成人免费av在线网站| 国产99精品久久久久久圆免看片| 999热精品在线观看| 四虎网站免费av| 亚洲欧美丝袜精品久久直播| 精品日韩偷拍欧美另类| 国产精品久久久久久久久久网站| 91丝袜放荡丝袜脚交| 又粗又猛又爽黄老大爷视频| 日韩美女在线视频一区| 日韩精品少妇人妻熟女| 国产 欧美 日韩 视频| 老熟女17页一91| 美女免费一二三区视频| 久久视频在线免费播放| 91超碰熟女在线97| 精品国产久久久久蜜臀| 亚洲第一黄色天堂| 午夜国产福利电影| 97色视频在线看视频| 一本久久久久久久18| 少妇激情视频一区二区| 日韩中文字幕在线综合网| 久久久久国产亚洲av麻豆| 日本中文国产字幕| 天天操,天天干,天天| 99久久精品国产777| 精品久久久久久亚洲国产999| 亚洲欧美自拍偷拍在线观看| 91一区二区精品在线| 精品国产麻豆免费成人网| 欧美日韩人妻久久精品| 夜夜撸日日撸夜夜爽日日干| 三级亚洲天堂亚洲天堂| 日韩人妻插舔激情午夜| 国产精品久久精品一区二区三区| 久久久久久久久久性| 人妻丰满精品一区二区三区| 午夜无人影视在线| 亚洲天堂黄色免费| 国产精品男人的天堂999| 久久精品视频在线国国| 精品国产一区二区三区无码蜜桃| 另类h小视频在线观看| 人人妻人人澡人人爽国产一区| 久久精品琪琪男人的天堂| 午夜精品久久久久久久久二区三区 | 亚洲国产精品成人精品软件| 亚洲欧美自拍偷拍在线观看| 欧美熟妇精品在线观看| 中文字幕版婷婷久久| 亚洲久久久久久久人妻| 久久久亚洲精品久久仙| 99精品视频69v精品视频| 久久久久久久精品综合| 日本东京热天天日天天干| www.199麻豆在线视频| 一级久久久久久久18| 久久久久久久夜精品精品| 亚洲综合精品久久| 日韩大全毛片免费观看视频| 中文字幕亚洲资源天堂| 日韩不卡一级成人免费视频| 国产天堂avwww| 9久热这里有国产精品| 日韩尤物人妻av在线网| 67914熟女在线观看| 国产又大又猛又黄的视频| 99久久精品国产777| 国产+日本+欧美在线观看| 欧洲美女黑人粗性暴交视| 亚洲女人中文字幕在线| 最新美女激情av| 在线国产小视频麻豆| 高清一区二区三区日本4| 日本中文字幕久久免费精品| 97偷拍视频在线观看| 中文字幕 日本伊人| 国产美女深喉口爆吞精免费| 91麻豆精品91久久久久同性| 日日日日日夜夜夜夜| 亚洲国产精品五月天久久久| 天天操,天天干,天天| 国产成人精品久久久久久蜜臀| 日韩在线啊啊啊的视频| 少妇惨叫久久久久久久| 日韩国产91综合精品| av日韩中文字幕人妻| 亚洲 免费在线视频| 久久伊人精品青青草原| 色综合久久久久久久久| 欧美爱情动作片在线一区| 99久久久99久久91熟女| 久久视频一区二区三| 欧美日韩精品一区电影| 在线观看日韩美视频一区| 亚洲自拍偷拍色图区| 超碰在线免费成人午夜剧场97| 91精品乱码久久久久久| 国语黄色淫秽录像带| 日韩有码在线免费观看视频| 欧美一区二区三区成人免费看 | 欧美中文字幕久久久| 久久激情毛片大放送| 高清一区二区三区日本4| 亚洲少妇黄色一级片| 骚妻少妇一区二区| 一区,二区,三区视频| 青青草久久大香蕉| 国产一区二区免费五遮挡| 日韩亚洲丝袜系列| 国产精品综合手机在线| 亚洲国产aⅴ精品一区二区欧美| 中文字幕成人资源网站 | 精品一区二区三区蜜桃臀的优势| 午夜无人影视在线| 乱女乱妇熟女熟妇综合站| 久久蜜桃视频亚洲精品| 亚洲伊人网在线播放| 色婷婷一区二区三区四区五| 亚洲伊人网在线观看| 蜜臀av久久久久av蜜臀| 久久在线人妻熟女高清完整版| 篠田优中文字幕在线播| 瑟瑟网站免费观看| 91精品欧美久久久久视频| 国产69tv精品久久| 麻豆精品123在线观看| 人人妻人人澡人人爽国产一区 | a级黄片在线免费观看| 亚洲 免费 在线 观看| 99精品视频69v精品视频| 中文字幕久久91| 亚洲天堂av电影| 最新偷窥偷拍免费视频观看| 青青草国产福利视频| 欧美一区二区三区,| 精品999久久久一免费ww| 天天插天天日天天舔| 五月综合缴情婷婷六月| 青青草成人影院在线观看| 日韩av手机在线电影| 精品久久中文字幕系列| 久久久96精品久久久| 影音在线精品免费国产资源| 国产青青91av在线视频| 国产精品一区二区三区福利| 精品国产一区二区三区无码蜜桃| 之久精品一区二区| 久久久久久久久久久久久丰满| 激情五月天狠婷婷| 日本久久久大片中文字幕| 亚洲欧洲黄色图区| 中文字幕久久91| 先锋资源站中文字幕| 久久亚洲熟妇中文字幕| 97人妻中文字幕精品视频| 午夜在线看1000集| 久久国产精品久久伊人麻豆 | 99精品高清视频一区二区| 亚洲一区二区三区久久aa| 久久亚洲精品日韩高清| 中文字幕在线有码二区| 天天做天天舔天天射| 中文字幕人妻一区二区在线看| 国产精品99久久电影| 亚洲天堂网av中文字幕| 91久久亚洲成人精品| 欧美日韩精品在线观看免费 | 人人妻人人爱碰千| 高清中文字幕乱码在线| 天天插天天日天天舔| 人人狠狠久久综合网| 日韩欧美三级一区二区在线观看| 久久久久久少妇被弄高潮| 亚洲日本韩国欧美一起| 亚洲国产精品成人精品软件| 精品久久中文字幕系列| 精品国产精品视频免费在线观看| 精品人妻一区二区三区√| 久久2020精品免费网站| 黄色片一级美女黄色片| 日韩av在线不卡网站| 日本加勒比中文字幕久久| 91丝袜放荡丝袜脚交| 欧美日韩精品欧美日韩| 久久久久女优免费视频| 久久视频这里都是精品| 日韩av在线观看免费看看| 亚洲一线产区二线产区区| 亚洲成a人片,77777| 人妻一区二区中文字幕在线| 亚洲 免费在线视频| 少妇人妻成人在线| 日韩美女主播人体视频自拍首页 | 久久九特黄的免费大片| 人妻熟女视频免费观看| 国产日韩欧美春色另类小说| 视频一区视频二区三区| 国产剧情高清在线观看| 日韩欧美国产成人一区| 欧美日韩国产一级一顶级| 大香蕉影视日本大香蕉97| 亚洲青青青国产观看视频| 无码人妻精品一区二区三区久久| 亚洲精品久久第一页| 日韩欧美颜色渔网| 狠狠干中文字幕97视频| 少妇人妻一区2区中文字幕| 欧美激情电影在线观看不卡| 久久久精品蜜桃在线| 久久久久国产亚洲av麻豆| 欧美一区二区三区成人久久片 | 日韩av在线不卡网站| 日韩在线啊啊啊的视频| 牛牛成人手机视频在线| 日韩高清av一区| 五月爱婷婷六月丁香性| 91老司机免费福利| 激情婷婷综合久久五月天| 欧洲av偷拍亚洲av偷拍| 91制片在线观看视频| 日韩欧美亚州综合久久| 激情一区日韩一区欧美一区 | 欧美激情电影在线观看不卡| 国产精品福利久久久久久久| 久久久亚洲在线视频| 亚洲国产欧美激情图区| 久久97久久免费视频| 久久亚洲AV成人无码| 性欧美另类sex极品free| 久久久久国产亚洲av麻豆| 中文字幕日韩久久精品tv| 欧美性久久久久久久久久久| 福利日韩精品中文字幕专区| 高清一区二区日韩视频精品| 国产无av码在线观看| 亚洲熟妇av熟妇在线| 伊人久久婷婷av| 91人妻露出精品在线| 日韩中文字幕在线综合网| 麻豆网站在线免费看| 国产无av码在线观看| 福利日韩精品中文字幕专区| 亚洲欧美日产人妻| 欧美性久久久久久久久久久| 青草青草视频免费2在线观看 | www日本不卡一二三区| 人妻中文字幕一二三区| 蜜臀av久久久久av蜜臀| 国产 另类 在线 欧美日韩| 亚洲熟妇在线观看一区二区| 亚洲久久精品午夜| 蜜臀av一区二区三区人妻少妇| 午夜探花在线免费观看| 亚洲国产精品国自产拍av麻豆| 91制片在线观看视频| 色婷婷综合免费在线视频| 日韩av网址在线播放| 日韩黄色一级大片| 亚洲人妻中文字幕av首页| 免费精品国产日韩热久久| 国产精品色呦呦视频免费看| 久久伊人亚洲综合网| 国产a级片免费在线观看| 亚洲一区视频大全| 337p亚洲精品色噜噜| 91嫩草17c欧美国产| 综合激情伊人久久| 久久视频一区二区三| 99日本亚洲精品视频| 五月天丁花香婷婷| 国产精品色呦呦视频免费看| 青青青在线视频自拍| 国产一区二中文字幕在线免费观看| 日韩一区二区三区水蜜桃| 1024 国产高清の最新合集| 91免费av在线观看| 人人妻人人澡人人爽国产一区| 国产精品99久久电影| 国产精品综合手机在线| 蜜臀久久99精品久久久久久久久| 高清不卡av在线网| 国产欧美日韩不卡在线观看| 成人黄片av在线播放| 国产精品福利久久久久久久| a级黄片在线免费观看 | 亚洲成a人片,77777| 欧美日韩人妻久久精品| 久久综合久久综合久久色| 初撮日本五十路人妻| 热香蕉和冷香蕉功效一样吗| 亚洲 自拍偷拍 欧美| 精品国产一区二区三区制服| 日韩av网址在线播放| 亚洲香蕉av电影| 日韩av电影com| 中文字幕熟女人妻在线观看| 五月婷婷激情四射综合网| 欧美一区二区三区激情啪啪啪| 67914熟女在线观看| 亚洲一区视频大全| 日韩av中文网址| 日韩有码视频在线免费观看| 国产精品男人的天堂999| 欧美一区二区理论片在线观看 | 亚洲天堂av电影| 成年人在线免费观看黄色片| 在线中文免费黄色| 亚洲制服高清中文字幕| 91啪啪啪内射网站| 国产成人一区二区三区在线视频| aaaaa亚洲电影| 日韩在线播放视频1区| 久久久久久久精品综合| 91精品乱码久久久久久| 精品久久久久久18免费网站| 91免费av在线观看| 天天色天天日天天操| 国产欧美日韩亚洲另类第一第二页 | 欧美成人黄色一区二区三区| 四虎国产精品久久免费精品| 亚洲aⅴ欧美综合一区二区三区| 欧美精品一区二区在线视频| 麻豆亚州av熟女国产一区二| 久久久久久久久久久久久熟女a∨| 一级片一级片久久精品电影网电影| 美国av 在线播放| 精品无码久久久久久毛片| 国产欧美日韩精品专区黑人 | 亚洲欧洲黄色图区| 色综合色综合色综合久久| 香蕉在线蕉久在线| 黑人操日本女人电影| 国产日韩欧美成人一二三区| 91久久婷婷国产麻豆精品| 久操免费福利在线视频观看视频| 91精品人妻一区二区三区四区| 精品久久精品久久久久| jizzhd国产剧情| 精品aa级中文字幕人妻| 日本女同性恋视频| 免费看久久久久久久性大片| 国产69tv精品久久| 真实玩弄白嫩丰满人妻少妇三级| 国产乱人妻精品久久久| 秋霞电影韩国一区二区二区三区| 精品美女1区2区3区| 国产乱人妻精品久久久| 国产熟女高潮av77777| av色香蕉一区二区三区| 91精品一二三区在线观看| 国产91久久久久久久| 人妻丰满一区二区三区| 天天干天天天天射天天操| 日本中文国产字幕| 日韩一区二区三区水蜜桃| 亚洲国产一成人久久精品| 999精品插丰满少妇人妻| 亚洲第一黄色天堂| 亚洲欧美在线视频播放| 欧美人妻a∨中文字幕在线| 99久久精品国产777| 欧美日韩精品亚洲欧美| 成人精品1024欧美日韩| 亚洲激情视频在线视频| 天天操,天天干,天天| 亚洲制服欧美丝袜| 一级久久久久久久18| 色亚洲天堂色派对欧美色| 久久五月婷婷综合视频| 91影视一区二区三区| 欧美激情 另类视频 亚洲| 精品999久久久一免费ww| 2020中文字幕在线看电影| 久久精品国产av网| 国产91熟女免费视频| 亚洲欧美日韩一区17c| 日韩精品久久久久久久软件| 国产欧美日韩不卡在线观看| 一本一道久久a久久久| 91人妻人人澡.人人精品| 香蕉久久久久久久久久久久女| 综合久久综合久久综合久久| 日韩一区二区三区水蜜桃| 91麻豆精品91久久久久同性| 熟女人妻之中文字幕| 99九九99九九热视频| 99爱99久久久久久久久久| 日韩中文字幕理伦| 综合激情伊人久久| 欧美熟女高清视频一区二区| 久久午夜福利电影免费试看| 婷婷激情五月天图片| 人人狠狠久久综合网| 精品蜜臀久久久久抄底| 精品国产久久久久99| 狠狠久久综合丁香777米奇| 日韩电影黄色免费| 免费人妻一区二区三区免费视频| 91精品国产综合久久久久久粉嫩| 先锋资源站中文字幕| 国产成AV人片在线观看天堂无码 | 久久久久久精品日韩| 久久精品国产亚洲av久丨| 日韩av电影com| 思思久久国产精品视频| 天天日天天干一道一小| 91精品国产综合久久久久久粉嫩| 欧美激情电影在线观看不卡| 久久久久国产麻豆婷婷| 日韩欧美不卡一区二区三区五区| 亚州av一区二区三区.| 国产91在线播放精品| 精品久久久久久999| 亚洲成人影院中文字幕| laoyawo老鸭窝在线视频| 日韩久久久三级电影| 91精品久久久久久五月天| 国产 日韩 欧美 日本| 亚洲丰满熟妇乱xxxxx| 亚洲精品一区二区三区丝袜| 国产乱子伦视频免费| 久久人人爽爽人人爽av| 色播五月激情四射| 亚洲国产精品午夜av| 日韩av在线天堂| av激情网站在线观看| 国产乱子伦视频免费| 日韩美女主播人体视频自拍首页| 日韩二区不卡视频| 欧美精品一区二区三区蜜臀| 91九色porny国产视频| 少妇人妻一区2区中文字幕| 成人午夜激情福利片| aaa久久久久久久久久网站| 久久久精品欧美一区二区国产| 青青青手机版视频在线看| 国产精品一区二区亚瑟不卡| 中文字幕亚洲专区欧美| 久久五月天天婷婷激情综合| 日韩av在线不卡网站| 亚洲女人老师毛茸茸| 蜜臀av一区二区三区人妻少妇| 欧美日本韩国乱搞视频| 人妻中出视频一区二区| 麻豆视传媒官网直接进入免费观看| 五月天丁香婷婷国产| 日韩中文字幕视频在线播放| 国产91久久久久久久| 日本久久久大片中文字幕| 亚洲av电影在线一区二区| av在线免费在线观看av| 亚洲视频欧美视频另类| 精品国产麻豆免费成人网| 亚洲 免费在线视频| 日韩在线中文字幕不卡| 亚洲国产精品五月天久久久| 久久精品香蕉绿巨人| 婷婷午夜美女诱惑福利电影网| 亚洲国产精品午夜av| 日韩av在线观看卡一卡| 亚洲日韩视频高清在线观看| 日韩欧美 国产精品| 亚洲综合成人久久av| 日韩av电影com| 99精品高清免费在线视频| 日韩av电影免费在线播放| 欧美中文字幕在线一区| 少妇人妻视频在线观看| 日本黄色成年视频| 色播网站在线播放| 欧美自拍 亚洲偷拍| 蜜桃视频在线观看一区精品| 高清一区二区日韩视频精品| 欧美日韩亚洲国产ay| 国产精品日韩欧美综合| 97国产人妻换人妻| 日韩久久久三级电影| 又粗又猛又爽黄老大爷视频| 麻豆成人在线免费观看视频| 久久五月婷婷综合视频| 高清中文字幕乱码在线| 精品国产乱码久久久人妻| 少妇高潮一区二区三区99欧美| 国产欧美精品久久无广告| 久久亚洲精品日韩高清| 一级久久久久久久18| 人妻熟 中文字幕| 日韩av午夜精品| 素人阁久久久久精品人妻| 在线人妻国产精品| 热热久久这里只有精品| 91插插插操美女视频| 亚洲成人日韩丶av| 久久久久久网站精品免费| 一本大道av伊人久久综合| 精品日韩偷拍欧美另类| 五月婷久久综合狠狠爱97| 中文字幕av最新在线| 福利精品视频免费观看| 精品久久久久久18免费网站 | 性欧美另类sex极品free| 国产精品成人av麻豆| 久久久久久最新精品| 蜜臀av 麻豆av| 日韩中文字幕一区二区三区四区| 久久这里只有欧美精品| 亚洲欧美av在线观看| 婷婷亚洲免费基地| 欧美日韩少妇一二三| 99精品中文字幕在线视频| 亚洲最黄色的视频| 久久久久久人妻无码| 久久久久国产精品夜夜夜| 日日碰狠狠躁久久躁一区二区| 亚洲国产精品国自产拍av麻豆| 亚洲图色91东京热| 精品国产乱码久久久久夜深 | 人妻丰满精品一区二区三区| 国内精品久久久久久久久久清纯 | 视频在线观看黄页| 欧美一区二区三区视频午夜| 又爽又黄的免费视频91| 208精品福利导航| 在线观看色有小视频| 蜜臀av一区二区三区人妻少妇| 人妻精品一区二区在线播放| 日韩毛片亚洲av| 亚洲五月婷婷激情图片| 久久av一区中文字幕| 91麻豆免费国产在线| 综合久久综合久久综合久久| 亚洲欧洲黄色图区| 美日韩美女三级电影| 久久国产精品久久伊人麻豆| 日本精品久久久久中人妻| 成人免费观看av毛片| 国产清纯白嫩美女无套| 久久久九九九九九精品6| 在线人妻国产精品| 清纯唯美激情五月| 久久激情毛片大放送| 少妇人妻成人在线| 久久久久久久久久久久久丰满| 婷婷 少妇 av| 五月天丁花香婷婷| 少妇人妻视频在线观看| 成人免费观看av毛片| 麻豆免费国产福利免费国产福利| 青草青草视频免费2在线观看| 久久精品美国亚洲av伦理| 国产日韩亚洲大尺度高清 | 制服丝袜亚洲欧美第一| 久久 99 精品视频| 精品久久久久久亚洲国产999| 熟女激情一区二区三区| 日韩高清av一区| 色图av亚洲综合| 草裙成人精品一区二区三区| 日日日日日夜夜夜夜| 日韩高清av一区| 欧美精品一区二区三区蜜臀| 中文字幕av久久爽爽| 久久在线人妻熟女高清完整版| 日本18禁片免费久久| 日韩电影黄色免费| 日韩欧美一级在线视频| 五月综合缴情婷婷六月| 亚洲欧美自拍偷拍在线观看| 久久久国产精品尤物av| 亚洲一区视频大全| 天天操天天干天天妻| 安斋拉拉中文字幕在线| 青青草久久大香蕉| 色男人天堂东京热| 亚洲视频欧美视频另类| 成人黄视频在线播放| 亚洲一级av大片| 亚洲 欧洲 日韩 人妻| 日韩在线中文字幕不卡| 日韩在线观看免费全集网站| 五月综合缴情婷婷六月| 欧美日韩国产一区二区三区免费| 色yeye香蕉凹凸人妻三区| 亚洲熟妇免费在线视频| 91一区二区精品在线| 初撮日本五十路人妻| 成人黄视频在线播放| 久久午夜福利电影免费试看| 99精品视频在线看17| 91精品久久久久久五月天| wwxxx中文字幕| 天天在线天天综合网色| 婷婷亚洲天堂中文字幕| 欧美一区二区性久久久| 欧美一级黄片视频看看| 91在线观看视频,| 清纯唯美激情亚洲综合另类| 欧美日韩国产综合aⅴ| 久久传奇网站一区三区视频| 久久爱免费视频16| 久久精品久久一区二区三区| 另类蜜桃刺激视频在线观看| 国产精品欧美日韩五月香蕉| 99免费观看视频在线| 中文字幕理伦福利片| 日韩欧美久久免费观看| 99精品高清免费在线视频| 欧美精品人妻丝袜一区| 亚洲另类色区欧美日韩| 亚洲午夜电影久久久| 中文字幕亚洲中文字幕| 日本vs欧美一区二区三区| 国产精品色呦呦视频免费看| 国产精品综合手机在线| 天天在线天天综合网色| 免费a级电影在线观看| 中文字幕在线视频亚洲| 97cao瑟瑟在线观看| 亚洲五月婷婷激情图片| 亚洲尺码和欧洲尺码av| 久久久久久久久久久久久丰满| 久久久久久精品国产成人| 中文在线字幕a在线| 蜜臀av一区二区三区人妻少妇| 国产精品久久久久久xxx| 真实玩弄白嫩丰满人妻少妇三级| 国产精品福利久久久久久久| 久久蜜桃视频亚洲精品| 国产成人一区二区三区在线视频| 国产+日本+欧美在线观看| 国产一区二区视频大全床| 91一区二区精品在线| 天天操天天爽天天舔天天操一操| 少妇高潮喷水久久久久久桃花| 午夜影院av在线| 玖玖资源站中文字幕一区二区 | 国产麻豆一级美女精品| 亚洲乱精品中文字字幕| 日韩av在线观看卡一卡| 一区二区三区内射美女毛片| 天天日天天干一道一小| 99热精品国产影视久久久影院| 日韩av电影com| 2020日本中文字幕| 日韩中文字幕有码人妻在线| 一区,二区,三区视频| 9久热这里有国产精品| 综合久久综合久久综合久久| 91在线观看视频,| 91国产视频网站在线观看| 欧美亚洲av日韩综合一区| 少妇高潮一区二区三区99欧美 | 日本中文字幕久久免费精品| 美女差点操死在线观看| 人人妻人人澡人人爽dv| 色视频精品视频在线观看| 色婷婷综合免费在线视频| 5858s在线视频| 自拍偷拍亚洲欧美另类| 玖玖玖玖日在线视频| 日韩日韩av在线| 老鸭子在线观看免费播放| 欧美人妻一区二区三区在线播放| 亚洲男人五月天堂| 日韩精品刺激视频| 亚洲av综合色区手机| 日韩成人av影视在线观看| 日本a级2020在线观看| 91久久精品日日躁夜夜躁| 久久久国产一区二区视| 中文字幕日韩天堂| 久久久免费精品少妇| 日韩av在线精品观看| 色图av亚洲综合| 男人亚洲天堂2018| 3d动漫一区二区在线观看| 亚洲人妻中文字幕一区二区| 麻豆丝袜美女人妻中文| 日韩欧美久久免费观看| 日本熟妇乱子伦a片在线观看| 久久视频精彩在线观看| 日本熟妇乱子伦a片在线观看| 日韩日韩av在线| 91人妻人人澡.人人精品| 亚洲中文字幕福利视频| 国产一区二区不卡91| 18在线观看久久久麻豆| 久久精品一区二区三区人妻蜜桃| www.视频一区二区三区| 五月婷久久综合狠狠爱97| av激情网站在线观看| av蜜臀懂色啊啊啊| 天天色综合天天射综合| 麻豆丝袜美女人妻中文| 国产aⅴ爽av久久久久成| 亚洲久久精品午夜| 2020日本中文字幕| 色哟哟视频在线观看国产| 97人人人欧美人人妻人人| 五月婷婷激情狠狠| 日韩欧美颜色渔网| 欧洲美女黑人粗性暴交视| 麻豆亚州av熟女国产一区二| 日韩中文字幕在线综合网| 久久99久久com| 欧美日韩人妻久久精品| 国产精品色呦呦视频免费看 | 亚洲一级av大片| 亚洲av网站女性向在线观看| av蜜臀懂色啊啊啊| 久久久久久久免费女人体| 青青草成人影院在线观看| 97精品国产自在在线观看蜜臀| 91在线播放视频免费| 熟女激情一区二区三区| 99久久999久久久精品综合| 蜜臀av久久久久av蜜臀| 韩国女团午夜大尺度福利| 日本18禁片免费久久| 青青草国产福利视频| 日本黄页在线播放日本网站| 久久精品美国亚洲av伦理 | 国产精品色呦呦视频免费看| 亚洲国模私拍视频| 91精品久久久久久五月天| 国产视频av一区二区| 中文字幕精品久久久人妻| 嫩草一区二区三区四区中文 | 亚洲熟妇av日韩熟妇在线| 亚洲综合成人久久av| 日韩卡一卡二卡三卡四卡五| 久久精品中文字幕av| 日本中文字幕久久免费精品| 伊人久久中文字幕综合观看| 日本高清不卡视频在线播放| www.成人国产精品| 欧美日韩国产综合aⅴ| 色哟哟视频在线一区| 亚洲欧美国产另类91综合| 97精品久久人人爽人人爽| av青青草原在线观看| 国产亚洲精久久久久久无码色戒| wwxxx中文字幕| 青青青在线视频自拍| 国产91在线播放精品| 午夜寻花美女在线| 欧美精品一区二区三区蜜臀| 欧美日韩综合国产精品| 热香蕉和冷香蕉功效一样吗| 激情五月天狠婷婷| 成年人在线免费观看黄色片| 精品乱码一区二区三区四区| 另类蜜桃刺激视频在线观看| 久久国产经典三级av| 中文字幕一线一区和二区| 久久精品国产av网| 99热这里只有精品网| 亚洲阿v天堂久久| 亚洲五月婷婷视频| 欧美aⅴ一区二区三区| 午夜精品久久久久久久久二区三区| 丰满大屁股熟妇猛交xxx| 欧美熟女vides| 亚洲国产欧美激情图区| 9久久国产精品一区二区| 国产91极品身材白皙| 国产又粗又硬又长又爽视频| 99免费观看视频在线| 777亚洲精品乱码久久| 久久在线人妻熟女高清完整版| 亚洲成a人片,77777| 亚洲欧洲久久精品| 久久精品人妻中文字幕一区| 久久激情毛片大放送| 国产91久久精品一区二区老| 亚洲日本韩国欧美一起| 日韩欧美xxxx大片| 成人免费观看av毛片| 国产成人一区二区三区在线视频| 先锋男人资源中文字幕| 中文字幕一区二区三区六区9区| 欧美人妻激情中文视频| 日本久久久大片中文字幕| 亚洲 免费 在线 观看| 91久久精品日日躁夜夜躁| 综合激情伊人久久| 国产成人免费精品视频大全| 91porny国产九色| 大尺度av一区二区三区| 亚洲自拍偷拍色图区| 午夜在线看1000集| 久久久久久网站精品免费| 久久蜜臀精品一区二区| 欧美精品国产精品久久久| 精品蜜臀久久久久抄底| 日韩少妇视频在线直播| 精品人妻一区二区三区√| 午夜精品久久久久久久久二区三区 | 日韩精品少妇人妻熟女| 色婷婷综合免费在线视频| 91亚洲国产成人久久精品app| 国产亚洲av免费一区二区| 999热精品在线观看| 熟女少妇一区二区精品| 无码人妻精品一区二区三区久久| 亚洲熟妇av日韩熟妇在线| 97久久视频免费在线播放| 久久久久久少妇被弄高潮| 欧美日韩精品一区电影| 国产精品久久久久久久漫画| 日韩视频在线播放一区二区| 欧美日韩国产一区二区三区免费| 亚洲 欧洲 日韩 人妻| 国产三级久久久999111| 国产精品日韩欧美综合| 国产 日韩 欧美 日本| 麻豆精品一区在线免费观看| 天天操天天干天天做天天射| 久久午夜福利电影免费试看 | 欧美一区二区三区综合色| 91超碰免费在线播放| 91麻豆精品91久久久久同性| 日韩精品在线视频播放| 色婷婷久久久swag精品| 国产又粗又黄又大又长视频| 午夜精品福利小视频| 国产91熟女免费视频| 亚洲国产精品综合久久2007| 七十路熟女俱乐部| 亚洲av综合色区手机| 麻豆亚州av熟女国产一区二| 精品美女1区2区3区| 精品国产久久久久99| 高清视频在线观看一区二区三区 | 亚洲一区二区三区久久aa| 精品国产乱码久久久久久蜜坠欲下| 色婷婷久久久swag精品| 久久精品 中文字幕| 亚洲aⅴ欧美综合一区二区三区| 精品国产麻豆免费成人网| 亚洲女人老师毛茸茸| 欧美日韩综合国产精品| 久久久久久少妇被弄高潮| 亚洲国产精品午夜av| 91精品欧美久久久久视频| 日韩视频在线观看一区二区| 91精品一二三区在线观看| 黄色片一级美女黄色片| 亚洲图色91东京热| 国产一区无码在线桃花| 中文字幕亚洲专区欧美| 免费精品国产日韩热久久| 五月天色婷婷av在线| 欧美日韩精品一区电影| 玖玖资源站中文字幕一区二区| 日韩av一区二区三区久久久| 18久久久免费视频| www日本不卡一二三区| 国产日韩av免费一区二区三区| 在线观看日韩中文| 国产探花在线播放精品| 久久蜜桃视频亚洲精品| 欧美日韩精品综合在线一区二区| 日韩欧美一级在线视频| 久久成人福利视频资源| 熟女人妻之中文字幕| 亚洲中文字幕成人久久| 美女免费一二三区视频| 欧美日韩人妻久久精品| 日韩人妻插舔激情午夜| 精品一区二区三区四区人妻69| 日韩美女夜夜爽av| 日韩精品福利性无码专区| 久久久精品国产亚洲av网深田| 久久蜜桃视频亚洲精品| 亚洲精品图片第十八页| 欧美3d成人动漫在线| 日韩av一区中文| 久久伊人亚洲综合网| 亚洲欧美自拍偷拍在线观看| 色丁香婷婷综合久久| 精品国产精品视频免费在线观看| 亚洲精品,欧美日韩| 99热精品国产影视久久久影院| 日本av男优巧克力| 玖玖玖玖日在线视频| 新版天堂av资源在线| 91免费版下载成人| 亚洲伊人网在线观看| 日韩人妻插舔激情午夜| 久久久亚洲在线视频| 日韩欧美 国产精品| 日韩精品综合视频在线| 欧美日韩激情在线视频观看| 大香蕉久草网一区二区三区| 欧美熟女vides| 91偷拍老熟女露脸合集| 蜜臀久久99精品久久久久久久久| 草裙成人精品一区二区三区| 日韩欧美不卡一区二区三区五区| 亚洲成a人片7777| 欧美亚洲av日韩综合一区| 国语黄色淫秽录像带| 婷婷丁香花五月天| 日韩欧美三级一区二区在线观看| 色yeye香蕉凹凸人妻三区| 日产av一区二区在线观看| 精品激情视频在线免费观看| 日韩中文字幕在线网站| 99久久极品蜜桃臀精品久久| 欧美自拍 亚洲偷拍| 精品久久久久久999| 亚洲视频另类专区| 少妇高潮一区二区三区99欧美 | 欧美肥臀精品一区二区三区| 久久久久久最新精品| 精品99国内中文字幕| 色yeye香蕉凹凸人妻三区| 蜜桃精品一区二区三区在| 先锋男人资源中文字幕| 一级片一级片久久精品电影网电影 | 亚洲欧美日韩一区17c| 色综合久久999| 香蕉久久久久久久久久久久女| 人妻精品一区二区在线播放| 中文字幕亚洲专区欧美| 中文字幕一区二区三区中文字幕| 亚洲国产精品午夜av| 国产日本精品久久久久| 午夜无人影视在线| 明天我们好好过高清免费| 亚洲国产aⅴ精品一区二区欧美| 国内精品久久久久久久久久清纯| 久久久久国产麻豆婷婷| 精品欧美日韩国产在线| 9久热这里有国产精品| 亚洲激情网在线播放| 18禁成年av网站免费看| 777亚洲精品乱码久久| 精品美女1区2区3区| 中文字幕精品久久久人妻| 日韩色在线视频观看免费| 99热这里只有的精品| 人妻丰满精品一区二区三区| 国产精品一区二区三区三级| 亚洲成人日韩丶av| 中文字幕日韩天堂| 国产又粗又硬又长又爽视频| 国产剧情高清在线观看| 精品无人区一区二区三区竹菊| 欧美激情电影在线观看不卡| 99热2这里只有精品| 欧美日韩国产一级一顶级| 五月黄色激情视频| 亚洲欧洲黄色图区| 色婷婷中文字幕基地| 高清不卡av在线网| 成人精品一区一区二区看片| 欧美人妻a∨中文字幕在线 | 日本av熟女人妻| 高清中文字幕乱码在线| 亚洲最大成人网一区二区三区| 十八禁久久久久久久久久久久久久| 91人妻人人做人碰人人| 日韩a毛片视频免费看| 久久精品熟女人妻一区二区三区| 337p亚洲精品色噜噜| 日韩在线啊啊啊的视频| 日韩在线观看免费全集网站| 免费a级电影在线观看| 丰满的人妻一区七区| 亚洲欧美日韩综合专区| 91人妻人人做人碰人人| aaa久久久久久久久久网站| 97精品国产自在在线观看蜜臀| 91人妻精品久久久久久久久| 亚洲av不卡码在线看| 人妻人人揉人人澡人人| 欧美日本一道本一区二区| 丰满人妻一区二区三区av| 欧美一二三区在线观看| www.成人国产精品| 少妇人妻视频在线观看| 91超碰熟女在线97| 最新精品成人在线| 免费观看a级在线视频| 99精品视频在线看17| 亚洲久久久久久久人妻| 久久亚洲精品日韩高清| 激情黄色开心五月天| 久久久成人在线免费视频| 成人黄视频在线播放| 精品人妻二区中文字幕| 成人国产一区二区免费| 一本久久久久久久18| 久久激情毛片大放送| 搡老熟女一区二区三区四区视频 | 日韩在线免费视频精品| 久久久久久人妻无码| 国产一区二区视频大全床| 久久99国产综合精品无码免费| 亚洲成人久久久久| 亚洲激情有码一区二区| 高清一区二区日韩视频精品| 亚洲欧美在线制服丝袜| 色哟哟视频在线一区| 久久精品 中文字幕| 国产丝袜香蕉在线观看| 久久精品国产亚洲av不卡性色| 91插插插操美女视频| 中文字幕人妻一区二区在线看 | 久久精品国产亚洲av不卡性色| 少妇高潮一区二区三区99欧美| 久久99永久免费看| 亚洲熟妇av日韩熟妇在线| 久久久精品欧美一区二区国产 | 91高级会所在线播放| 亚洲欧洲久久精品| 五月爱婷婷六月丁香性| ass日本丰满熟妇pics| 久久视频这里都是精品| 久久精品国产亚洲av不卡性色| 久久久久女优免费视频| 五月天丁香婷婷国产| 精品97人妻无码中文永久| 久久久久久久精品综合| 麻豆精品一区在线免费观看| 人人妻人人澡人人爽dv| 玖玖资源站中文字幕一区二区| 精品久久久久久18免费网站| 人人妻人人澡人人爽国产一区 | 人妻一区二区中文字幕在线| 激情黄色开心五月天| 亚洲精品图片第十八页| 精品乱码一区二区三四五六区| 久久精品中文字幕av| 亚洲av网站女性向在线观看| 天天日天天干天天爱天天| 少妇人妻一区2区中文字幕| 日韩av电影免费在线播放| 免费看久久久久久久性大片| 欧美日韩在线卡一卡二卡三| 亚洲精品网站成人久久综合| 蜜桃av 1区二区| 欧美亚洲av日韩综合一区| www.亚洲成人色| 国产欧美日韩亚洲另类第一第二页 | 97人妻人人揉人人澡人人爽国产| 亚洲一区二区三区久久aa| 日本最新中文字幕| www.亚洲成人色| 欧美日韩国产色图视频| 人妻一区二区中文字幕在线 | 国产免费一级a男人的天堂| 国产成人无码AA精品一区 | 蜜桃视频在线观看一区精品| 欧美一区二区理论片在线观看 | 久久爱免费视频16| 91免费av在线观看| 久久最近最新中文字幕大全| 久久99国产综合精品无码免费| 大香蕉大香蕉大香蕉大香蕉大| 亚洲综合精品久久| 日本二次元少女裸| 精品成人1区2区3区在线看片 | 日韩乱妇乱女熟妇熟女网红| 久久久久久久久久久久久熟女a∨ 精品99国内中文字幕 | 久久久精品欧美一区二区国产| 亚洲熟妇在线观看一区二区| 中文字幕av久久爽爽| 蜜桃av 1区二区|