ECMAScript 6 类 应用
来源:互联网 发布:御彩轩时时彩计划软件 编辑:程序博客网 时间:2024/06/05 06:10
近些日子在git上经常看到以es6编写的js代码。
以前有些了解,但没有深入学习。
现在用的人多了,也就找了些时间来学习了下。
应用:
在webpack 中会使用es6。
当然肯定需要模块来翻译成es5的代码:babel
es6文档看了下,我觉得对于类模块这块用处比较大。
在现实中使用也简单方便些。
js 语言传统是通过构造函数,定义并生成新对象。
在es6中引用了class 类。作为对象的模板。通过class关键字,定义类。
新的class写法只是让对象原型的写法更新清晰、更像面向对象编程的语法而以。
和后端写法类似了。
//定义类class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; }}constructor j 是构造函数,this 表示实例对象。tostring 是类的方法。
方法的定义 实现是扩展了Point.prototype
实例对象:
var a=new Point(参数)
Point .name //Point
Class 表达式:
const MyClass = class Me { getClassName() { return Me.name; }};以上创建了一个类,类名是MyClass而不是Me. me只能在类的内部代码可用。
let inst = new MyClass();inst.getClassName() // Me
当然me是可以省略的const MyClass = class { /* ... */ };
采用class 表达式,可以写出立即执行的classlet person = new class { constructor(name) { this.name = name; } sayName() { console.log(this.name); }}("张三");person.sayName(); // "张三"
class 不存在变量提升,class 继承
class之间可以通过extends关键字实现继承。
class ColorPoint extends Point {}
上面定义了一个colorpoint 类,继承了point类的所有属性和方法。但是由于没有部署任何任何,所以这两个类完全一样。等于复制了一个point。
class ColorPoint extends Point { constructor(x, y, color) { super(x, y); // 调用父类的constructor(x, y) this.color = color; } toString() { return this.color + ' ' + super.toString(); // 调用父类的toString() }}
上面代码定义了新的构造函数,和tostring方法。方法内的super指向父类的方法。
class 的取值函数get和存值函数set
class MyClass { constructor() { // ... } get prop() { return 'getter'; } set prop(value) { console.log('setter: '+value); }}let inst = new MyClass();inst.prop = 123;// setter: 123inst.prop
class的静态方法
class Foo { static classMethod() { return 'hello'; }}Foo.classMethod() // 'hello'var foo = new Foo();foo.classMethod()// TypeError: undefined is not a function
staitc可以创建静态方法或属性。
模块的定义和引用。
js一直没有模块体系,无法将一个大程序拆分成互相依赖的小文件。
在es6之前社区制定了一些模块加载方案,最主要的有commonjs 和amd 两种。
前者用于服务器,后者用于浏览器
es6实现了模块功能,完全可以取代commonjs amd规范。
es6模块的设计思想,是尽量的静态化。使得编译时就能确定模块的依赖关系。
以及输入和输出的变量。
// CommonJS模块let { stat, exists, readFile } = require('fs');// 等同于let _fs = require('fs');let stat = _fs.stat, exists = _fs.exists, readfile = _fs.readfile;
上面代码的实质是整体加载fs模块,生成一个对象。然后从这个对象上获取三个方法。这种加载为“运行时加载”
因为只有运行时才能得到这个对象,导致完全没有办法 在编译时做“静态优化”
es6模块不是对象,而是通过export命令显式指定输出的代码,输出时采用静态命令的形式。
// ES6模块import { stat, exists, readFile } from 'fs';
上面是加载fs模块的三个方法,其他方法不加载。称为“编译加载”,即es6在编译时就完成模块加载。
当然这也导致了没法引用es模块本身,因为它不是对象。
export 命令
模块功能主要由export 和Import 。
export 命令用于规定模块的对外接口。
Import 命令用于输入其他模块提供的功能。
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。
如果你希望外部能够读取模块内部的某个变量,就必须使用export 输出该变量。
// profile.jsexport var firstName = 'Michael';export var lastName = 'Jackson';export var year = 1958;
对外输出三个变量。// profile.jsvar firstName = 'Michael';var lastName = 'Jackson';var year = 1958;export {firstName, lastName, year};
也可以这样写。使用大括号指定要输出的一组变量。
export function multiply (x, y) { return x * y;};
还可以输出函数或类。function v1() { ... }function v2() { ... }export { v1 as streamV1, v2 as streamV2, v2 as streamLatestVersion};
export输出的变量就是本来的名字,但是 可以使用as 重合名。
export var foo = 'bar';setTimeout(() => foo = 'baz', 500);
export语句输出的值是动态绑定,绑定其所在的模块。上在代码输出变量foo 什为bar ,500ms后变成baz
import 命令
js文件可通过import命令加载这个模块。
// main.jsimport {firstName, lastName, year} from './profile';function setName(element) { element.textContent = firstName + ' ' + lastName;}
import 命令接受一个对象,里面指定要多其他模块导入的变量名。大括号里的变量名,必须与被导入模块对外接口名称相同。
import { lastName as surname } from './profile';
as 可将输入的的名称,从命名。import 命令具有提升效果,会提升到整个模块的头部,首先执行。
foo();import { foo } from 'my_module';
上面代码不会报错,因为Import 的执行早于foo的调用。export { es6 as default } from './someModule';// 等同于import { es6 } from './someModule';export default es6;
模块中可以先输入加载模块,再输出此模块export 输出和import输入可以结合一起。
import 'lodash'
模块的整体加载
除了指定加载某个输出值,还可以使用整体加载,即用* 指定一个对象,所有输出值都加载在这个对象上面。
export function area(radius) { return Math.PI * radius * radius;}export function circumference(radius) { return 2 * Math.PI * radius;}
输出三个方法。// main.jsimport { area, circumference } from './circle';console.log("圆面积:" + area(4));console.log("圆周长:" + circumference(14));
上面写法是指定要加载的方法,整体加载如下:import * as circle from './circle';console.log("圆面积:" + circle.area(4));console.log("圆周长:" + circle.circumference(14));
export default 命令
import命令使用时,用户需要知道所需加载的变量名,否则无法加载。
但为了方便,可以用default 命令,为模块指定默认输出。
// export-default.jsexport default function () { console.log('foo');}
默认输出一个函数// import-default.jsimport customName from './export-default';customName(); // 'foo'
加载时import 可以为默认函数指定任意的名称。需要注意的是,这时Import命令后面,不使用大括号 。
// export-default.jsexport default function foo() { console.log('foo');}// 或者写成function foo() { console.log('foo');}export default foo;
default 命令用在非匿名函数前,也是可以的。// 输出export default function crc32() { // ...}// 输入import crc32 from 'crc32';// 输出export function crc32() { // ...};// 输入import {crc32} from 'crc32';
// modules.jsfunction add(x, y) { return x * y;};export {add as default};// 等同于// export default add;// app.jsimport { default as xxx } from 'modules';// 等同于// import xxx from 'modules';
本质上export default 就是输出一个叫做default的变量或方法,然后系统允许你为它取任意名字。// 正确export var a = 1;// 正确var a = 1;export default a;// 错误export default var a = 1;
因为export default 命令其实中是输出一个叫做default的变量,所以它后面不能跟变量声明语句。import customName, { otherMethod } from './export-default';
可以在一条import语句中,同时输入默认方法和其他变量。模块的继承
模块间可以继承
// circleplus.jsexport * from 'circle';export var e = 2.71828182846;export default function(x) { return Math.exp(x);}
以上继承了circle模块。export * 表示输出circle 模块的所有属性和方法,当然它会忽略default。
export { area as circleArea } from 'circle';
可以将circle 改名后再输出 。import * as math from "circleplus";import exp from "circleplus";console.log(exp(math.e));
加载模块再定义新引入对象,再获取模块的默认方法定义成expimport * as math from "circleplus";import exp from "circleplus";console.log(exp(math.e));
import * as math from "circleplus";import exp from "circleplus";console.log(exp(math.e));
es6模块加载的实质
es6模块加载的机制,与commonjs模块完全不同。
commonjs模块输出的是一个值的拷贝,而es模块输出的是值的引用。
拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。
// lib.jsvar counter = 3;function incCounter() { counter++;}module.exports = { counter: counter, incCounter: incCounter,};
// main.jsvar mod = require('./lib');console.log(mod.counter); // 3mod.incCounter();console.log(mod.counter); // 3
lib加载以后,它的内部变化就不影响输出的counter了。这是因为mod.counter是一个原始类型的值,会被缓存。es6模块的运行机制,与commonjs不一样。
它遇到模块加载命令Import时,不会执行模块,而是只生成一个动态的只读引用。
等到真的需要用到时,再到模块里去取值。
es6输出有点像地址引用,原始值变了,输入的值也会变。
因此es6模块是动态引用,模块里的变量绑定其白发在的模块。
// lib.jsexport let counter = 3;export function incCounter() { counter++;}// main.jsimport { counter, incCounter } from './lib';console.log(counter); // 3incCounter();console.log(counter); // 4
// m1.jsexport var foo = 'bar';setTimeout(() => foo = 'baz', 500);// m2.jsimport {foo} from './m1.js';console.log(foo);setTimeout(() => console.log(foo), 500);
// lib.jsexport let obj = {};// main.jsimport { obj } from './lib';obj.prop = 123; // OKobj = {}; // TypeError
由于es6输入的模块变量,只是一个“符号连接”,所以这个变量是只读的。对它进行重新赋值会报错。- ECMAScript 6 类 应用
- ECMASCRIPT-6
- ECMAScript 6
- ECMAScript 6
- ECMAScript 6
- ECMAScript 6
- 理解ECMAScript 6:类和继承
- 理解Ecmascript 6中的类和继承
- Use ECMAScript 6 Today
- ECMAScript 6 模块简介
- ECMAScript 6 Features 中文版
- ECMAScript 6 新特性
- ECMAScript 6 Features 中文版
- ECMAScript 6入门
- 试试 ECMAScript 6
- ECMAScript 6新特性
- ECMAScript 6简介
- ECMAScript 6 入门
- Gym 100231BIntervals
- Git的学习笔记(二)——提交流程与暂存区
- [BUG]-Assertion failure in void _UIPerformResizeOfTextViewForTextContainer
- c语言中cJson的使用
- URAL 1017 Staircases
- ECMAScript 6 类 应用
- OOM与memory leak区别
- EXTJS学习笔记:grid之gridview
- 51nod 1347 旋转字符串
- Matlab中cell数组的使用
- Spring 整合 Redis详细
- orm
- 全排列算法实现 分治策略
- java中的日期处理类总结