资讯专栏INFORMATION COLUMN

ES6—class与模块化(9)

weij / 2438人阅读

摘要:中的模块功能主要由两个命令构成和。命令用于规定模块的对外接口,命令用于输入其他模块提供的功能,二者属于相辅相成一一对应关系。文件大括号里面的变量名,必须与被导入模块对外接口的名称相同。每一个模块内声明的变量都是局部变量,不会污染全局作用域。

JavaScript语言自创立之初,一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。

很多编程语言都有这项功能,比如 Python的import、Ruby的require,甚至就连CSS都有@import,但是JavaScript没有这方面的支持,这增加了开发大型的、复杂的项目时的难度。

于是前端开发者们开始想办法,为了防止命名空间被污染,采用的是命名空间的方式。

在ES6之前,一些前端社区制定了模块加载方案,最主要的有CommonJS和AMD两种。前者用于服务器,后者用于浏览器。

但这两种规范都由开源社区制定,没有统一,而ES6中引入了模块(Module)体系,从语言层在实现了模块机制,实现了模块功能,而且实现得相当简单,为JavaScript开发大型的、复杂的项目扫清了障碍。

ES6中的模块功能主要由两个命令构成:export和import。

export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能,二者属于相辅相成、一一对应关系。

一、什么是模块

模块可以理解为函数代码块的功能,是封装对象的属性和方法的javascript代码,它可以是某单个文件、变量或者函数。

模块实质上是对业务逻辑分离实现低耦合高内聚,也便于代码管理而不是所有功能代码堆叠在一起,模块真正的魔力所在是仅导出和导入你需要的绑定,而不是将所有的东西都放到一个文件。

在理想状态下我们只需要完成自己部分的核心业务逻辑代码,其他方面的依赖可以通过直接加载被人已经写好模块进行使用即可。

二、export 导出 命令

一个模块就是一个独立的文件,该文件内部的所有变量,外部无法获取。如果想从外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。分为以下几种情况:

(1)在需要导出的lib.js文件中, 使用 export{接口} 导出接口, 大括号中的接口名字为上面定义的变量, import和引入的main.js文件中的export是对应的:

//lib.js 文件
let bar = "stringBar";
let foo = "stringFoo";
let fn0 = function() {
    console.log("fn0");
};
let fn1 = function() {
    console.log("fn1");
};
export{ bar , foo, fn0, fn1}

//main.js文件
import {bar,foo, fn0, fn1} from "./lib";
console.log(bar+"_"+foo);
fn0();
fn1();

(2)在export接口的时候, 我们可以使用 XX as YY, 把导出的接口名字改了, 比如: xiaoming as haoren,

这样做的目的是为了让接口字段更加语义化。

//lib.js文件
let fn0 = function() {
    console.log("fn0");
};
let obj0 = {}
export { fn0 as foo, obj0 as bar};

//main.js文件
import {foo, bar} from "./lib";
foo();
console.log(bar);

(3)直接在export的地方定义导出的函数,或者变量:

//lib.js文件
export let foo = ()=> {console.log("fnFoo") ;return "foo"},bar = "stringBar";

//main.js文件
import {foo, bar} from "./lib";
console.log(foo());
console.log(bar);

(4)不需要知道变量名字(相当于是匿名的)的情况,可以 直接把开发的接口给export。如果一个js模块文件就只有一个功能, 那么就可以使用export default导出。

//lib.js
export default "string";

//main.js
import defaultString from "./lib";
console.log(defaultString);

这样做的好处是其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。

(5)export也能默认导出函数, 在import的时候, 名字可以自定义, 因为每一个模块的默认接口就一个:

//lib.js
let fn = () => "string";
export {fn as default};

//main.js
import defaultFn from "./lib";
console.log(defaultFn());


(6)使用通配符* ,重新导出其他模块的接口

//lib.js
export * from "./other";
//如果只想导出部分接口, 只要把接口名字列出来
//export {foo,fnFoo} from "./other";

//other.js
export let foo = "stringFoo", fnFoo = function() {console.log("fnFoo")};

//main.js
import {foo, fnFoo} from "./lib";
console.log(foo);
console.log(fnFoo());

三、import 导入命令

ES6导入的模块都是属于引用,每一个导入的js模块都是活的, 每一次访问该模块的变量或者函数都是最新的, 这个是原生ES6模块 与AMD和CMD的区别之一。

使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块。

//main.js文件
import {bar,foo, fn0, fn1} from "./lib";
console.log(bar+"_"+foo);
fn0();
fn1();

大括号里面的变量名,必须与被导入模块对外接口的名称相同。

想要输入的变量重新取一个名字,import命令要使用 as关键字,将输入的变量重命名。

import { formatFn as fn0 } from "lib.js";

注:import后面的from指定模块文件的位置,可以是相对路径,也可以是绝对路径,.js后缀可以省略。

四、ES6模块化的基本规则、特点

1、每一个模块只加载一次, 每一个JS只执行一次, 如果下次再去加载同目录下同文件,直接从内存中读取。 一个模块就是一个单例,或者说就是一个对象。

2、每一个模块内声明的变量都是局部变量, 不会污染全局作用域。

3、模块内部的变量或者函数可以通过export导出。

4、一个模块可以导入别的模块。

五、class与模块化相结合实例

结合上节课我们学的 ES6 class与面向对象编程的知识,我们再实现一个把class和模块化结合的例子。

首先我们创建一个parent.js文件,使用class类的写法创建一个Parent类:

const name = "tom";
const age = "20";

class Parent{
  hw(){
    console.log(`hello world`)
  }
  static obj(){
      console.log("obj")/*表示为静态方法不回呗实例继承,而是直接通过类调用。*/
    }
}  
var parent = new Parent()
parent.hw()//hell world

export{name,age,Parent}

之后在child.js中分别引入parent.js中的name、age、Parent

import {name,age,Parent} from "./parent"


class Child extends Parent{
    constructor(obj){
        //就是new命令自动跳用方法。一个类必须要有constructor,如果没定义,有默认添加一个空的。
        super()//调用父类的constructor()
        this._config = obj;
        console.log(obj.name+"年龄"+obj.age)
    }
    hw(){
      console.log("hw")
    }
    set val(value){
      this._config.name = value;
      console.log(`name=${value}`)
    }
    get val(){
      console.log(this._config.name);
    }
}

Child.obj()//obj 继承父类static方法
var model = new Child({name,age}) //tom年龄20
model.hw()//hw
model.val = "jock"; //name=jock
model.val//jock

六、总结

本文主要从什么是模块,模块的导出(导出变量、函数、类、文件等),模块的导入(单个导入、多个导入、导入整个)等角度讲述了ES6模块化操作。

ES6模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS和AMD模块,都只能在运行时确定这些东西。比如 CommonJS模块就是对象,输入时必须查找对象属性。

模块打包现在最好用的就是webpack了,webpack作为一款新兴的模块化管理和打包工具,其视任意文件都为模块,并打包成bundle文件,相比于browserify更加强大。

模块化开发是前端开发的一大趋势,比如大家去看vue、react、angular,或者你们公司的项目源码,你会发现,几乎所有项目都使用了模块化。小伙伴们一定要紧跟时代的大潮,将组件化开发,模块化开发,自动化构建结合,探索高效的开发之道。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/109450.html

相关文章

  • ES6

    摘要:对象可被不定参数和默认参数完美代替。将对象纳入规范,提供了原生的对象。规定,命令和命令声明的全局变量,属于全局对象的属性命令命令命令声明的全局变量,不属于全局对象的属性。。这些函数表达式最适合用于非方法函数,并且它们不能用作构造函数。 ES6的了解 新增模板字符串(为JavaScript提供了简单的字符串插值功能)、箭头函数(操作符左边为输入的参数,而右边则是进行的操作以及返回的值In...

    snifes 评论0 收藏0
  • 10个最佳ES6特性

    摘要:,正式名称是,但是这个名称更加简洁。已经不再是最新的标准,但是它已经广泛用于编程实践中。而制定了模块功能。自从年双十一正式上线,累计处理了亿错误事件,得到了金山软件等众多知名用户的认可。 译者按: 人生苦短,我用ES6。 原文: Top 10 ES6 Features Every Busy JavaScript Developer Must Know 译者: Fundebug 为了保...

    codeKK 评论0 收藏0
  • ES6、ES7、ES8、ES9、ES10新特性一览

    摘要:规范最终由敲定。提案由至少一名成员倡导的正式提案文件,该文件包括事例。箭头函数这是中最令人激动的特性之一。数组拷贝等同于展开语法和行为一致执行的都是浅拷贝只遍历一层。不使用对象中必须包含属性和值,显得非常冗余。 ES全称ECMAScript,ECMAScript是ECMA制定的标准化脚本语言。目前JavaScript使用的ECMAScript版本为ECMA-417。关于ECMA的最新资讯可以...

    Muninn 评论0 收藏0
  • ES6核心特性

    摘要:报错不报此外还有个好处就是简化回调函数正常函数写法箭头函数写法改变指向长期以来,语言的对象一直是一个令人头痛的问题,在对象方法中使用,必须非常小心。 前言 ES6 虽提供了许多新特性,但我们实际工作中用到频率较高并不多,根据二八法则,我们应该用百分之八十的精力和时间,好好专研这百分之二十核心特性,将会收到事半功倍的奇效!写文章不容易,请大家多多支持与关注!本文首发地址GitHub博客(...

    loostudy 评论0 收藏0
  • ES6核心特性

    摘要:报错不报此外还有个好处就是简化回调函数正常函数写法箭头函数写法改变指向长期以来,语言的对象一直是一个令人头痛的问题,在对象方法中使用,必须非常小心。 前言 ES6 虽提供了许多新特性,但我们实际工作中用到频率较高并不多,根据二八法则,我们应该用百分之八十的精力和时间,好好专研这百分之二十核心特性,将会收到事半功倍的奇效!写文章不容易,请大家多多支持与关注!本文首发地址GitHub博客(...

    _DangJin 评论0 收藏0

发表评论

0条评论

weij

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<