-
Notifications
You must be signed in to change notification settings - Fork 2
模块化,通往未来JavaScript库之路
原文:http://code.tutsplus.com/articles/modules-a-future-approach-to-javascript-libraries--cms-21800
JavaScript libraries such as jQuery have been the go-to approach for writing JavaScript in the browser for nearly a decade. They’ve been a huge success and necessary intervention for what was once a browser land full of discrepancies and implementation issues. jQuery seamlessly glossed over browser bugs and quirks and made it a no brainer approach to getting things done, such as event handling, Ajax and DOM manipulation.
JS库在过去的十年里已经发展到了顶峰,比如jQuery在浏览器端的贡献,它在处理浏览器兼容方面取得了非常巨大的成功,比如时间处理,Ajax和DOM操作。
At the time, jQuery solved all our problems, we include its almighty power and get to work straight away. It was, in a way, a black box that the browser “needed” to function properly.
当时,jQuery几乎解决了我们所有的问题,我们带着这股超强能量一路披荆斩棘。
But the web has evolved, APIs are improving, standards are being implemented, the web is a very fast moving scene and I’m not sure giant libraries have a place in the future for the browser. It’s becoming a module-oriented environment.
但是web在发展,API在改进,标准在被不断的实现,web技术正在你来我往的进行快速更新,我不确定当前的巨人是否可以在将来的浏览器端找到属于自己的位置,但我知道未来生态正在被面向模块所主导。
Enter the Module
进入模块的世界
A module is an encapsulated piece of functionality that does one thing only, and that one thing very well. For example, a module may be responsible for adding classes to an element, communicating over HTTP via Ajax, and so on - there are endless possibilities.
一个模块通常是由做一件事情的很多方法组合而成。比如,一个模块负责向元素增加class样式、或者基于Ajax进行HTTP通信等等,数不胜数。
A module can come in many shapes and sizes, but the general purpose of them is to be imported into an environment and work out of the box. Generally, each module would have some basic developer documentation and installation process, as well as the environments it’s meant for (such as the browser, server).
各个模块可能大小和样子都不同,但是它们有一个共同的目标,那就是可以组合到一起保证功能的运行。简而言之,每个模块都会有自己的逻辑实现,不论在客户端还是服务器端。
These modules then become project dependencies, and the dependencies become easy to manage. The days of dropping in a huge library are slowly fading away, large libraries don’t offer as much flexibility or power. Libraries such as jQuery have recognised this too, which is fantastic - they’ve a tool online which lets you download only the things you need.
这样这些模块之间就会形成依赖,但是这些依赖却变得更加容易管理。沉浸在巨型库的日子正在慢慢褪去,因为它不够灵活。像jQuery这类的库已经意识到了这点,他们提供了一个在线工具可以让你只下载自己需要的部分。
Modern APIs are a huge booster for module inspiration, now that browser implementations have drastically improved, we can start to create small utility modules to help us do our most common tasks.
现代版的API助推了模块化灵感的出现,因为当前浏览器实现已经大幅改进,我们只要创建一个很小的工具型模块就可以帮组我们做最普通的任务了。
The module era is here, and it’s here to stay.
模块化时代已经来临,准确的说是已经到来。
Inspiration for a First Module
第一个模块的启发
One modern API that I’ve always been interested in since its inception is the classList API. Inspired from libraries such as jQuery, we’ve now got a native way to add classes to an element without a library or utility functions.
从现代版API出现的时候,我就对classList产生了很大的兴趣。受到诸如jQuery库的启发,我们现在将使用一个原生的方法去为元素增加class。
The classList API has been around a few years now, but not many developers know about it. This inspired me to go and create a module that utilised the classList API, and for those browsers less fortunate to support it, provide some form of fallback implementation.
classList已经出现有一段时间了,但是知道的人并不是很多,这就启发我去创建一个模块来封装这个API。
Before we dive into the code, let’s look at what jQuery brought to the scene for adding a class to an element: 在我们深入代码之前,我们先看下jQuery是如何给一个元素增加class的。
$(elem).addClass(‘myclass’);
When this manipulation landed natively, we ended up with the aforementioned classList API - a DOMTokenList Object (space separated values) which represents the values stored against an element’s className. The classList API provides us a few methods to interact with this DOMTokenList, all very “jQuery-like”. Here’s an example of how the classList API adds a class, which uses the classList.add() method:
当这个代码被加载的时候,我们不在关心之前讨论的classList API,取而代之的是DOMTokenList对象,它存储了对应元素的className(空格隔开取值)。classList API提供了一些和DOMTokenList对象交互的方法,这和jQuery很像。下面是一个如果通过classListadd()增加class的例子:
elem.classList.add(‘myclass’);
What can we learn from this? A library feature making its way into a language is a pretty big deal (or at least inspiring it). This is what is so great about the open web platform, we can all have some insight as to how things progress.
从这里我们能学到什么呢?一个库的特性如果能够融入到一个语言中是一个非常棒的事情。这就是开放WEB平台的伟大,对于代码的处理,我们可以拥有自己的想法。
So, what next? We know about modules, and we kind of like the classList API, but unfortunately, not all browsers support it yet. We could write a fallback, though. Sounds like a good idea for a module that uses classList when supported or automatic fallbacks if not.
那下一步呢?我们知道了模块,而且我们喜欢这个classList API,但是不幸的是,当前并不是所有的浏览器都支持它,不过我们可以写个后备方法。这听起来是个不错的想法:如果支持则使用classList,否则自动转到后备方法中。
Creating a First Module: Apollo.js
创建第一个模块:Apollo.js
Around six months ago, I built a standalone and very lightweight module for adding classes to an Element in plain JavaScript - I ended up calling it apollo.js.
大约6个月前,我写了一个非常独立而且轻量级的模块用来对一个元素增加class,而且是原生js代码,最后我将它命名为apollo.js。
The main goal for the module was to start using the brilliant classList API and break away from needing a library to do a very simple and common task. jQuery wasn’t (and still doesn’t) use the classList API, so I thought it’d be a great way to experiment with the new technology.
这个模块的主要目的就是在不依赖其他库的情况下使用classList API去做一些简答的事情。jQuery还没有使用classList API,因此我想去试验这个新技术是非常值得的。
We’ll walk through how I made it as well and the thinking behind each piece that makes up the simple module.
我当前的任务就是尽可能好的设计它、组装它。
Using classList
使用classList
As we’ve seen already, classList is a very elegant API and “jQuery developer-friendly”, the transition to it is easy. One thing I don’t like about it, however, is the fact we have to keep referring to the classList Object to use one of its methods. I aimed to remove this repetition when I wrote apollo, deciding on the following API design:
正如我们所见,classList是一个非常优雅的API,并且对jQuery开发者来说也很友好,上手会很快。但是有一点不是我喜欢的,就是必须每次调用classList 对象来使用它的方法。我决定移除掉这些重复部分,使用下面的API进行设计:
apollo.addClass(elem, ‘myclass’);
A good class manipulation module should contain hasClass, addClass, removeClass and toggleClass methods. All these methods will ride off the “apollo” namespace.
一个号的class操作模块应该包含 hasClass, addClass, removeClass 和 toggleClass方法。这些方法都是在apollo命名空间下。
Looking closely at the above “addClass” method, you can see I pass in the element as the first argument. Unlike jQuery, which is a huge custom Object which you’re bound into, this module will accept a DOM element, how it’s fed that element is up to the developer, native methods or a selector module. The second argument is a simple String value, any class name you like.
自己看上面的addClass方法,你会发现我把元素节点传递给了它作为第一个参数。和jQuery不一样,jQuery采用的是在对象上绑定这些方法,这就很容易形成大对象。而这里我要设计的模块只是接收一个DOM节点,我们要做的就是使用开发者定义的元素、很原生的方法。第二个参数是一个字符串,就是class名字。
Let’s walk through the rest of the class manipulation methods that I wanted to create to see what they look like:
让我们过下剩下的class操作方法:
apollo.hasClass(elem, ‘myclass’); apollo.addClass(elem, ‘myclass’); apollo.removeClass(elem, ‘myclass’); apollo.toggleClass(elem, ‘myclass’);
So where do we begin? First, we need an Object to add our methods to, and some function closure to house any internal workings/variables/methods. Using an immediate-invoked function expression (IIFE), I wrap an Object named apollo (and some methods containing classList abstractions) to create our module definition.
那我们从那里开始呢?首先我们需要一个添加我们方法的对象,一些掌控内部运行变量或者方法的函数闭包。使用IIFE,我包装了一个对象apollo来创建我们的模块定义。
(function () {
var apollo = {};
apollo.hasClass = function (elem, className) {
return elem.classList.contains(className);
};
apollo.addClass = function (elem, className) {
elem.classList.add(className);
};
apollo.removeClass = function (elem, className) {
elem.classList.remove(className);
};
apollo.toggleClass = function (elem, className) {
elem.classList.toggle(className);
};
window.apollo = apollo;
})();
apollo.addClass(document.body, 'test');
Now we’re got classList working, we can think about legacy browser support. The aim for the apollomodule is to provide a tiny and standalone consistent API implementation for class manipulation, regardless of the browser. This is where simple feature detection comes into play.
现在classList可以工作了,我们该思考浏览器兼容问题了。apollo模块的目标就是提供一个独立小巧的API,而不管是啥浏览器。
The easy way to test feature presence for classList is this:
测试classList特性的最简单方法就是下面这样:
if ('classList' in document.documentElement) {
// you’ve got support
}
We’re using the in operator which evaluates the presence of classList to Boolean. The next step would be to conditionally provide the API to classList supporting users only:
我们使用in操作符来判断classList是否存在,如果存在,则使用它来提供给用户:
(function () {
var apollo = {};
var hasClass, addClass, removeClass, toggleClass;
if ('classList' in document.documentElement) {
hasClass = function () {
return elem.classList.contains(className);
}
addClass = function (elem, className) {
elem.classList.add(className);
}
removeClass = function (elem, className) {
elem.classList.remove(className);
}
toggleClass = function (elem, className) {
elem.classList.toggle(className);
}
}
apollo.hasClass = hasClass;
apollo.addClass = addClass;
apollo.removeClass = removeClass;
apollo.toggleClass = toggleClass;
window.apollo = apollo;
})();
Legacy support can be done in a few ways, reading the className String and looping through all the names, replace them, add them and so forth. jQuery uses a lot of code for this, utilising long loops and complex structure, I don’t want to completely bloat out this fresh and lightweight module, so set out to use a Regular Expression matching and replaces to achieve the exact same effect with next to no code at all.
判断class是否存在有不少方法,可以读取className然后循环遍历所有的name,然后可以替换它或者新增它。jQuery经常这样做,使用长循环或者复杂的结构,但是我不想弄坏我这个轻量级模块的味道,因此使用正则表达式去匹配和替换,这样能达到同样的效果。
Here’s the cleanest implementation I could come up with:
下面是我想到的最简洁的实现了:
function hasClass (elem, className) { return new RegExp('(^|\s)' + className + '(\s|$)').test(elem.className); }
function addClass (elem, className) { if (!hasClass(elem, className)) { elem.className += (elem.className ? ' ' : '') + className; } }
function removeClass (elem, className) { if (hasClass(elem, className)) { elem.className = elem.className.replace(new RegExp('(^|\s)' + className + '(\s|$)', 'g'), ''); } }
function toggleClass (elem, className) { (hasClass(elem, className) ? removeClass : addClass)(elem, className); }
Let’s integrate them into the module, adding the else part for non-supporting browsers:
现在让我们把这些集成到模块中,同时把浏览器兼容性代码也加进去:
(function () {
var apollo = {};
var hasClass, addClass, removeClass, toggleClass;
if ('classList' in document.documentElement) {
hasClass = function () {
return elem.classList.contains(className);
};
addClass = function (elem, className) {
elem.classList.add(className);
};
removeClass = function (elem, className) {
elem.classList.remove(className);
};
toggleClass = function (elem, className) {
elem.classList.toggle(className);
};
} else {
hasClass = function (elem, className) {
return new RegExp('(^|\\s)' + className + '(\\s|$)').test(elem.className);
};
addClass = function (elem, className) {
if (!hasClass(elem, className)) {
elem.className += (elem.className ? ' ' : '') + className;
}
};
removeClass = function (elem, className) {
if (hasClass(elem, className)) {
elem.className = elem.className.replace(new RegExp('(^|\\s)*' + className + '(\\s|$)*', 'g'), '');
}
};
toggleClass = function (elem, className) {
(hasClass(elem, className) ? removeClass : addClass)(elem, className);
};
}
apollo.hasClass = hasClass;
apollo.addClass = addClass;
apollo.removeClass = removeClass;
apollo.toggleClass = toggleClass;
window.apollo = apollo;
})();
A working jsFiddle of what we’ve done so far.
Let’s leave it there, the concept has been delivered. The apollo module has a few more features such as adding multiple classes at once, you can check that here, if interested.
好,功能我们就谈到这里。apollo模块还有一些其他功能,比如一次可以增加多个class,如果你有兴趣你可以试下。
So, what have we done? Built an encapsulated piece of functionality dedicated to doing one thing, and one thing well. The module is very simple to read through and understand, and changes can be easily made and validated alongside unit tests. We also have the ability to pull in apollo for projects where we don’t need jQuery and its huge offering, and the tiny apollo module will suffice.
那我们到现在为止都做了哪些事情呢?我们创建了多个函数的包装,这个包装用来去做一件事,而且一件事就够了。这个模块非常简单易读,而且很容易做单元测试。后面我们可以把apollo引入到项目中,它的小巧远胜jQuery。
Dependency Management: AMD and CommonJS
依赖管理:AMD和CommonJS
The concept of modules isn’t new, we use them all the time. You’re probably aware that JavaScript isn’t just about the browser anymore, it’s running on servers and even TV’s.
模块的概念并不新颖,我们经常使用他们。你可能知道JS可不仅仅只用于浏览器端,它可以运行于服务端甚至是TV。
What patterns can we adopt when creating and using these new modules? And where can we use them? There are two concepts called “AMD” and “CommonJS”, let’s explore them below.
对于这个新创建的模块我们应该采用哪个模式呢?我们能在什么地方使用它呢?当前有两个概念:AMD和CommonJS,下面让我们深入剖析下。
AMD
AMD
Asynchronous Module Definition (usually referred to as AMD) is a JavaScript API for defining modules to be asynchronously loaded, these typically run in the browser as synchronous loading incurs performance costs as well as usability, debugging, and cross-domain access problems. AMD can aid development, keeping JavaScript modules encapsulated in many different files.
异步模块定义(AMD)是一个用来定义异步加载模块的JS API,它一般用于浏览器端因为在调试和跨域访问中需要异步加载。AMD可以再开发阶段把各个模块分散在各个不同的文件中。
AMD uses a function called define, which defines a module itself and any export Objects. Using AMD, we can also refer to any dependencies to import other modules. A quick example taken from the AMD GitHub project:
AMD使用了define方法,用来定义一个模块并导出对象。使用AMD,我们可以引用任何依赖。下面是一个简单的例子:
define([‘alpha’], function (alpha) {
return {
verb: function () {
return alpha.verb() + 2;
}
};
});
We might do something like this for apollo if we were to use an AMD approach:
如果你想用AMD的话你也可以这样做:
define([‘apollo’], function (alpha) {
var apollo = {};
var hasClass, addClass, removeClass, toggleClass;
if ('classList' in document.documentElement) {
hasClass = function () {
return elem.classList.contains(className);
};
addClass = function (elem, className) {
elem.classList.add(className);
};
removeClass = function (elem, className) {
elem.classList.remove(className);
};
toggleClass = function (elem, className) {
elem.classList.toggle(className);
};
} else {
hasClass = function (elem, className) {
return new RegExp('(^|\\s)' + className + '(\\s|$)').test(elem.className);
};
addClass = function (elem, className) {
if (!hasClass(elem, className)) {
elem.className += (elem.className ? ' ' : '') + className;
}
};
removeClass = function (elem, className) {
if (hasClass(elem, className)) {
elem.className = elem.className.replace(new RegExp('(^|\\s)*' + className + '(\\s|$)*', 'g'), '');
}
};
toggleClass = function (elem, className) {
(hasClass(elem, className) ? removeClass : addClass)(elem, className);
};
}
apollo.hasClass = hasClass;
apollo.addClass = addClass;
apollo.removeClass = removeClass;
apollo.toggleClass = toggleClass;
window.apollo = apollo;
});
CommonJS
CommonJS
Node.js has been rising for the last few years, as well as dependency management tools and patterns. Node.js utilises something called CommonJS, which uses an “exports” Object to define a module’s contents. A really basic CommonJS implementation might look like this (the idea of “exporting” something to be used elsewhere):
这几年依赖管理工具盒模式已经伴随着Nodejs迅速发展起来了。NodeJS使用了CommonJS,后者通过一个esports对象来定义一个模块的内容。下面看一个最简单的CommonJS实现:
// someModule.js
exports.someModule = function () {
return "foo";
};
The above code would sit in it’s own file, I’ve named this one someModule.js. To import it elsewhere and be able to use it, CommonJS specifies that we need to use a function called “require” to fetch individual dependencies:
上面的代码我把它放在了someModele.js文件中。在其他地方只要引用它就可以使用它了,按照CommonJS的描述,我们只要调用require就可以了:
// do something with myModule
var myModule = require(‘someModule’);
If you’ve used Grunt/Gulp as well, you’re used to seeing this pattern.
如果你使用过Grunt或者Gulp,那么你可能会习惯这种模式了。
To use this pattern with apollo, we would do the following and reference the exports Object instead of the window (see last line exports.apollo = apollo):
为了在apollo中使用这个模式,我们不在使用window对象来引用他,而是使用了exports对象(看最后一行exports.apollo = apollo)。
(function () {
var apollo = {};
var hasClass, addClass, removeClass, toggleClass;
if ('classList' in document.documentElement) {
hasClass = function () {
return elem.classList.contains(className);
};
addClass = function (elem, className) {
elem.classList.add(className);
};
removeClass = function (elem, className) {
elem.classList.remove(className);
};
toggleClass = function (elem, className) {
elem.classList.toggle(className);
};
} else {
hasClass = function (elem, className) {
return new RegExp('(^|\\s)' + className + '(\\s|$)').test(elem.className);
};
addClass = function (elem, className) {
if (!hasClass(elem, className)) {
elem.className += (elem.className ? ' ' : '') + className;
}
};
removeClass = function (elem, className) {
if (hasClass(elem, className)) {
elem.className = elem.className.replace(new RegExp('(^|\\s)*' + className + '(\\s|$)*', 'g'), '');
}
};
toggleClass = function (elem, className) {
(hasClass(elem, className) ? removeClass : addClass)(elem, className);
};
}
apollo.hasClass = hasClass;
apollo.addClass = addClass;
apollo.removeClass = removeClass;
apollo.toggleClass = toggleClass;
exports.apollo = apollo;
})();
Universal Module Definition (UMD)
统一模块定义(UMD)
AMD and CommonJS are fantastic approaches, but what if we were to create a module that we wanted to work across all environments: AMD, CommonJS and the browser?
AMD和CommonJS都不是非常完美的解决方案,因为我我们想创建一个可以运行于任何地方的模块。
Initially, we did some if and else trickery to pass a function to each definition type based on what was available, we’d sniff out for AMD or CommonJS support and use it if it was there. This idea was then adapted and a universal solution began, dubbed “UMD”. It packages this if/else trickery for us and we just pass in a single function as reference to either module type that was supported, here’s one example from the project’s repository:
诚然,我们可以通过If else来判断当前哪个方案可用,如果支持AMD或者CommonJS,那就可以直接使用它,这个解决方案被称为UMD。UMD包装了If else分支,我们只要传入一个函数给它就可以了,下面是一个例子:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['b'], factory);
} else {
// Browser globals
root.amdWeb = factory(root.b);
}
}(this, function (b) {
//use b in some fashion.
// Just return a value to define the module export.
// This example returns an object, but the module
// can return a function as the exported value.
return {};
}));
Whoa! Lots happening here. We are passing in a function as the second argument to the IIFE block, which under a local variable name factory is dynamically assigned as AMD or globally to the browser. Yep, this doesn’t support CommonJS. We can, however, add that support (removing comments this time too):
哇!这里还差了东东。我们把一个函数传递给了IIFE风格的函数第二个参数factory,这个factory被设定在AMD和全局变量中。注意,这里不支持CommonJS,但是我们可以让它支持下:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['b'], factory);
} else if (typeof exports === 'object') {
module.exports = factory;
} else {
root.amdWeb = factory(root.b);
}
}(this, function (b) {
return {};
}));
The magic line here is module.exports = factory which assigns our factory to CommonJS.
这里巧妙的module.exports = factory这行代码,使用它可以支持CommonJS。
Let’s wrap apollo in this UMD setup so it can be used in CommonJS environments, AMD and the browser! I’ll include the full apollo script, from the latest version on GitHub, so things will look a little more complex than what I covered above (some new features have been added but weren’t purposely included in the above examples):
让我们把apollo填充到这个UMD结构中,这样它就可以不仅运行于CommonJS环境中,同时也可以运行于AMD和浏览器端。
/*! apollo.js v1.7.0 | (c) 2014 @toddmotto | https://github.com/toddmotto/apollo */ (function (root, factory) { if (typeof define === 'function' && define.amd) { define(factory); } else if (typeof exports === 'object') { module.exports = factory; } else { root.apollo = factory(); } })(this, function () {
'use strict';
var apollo = {};
var hasClass, addClass, removeClass, toggleClass;
var forEach = function (items, fn) { if (Object.prototype.toString.call(items) !== '[object Array]') { items = items.split(' '); } for (var i = 0; i < items.length; i++) { fn(items[i], i); } };
if ('classList' in document.documentElement) { hasClass = function (elem, className) { return elem.classList.contains(className); }; addClass = function (elem, className) { elem.classList.add(className); }; removeClass = function (elem, className) { elem.classList.remove(className); }; toggleClass = function (elem, className) { elem.classList.toggle(className); }; } else { hasClass = function (elem, className) { return new RegExp('(^|\s)' + className + '(\s|$)').test(elem.className); }; addClass = function (elem, className) { if (!hasClass(elem, className)) { elem.className += (elem.className ? ' ' : '') + className; } }; removeClass = function (elem, className) { if (hasClass(elem, className)) { elem.className = elem.className.replace(new RegExp('(^|\s)' + className + '(\s|$)', 'g'), ''); } }; toggleClass = function (elem, className) { (hasClass(elem, className) ? removeClass : addClass)(elem, className); }; }
apollo.hasClass = function (elem, className) { return hasClass(elem, className); };
apollo.addClass = function (elem, classes) { forEach(classes, function (className) { addClass(elem, className); }); };
apollo.removeClass = function (elem, classes) { forEach(classes, function (className) { removeClass(elem, className); }); };
apollo.toggleClass = function (elem, classes) { forEach(classes, function (className) { toggleClass(elem, className); }); };
return apollo;
});
We’ve created, a packaged our module to work across many environments, this gives us huge flexibility when bringing new dependencies into our work - something a JavaScript library can’t provide us without breaking it into little functional pieces to begin with.
我们已经创建了一个跨多个环境的模块,这对于项目中增加一个新特性到我们项目中就非常灵活-我们不需要分成好几块来分别支持一个功能。
Testing
测试
Typically, our modules are accompanied by unit tests, small bite size tests that make it easy for other developers to join your project and submit pull requests for feature enhancements, it’s a lot less daunting as well than a huge library and working out their build system! Small modules are often rapidly updated whereas larger libraries can take time to implement new features and fix bugs.
很明显,我们的模块是支持单元测试的,而且只需要很少的测试用例,这样开发者就能很容易的把它集成到项目中了,并做功能增强。和巨型库需要花好长时间去实现新特性和修复bug相比,小模块可以很快速的更新。
Wrapping Up
包装
It was great to create our own module and know we’re supporting many developers across many development environments. This makes developing more maintainable, fun and we understand the tools we’re using a lot better. Modules are accompanied by documentation that we can get up to speed with fairly quickly and integrate into our work. If a module doesn’t suit, we could either find another one or write our own - something we couldn’t do as easily with a large library as a single dependency, we don’t want to tie ourselves into a single solution.
我们自己创建我们自己的模块并且可以支持多个开发环境,这是一件很棒的事情。这是的开发更加可控、有趣,同时我们可以更加了解我们的工具,从而用的更好。模块都附有说明文档,我们可以很快的把它应用到我们的项目中。如果一个模块不可用,我们可以可以找个其他的模块,当然也可以自己写。我们最好不要直接依赖一个库。
Bonus: ES6 Modules
惊喜:ES6模块
A nice note to finish on, wasn’t it great to see how JavaScript libraries had influenced native languages with things like class manipulation?A Well, with ES6 (the next generation of the JavaScript language), we’ve struck gold! We have native imports and exports!
最后,一个可喜的结果就是,JS库已经影响了原生JS语言了,比如类管理。下一代JS语言ES6会支持import和export。
Check it out, exporting a module:
看下export代码:
/// myModule.js function myModule () { // module content } export myModule;
And importing:
import代码:
import {myModule} from ‘myModule’;
You can read more on ES6 and the modules specification here.
你可以点击这里读更懂关于ES6和模块化的说明。