google+javascriptbanktwitter@js_bankfacebook@jsbankrss@jsbank






Mô-đun và namespace trong JavaScript Bài viết này cung cấp các khái niệm cơ bản về mô-đun và namespace trong ngôn ngữ lập trình JavaScript. Bài viết hướng dẫn JavaScript này sẽ bàn về mục đích sử dụng của chúng, cách định nghĩa, khai báo và sử dụng chúng trong mã nguồn JavaScript, mã nguồn ứng dụng web. Ngoài ra bài viết còn cung cấp một số công cụ JavaScript hỗ trợ cũng như các thư viện JavaScript phổ biến để sử dụng module và namespace tốt, hiệu quả hơn.


Nhãn: ngôn ngữ lập trình JavaScript, công cụ JavaScript

Miễn phí web hosting 1 năm đầu tại iPage



Nếu bạn vẫn còn đang tìm kiếm một nhà cung cấp hosting đáng tin cậy, tại sao không dành chút thời gian để thử với iPage, chỉ với không quá 40.000 VNĐ/tháng, nhưng bạn sẽ được khuyến mãi kèm với quà tặng trị giá trên 10.000.0000 VNĐ nếu thanh toán cho 24 tháng ~ 900.000 VNĐ?

Có trên 1 triệu khách hàng hiện tại của iPage đã & đang hài lòng với dịch vụ, tuyệt đối chắc chắn bạn cũng sẽ hài lòng giống họ! Quan trọng hơn, khi đăng ký sử dụng web hosting tại iPage thông qua sự giới thiệu của chúng tôi, bạn sẽ được hoàn trả lại toàn bộ số tiền bạn đã sử dụng để mua web hosting tại iPage. Wow, thật tuyệt vời! Bạn không phải tốn bất kì chi phí nào mà vẫn có thể sử dụng miễn phí web hosting chất lượng cao tại iPage trong 12 tháng đầu tiên. Chỉ cần nói chúng tôi biết tài khoản của bạn sau khi đăng ký.

Nếu muốn tìm hiểu thêm về ưu / nhược điểm của iPage, bạn hãy đọc đánh giá của ChọnHostViệt.com nhé!
Thử iPage miễn phí cho năm đầu tiên NGAY

JavaScript does not come with support for modules. This blog post examines patterns and APIs that provide such support. It is split into the following parts:

  1. Patterns for structuring modules.
  2. APIs for loading modules asynchronously.
  3. Related reading, background and sources.

1. Patterns for structuring modules

A module fulfills two purposes: First, it holds content, by mapping identifiers to values. Second, it provides a namespace for those identifiers, to prevent them from clashing with identifiers in other modules. In JavaScript, modules are implemented via objects.
  • Namespacing: A top-level module is put into a global variable. That variable is the namespace of the module content.
  • Holding content: Each property of the module holds a value.
  • Nesting modules: One achieves nesting by putting a module inside another one.

Filling a module with content

Approach 1: Object literal.
    var namespace = {
        func: function() { ... },
        value: 123
    };
Approach 2: Assigning to properties.
    var namespace = {};
    namespace.func = function() { ... };
    namespace.value = 123;
Accessing the content in either approach:
    namespace.func();
    console.log(namespace.value + 44);
Assessment:
  1. Object literal.
    • Pro: Elegant syntax.
    • Con: As a single, sometimes very long syntactic construct, it imposes constraints on its contents. One must maintain the opening brace before the content and the closing brace after the content. And one must remember to not add a comma after the last property value. This makes it harder to move content around.
  2. Assigning to properties.
    • Con: Redundant repetitions of the namespace identifier.

The Module pattern: private data and initialization

In the module pattern, one uses an Immediately-Invoked Function Expression (IIFE, [1]) to attach an environment to the module data. The bindings inside that environment can be accessed from the module, but not from outside. Another advantage is that the IIFE gives you a place to perform initializations.
    var namespace = function() {
        // set up private data
        var arr = []; // not visible outside
        for(var i=0; i<4; i++) {
            arr.push(i);
        }
        return {
            // read-only access via getter
            get values() {
                return arr;
            }
        };
    }();
    console.log(namespace.values); // [0,1,2,3]
Comments:
  • Con: Harder to read and harder to figure out what is going on.
  • Con: Harder to patch. Every now and then, you can reuse existing code by patching it just a little. Yes, this breaks encapsulation, but it can also be very useful for temporary solutions. The module pattern makes such patching impossible (which may be a feature, depending on your taste).
  • Alternative for private data: use a naming convention for private properties, e.g. all properties whose names start with an underscore are private.
Variation: Namespace is a function parameter.
    var namespace = {};
    (function(ns) {
        // (set up private data here)
        ns.func = function() { ... };
        ns.value = 123;
    }(namespace));
Variation: this as the namespace identifier (cannot accidentally be assigned to).
    var namespace = {};
    (function() {
        // (set up private data here)
        this.func = function() { ... };
        this.value = 123;
    }).call(namespace); // hand in implicit parameter "this"

Referring to sibling properties

Use this. Con: hidden if you nest functions (which includes methods in nested objects).
    var namespace = {
        _value: 123; // private via naming convention
        getValue: function() {
            return this._value;
        }
        anObject: {
            aMethod: function() {
                // "this" does not point to the module here
            }
        }
    }
Global access. Cons: makes it harder to rename the namespace, verbose for nested namespaces.
    var namespace = {
        _value: 123; // private via naming convention
        getValue: function() {
            return namespace._value;
        }
    }
Custom identifier: The module pattern (see above) enables one to use a custom local identifier to refer to the current module.
  • Module pattern with object literal: assign the object to a local variable before returning it.
  • Module pattern with parameter: the parameter is the custom identifier.

Private data and initialization for properties

An IFEE can be used to attach private data and initialization code to an object. It can do the same for a single property.
    var ns = {
        getValue: function() {
            var arr = []; // not visible outside
            for(var i=0; i<4; i++) {
                arr.push(i);
            }
            return function() { // actual property value
                return arr;
            };
        }()
    };

Read on for an application of this pattern.

Types in object literals

Problem: A JavaScript type is defined in two steps. First, define the constructor. Second, set up the prototype of the constructor. These two steps cannot be performed in object literals. There are two solutions:
  • Use an inheritance API where constructor and prototype can be defined simultaneously [4].
  • Wrap the two parts of the type in an IIFE:
        var ns = {
            Type: function() {
                var constructor = function() {
                    // ...
                };
                constructor.prototype = {
                    // ...
                };
                return constructor; // value of Type
            }()
        };
    

Managing namespaces

Use the same namespace in several files: You can spread out a module definition across several files. Each file contributes features to the module. If you create the namespace variable as follows then the order in which the files are loaded does not matter. Note that this pattern does not work with object literals.
    var namespace = namespace || {};
Nested namespaces: With multiple modules, one can avoid a proliferation of global names by creating a single global namespace and adding sub-modules to it. Further nesting is not advisable, because it adds complexity and is slower. You can use longer names if name clashes are an issue.
    var topns = topns || {};
    topns.module1 = {
        // content
    }
    topns.module2 = {
        // content
    }
YUI2 uses the following pattern to create nested namespaces.
    YAHOO.namespace("foo.bar");
    YAHOO.foo.bar.doSomething = function() { ... };

2. APIs for loading modules asynchronously

Avoiding blocking: The content of a web page is processed sequentially. When a script tag is encountered that refers to a file, two steps happen:
  1. The file is downloaded.
  2. The file is interpreted.
All browsers block the processing of subsequent content until (2) is finished, because everything is single-threaded and must be processed in order. Newer browsers perform some downloads in parallel, but rendering is still blocked [2]. This unnecessarily delays the initial display of a page. Modern module APIs provide a way around this by supporting asynchronous loading of modules. There are usually two parts to using such APIs: First one specifies what modules one would like to use. Second, one provides a callback that is invoked once all modules are ready. The goal of this section is not to be a comprehensive introduction, but rather to give you an overview of what is possible in the design space of JavaScript modules.

2.1. RequireJS

RequireJS has been created as a standard for modules that work both on servers and in browsers. The RequireJS website explains the relationship between RequireJS and the earlier CommonJS standard for server-side modules [3]:
CommonJS defines a module format. Unfortunately, it was defined without giving browsers equal footing to other JavaScript environments. Because of that, there are CommonJS spec proposals for Transport formats and an asynchronous require.

RequireJS tries to keep with the spirit of CommonJS, with using string names to refer to dependencies, and to avoid modules defining global objects, but still allow coding a module format that works well natively in the browser. RequireJS implements the Asynchronous Module Definition (formerly Transport/C) proposal.

If you have modules that are in the traditional CommonJS module format, then you can easily convert them to work with RequireJS.

RequireJS projects have the following file structure:
    project-directory/
        project.html
        legacy.js
        scripts/
            main.js
            require.js
            helper/
                util.js
project.html:
    <!DOCTYPE html>
    <html>
        <head>
            <title>My Sample Project</title>

            <!-- data-main attribute tells require.js to load
                 scripts/main.js after require.js loads. -->
            <script data-main="scripts/main" src="/javascript/article/Modules_and_Namespaces_in_JavaScript.php/scripts/require.js"></script>
        </head>
        <body>
            <h1>My Sample Project</h1>

        </body>
    </html>
main.js: helper/util is resolved relative to data-main. legacy.js ends with .js and is assumed to not be in module format. The consequences are that its path is resolved relative to project.html and that there isn�t a function parameter to access its (module) contents.
    require(["helper/util", "legacy.js"], function(util) {
        //This function is called when scripts/helper/util.js is loaded.

        require.ready(function() {
            //This function is called when the page is loaded
            //(the DOMContentLoaded event) and when all required
            //scripts are loaded.
        });
    });
Other features of RequireJS:
  • Specify and use internationalization data.
  • Load text files (e.g. to be used for HTML templating)
  • Use JSONP service results for initial application setup.

2.2. YUI3

Version 3 of the YUI JavaScript framework brings its own module infrastructure. YUI3 modules are loaded asynchronously. The general pattern for using them is as follows.
    YUI().use('dd', 'anim', function(Y) {
        // Y.DD is available
        // Y.Anim is available
    });
Steps:
  • Provide IDs �dd� and �anim� of the modules you want to load.
  • Provide a callback to be invoked once all modules have been loaded.
  • The parameter Y of the callback is the YUI namespace. This namespace contains the sub-namespaces DD and Anim for the modules. As you can see, the ID of a module and its namespace are usually different.
Method YUI.add() allows you to register your own modules.
    YUI.add('mymodules-mod1',
        function(Y) {
            Y.namespace('mynamespace');
            Y.mynamespace.Mod1 = function() {
                // expose an API
            };
        },
        '0.1.1' // module version
    );
YUI includes a loader for retrieving modules from external files. It is configured via a parameter to the API. The following example loads two modules: The built-in YUI module dd and the external module yui_flot that is available online.
    YUI({
        modules:  {
            yui2_yde_datasource: { // not used below
                fullpath: 'http://yui.yahooapis.com/datasource-min.js'
            },
            yui_flot: {
                fullpath: 'http://bluesmoon.github.com/yui-flot/yui.flot.js'
            }
        }
    }).use('dd', 'yui_flot', function(Y) {
        // do stuff
    });

2.3. Script loaders

Similarly to RequireJS, script loaders are replacements for script tags that allow one to load JavaScript code asynchronously and in parallel. But they are usually simpler than RequireJS. Examples:
  • LABjs: a relatively simple script loader. Use it instead of RequireJS if you need to load scripts in a precise order and you don't need to manage module dependencies. Background: �LABjs & RequireJS: Loading JavaScript Resources the Fun Way� describes the differences between LABjs and RequireJS.
  • yepnope: A fast script loader that allows you to make the loading of some scripts contingent on the capabilities of the web browser.
Ứng dụng AI Video.com
Tạo video doanh nghiệp của bạn bằng AI chỉ với giọng nói hoặc văn bản

chatGPTaz.com
Nói chuyện với ChatGPT bằng ngôn ngữ mẹ đẻ của bạn

Ứng dụng AI Video
Ứng dụng video AI MIỄN PHÍ đầu tiên của bạn

Deepfake Video
Deepfake AI Video Maker

Deepfake
Deepfake AI Video Maker

AI Deep Fake
Deepfake AI Video Maker

AIvidio
AI Video Mobile Solutions

AIvideos
AI Video Platform & Solutions

AIvedio
AI Video App Maker

Faceswap AI trực tuyến
Đổi mặt Video, Ảnh & GIF ngay lập tức với Công cụ AI mạnh mẽ - Faceswap AI Trực tuyến MIỄN PHÍ

Faceswap AI trực tuyến
Đổi mặt Video, Ảnh & GIF ngay lập tức với Công cụ AI mạnh mẽ - Faceswap AI Trực tuyến MIỄN PHÍ

Temu tặng $500 cho người dùng mới
Claim Free Temu $500 Credit via Affiliate & Influencer Program

Tín dụng quảng cáo TikTok miễn phí
Làm chủ quảng cáo TikTok cho hoạt động tiếp thị doanh nghiệp của bạn

Dall-E-OpenAI.com
Tự động tạo ra hình ảnh sáng tạo với AI

chatGPT4.win
Nói chuyện với ChatGPT bằng ngôn ngữ mẹ đẻ của bạn

Sản phẩm AI đầu tiên của Elon Musk - Grok/UN.com
Nói chuyện với Grok AI Chatbot bằng ngôn ngữ của bạn

Công cụ.win
Mở trung tâm công cụ miễn phí để mọi người sử dụng với hàng trăm công cụ

GateIO.gomymobi.com
Airdrop miễn phí để nhận, chia sẻ lên đến 150.000 đô la cho mỗi dự án

iPhoneKer.com
Tiết kiệm tới 630$ khi mua iPhone 16 mới

Mua Robot Tesla Optimus
Đặt mua Tesla Bot: Robot Optimus Gen 2 ngay hôm nay với giá dưới 20.000 đô la

JavaScript theo ngày


Google Safe Browsing McAfee SiteAdvisor Norton SafeWeb Dr.Web