By
汤桂川 @广发证券
爱Coding,也爱Traveling
@ 腾讯 - AlloyTeam 前端工程师
@ 广发证券 - 前端技术专家
① ES6介绍
② ES6实战开发
Angular - ES6
Angular 2.0
Babel
jspm, Webpack, Gulp
Linting, Debug , Test
React, Node, Meteor - ES6
③ 发展趋势
JavaScript简史
Brendan Eich @Netscape
->1993年的小鲜肉
ECMAScript 5 在浏览器的实现情况
数据来源:http://kangax.github.io/compat-table/es5/
ECMAScript 6 在浏览器的实现情况
爱看规范的男生运气不会太差。
-- 乔布斯??
声明 - Declarations
var num = 222;
if (true) {
num = 666;
let num;
console.log('此时的num是什么:' + num );
}
for (var i=0; i<6; i++) {
setTimeout(function() {
console.log(i)
},0);
}
for (let i=0; i<6; i++) {
setTimeout(function() {
console.log(i)
},0);
}
const name = 'object name';
let obj = {
name,
init() {
// Lexical this
$.on('click', () => this.name);
}
};
// 以上代码等同于 ES5
var name = 'object name';
var obj = {
name: name,
init: function init() {
var _this = this;
$.on('click', function () {
return _this.name;
});
}
};
严格模式下,模块里顶层的this是undefined
//改造一下上面例子,this变成什么?
let obj = {
init: ()=> this
};
// 上面代码等同于:
var obj = {
init: function test() {
return undefined;
}
};
More detail in:
// 多行字符串,引号
var multiStr = `In 'JavaScript' this is
not legal.`;
// 字符串插值
var name = "QCon", time = "today";
console.log(`Hello ${name},
how are you ${time}?`);
More detail in:
class Animal {
constructor(name) {
this.name = name;
}
say(msg){
alert(`${this.name} says ${msg}`);
}
static staticMethod() {
return '不能被实例继承,子类可继承父类';
}
}
class Panda extends Animal {
say(msg = 'hi') {
super(msg); // 调用父类say方法
}
}
let panda = new Panda('Tuan');
panda.say(); // 'Tuan says hi'
panda.say('Ooooh'); // 'Tuan says Ooooh'
// 上面代码转换为ES5
'use strict';
function _inherits(subClass, superClass) {
if (typeof superClass !== 'function' && superClass !== null) {
throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass);
} subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ superClass;
}
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
var Animal = (function () {
function Animal(name) {
_classCallCheck(this, Animal);
this.name = name;
}
Animal.prototype.say = function say(msg) {
alert(this.name + ' says ' + msg);
};
Animal.staticMethod = function staticMethod() {
return '不能被实例继承,子类可继承父类';
};
return Animal;
})();
var Panda = (function (_Animal) {
_inherits(Panda, _Animal);
function Panda() {
_classCallCheck(this, Panda);
_Animal.apply(this, arguments);
}
Panda.prototype.say = function say() {
var msg = arguments.length <= 0 || arguments[0] === undefined ? 'hi' : arguments[0];
_Animal.prototype.say.call(this, msg); // 调用父类say方法
};
return Panda;
})(Animal);
var panda = new Panda('Tuan');
panda.say(); // 'Tuan says hi'
panda.say('Ooooh'); // 'Tuan says Ooooh'
// 好
class SomeClass {
constructor() {
// constructor
}
get aval() {
// public getter
}
set aval(val) {
// public setter
}
doSth() {
// 公用方法
}
get _aval() {
// private getter
}
set _aval() {
// private setter
}
_doSth() {
// 私有方法
}
}
// 模块导入
import { lightRed } from './colors';
import { Component } from 'angular2/core';
import * as UserModule from './user.module';
let userCtrl = UserModule.ctrl;
// 模块导出
export { userCtrl };
export class App{
constructor() {}
};
export default lightRed;
AMD, CommonJS, UMD
More Detail in: 下一代模块化的js
var webpackOptions = {
resolve: {
root: [
path.resolve(__dirname, "../src/app"),//根路径
path.resolve(__dirname, "../../public-modules")
],
extensions: ['', '.js'],
alias: {
functions: "utils/functions.js" // 配置需要的文件别名
}
}
};
//import {resolveInject} from '../../../../public-modules/utils/functions';
import {resolveInject} from 'functions';
查看详情: ES6features(中文版)
⬇️
Babel
⬇️
Webpack & Gulp & JSPM
⬇️
ESlint
⬇️
Debug & Unit Test
⬇️
React , Node, Meteor - ES6
angular.module('myapp', ['localInfos'])
.service('locationService', ['localInfo', '$q',
function(localInfo, $q) {
$scope.localInfo = localInfo;
// 打印当前状态
$scope.printInfo = function(msg) {
msg = msg || 'unknown';
console.log('State:' + msg);
};
// 寻找当前位置
$scope.findLocation = function() {
var deferred = $q.defer();
var self = this;
navigator.geolocation.getCurrentPosition(function(pos) {
pos = pos || {};
self.printInfo('Location');
self.localInfo.save(pos);
deferred.resolve('You are at ' + pos.coords.latitude);
}, deferred.reject);
return deferred.promise;
};
}
]);
angular.module('myapp', ['localInfos'])
.service('locationService', LocationService);
class LocationService {
constructor(localInfo, $q) {
'ngInject';
this.localInfo = localInfo;
this.$q = $q;
}
// 打印当前状态
printInfo(msg = 'unknown') {
console.log(`State: ${msg}`);
}
// 寻找位置
findLocation() {
return this.$q((resolve, reject) => {
navigator.geolocation.getCurrentPosition((pos = {}) => {
this.printInfo('Location');
this.localInfo.save(pos);
resolve(`You are at ${pos.coords.latitude}`);
}, reject);
});
}
}
// 'app/index.js'
import angular from 'angular';
import UserService from './user.service';
import UserController from './user.controller';
angular.module('myApp',[])
.factory('userService', UserService)
.controller('userController', UserController);
使用gulp-inject进行自动import与组装angular模块
Note: 文件遵循自动化命名规范(如: shop.controller.auto.js)
// 变成自动注入与Angular模块组装
import ShopController from './shop.controller.auto';
angular.module('shop',[])
.controller('shopController', ShopController);
// "shop/shop.module.js"
import { ShopController } from './shop/shop.controller';
import { ShopService } from './shop/shop.service';
let ctrl = ShopController;
let svc = ShopService.init;
export { svc };
export { ctrl };
另一种按页面进行分模块导入导出,
并可DIY暴露特定方法的模式
// 调用方 'index.js'
import * as ShopModules from './shop/shop.module';
angular.module('microshop',[])
.factory('shopSvc', ShopModules.svc)
.controller('shopCtrl', ShopModules.ctrl);
// 'user.service.js'
class UserService {
constructor($http) {
'ngInject';
this.$http = $http;
this.userUrl = '/serve/user/';
}
getUser(name = 'Hanmeimei') {
return this.$http.get(this.userUrl + name)
.then((response) => response.data);
}
}
export default UserService;
'ngInject': 使用ng-annotate进行DI依赖自动注入
<div ng-app="myApp" ng-strict-di>
'ng-strict-di': missing DI annotations; ng 1.3 or later
AtScript vs TypeScript
No $scope, controller, default 2-way data binding
No $watch, $apply: Zone.js
(events) , [properties]
// Angular 2.0
import { UnicornHorn } from "../animals/unicorn";
class UnicornHype {
constructor(unicornHorn:UnicornHorn) {
this.horn = unicornHorn;
}
findUnicorn() {
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition((pos) => {
this.horn.thrust();
resolve(`The unicorn is at ${pos.coords.latitude}`);
}, reject);
});
}
}
// Angular ES6
angular.module('test', ['unicorn']).service('unicornHype', UnicornHype);
class UnicornHype {
constructor(unicornHorn, $q) {
'ngInject';
this.horn = unicornHorn;
this.$q = $q;
}
findUnicorn() {
return this.$q((resolve, reject) => {
navigator.geolocation.getCurrentPosition((pos) => {
this.horn.thrust();
resolve(`The unicorn is at ${pos.coords.latitude}`);
}, reject);
});
}
}
More Info about Angular 2.0:
Angular - ES6
⬇️
⬇️
Webpack & Gulp & JSPM
⬇️
ESlint
⬇️
Debug & Unit Test
⬇️
React , Node, Meteor - ES6
1.Compatibility(支持度高):
2.生态圈与社区成熟:
More Detail:
// ES6
(...args) => args
// 转换为ES5
(function () {
for (
var _len = arguments.length,
args = Array(_len),
_key = 0;
_key < _len;
_key++
) {
args[_key] = arguments[_key];
}
return args;
});
Angular - ES6
⬇️
Babel
⬇️
⬇️
ESlint
⬇️
Debug & Unit Test
⬇️
React , Node, Meteor - ES6
// gulp与babel结合
var gulp = require("gulp");
var babel = require("gulp-babel");
gulp.task("default", function () {
return gulp.src("src/app.js")
.pipe(babel())
.pipe(gulp.dest("dist"));
});
Angular - ES6
⬇️
Babel
⬇️
⬇️
ESlint
⬇️
Debug & Unit Test
⬇️
React , Node, Meteor - ES6
<!-- index.html -->
<script src="jspm_packages/system.js">
</script>
<script src="config.js"></script>
<script>
System.import('./app/index');
</script>
// config.js
System.config({
"baseURL": "/",
"transpiler": "babel",
"paths": {
"*": "*.js",
"github:*": "jspm_packages/github/*.js"
}
});
-- local git repos, Github, NPM, Bower
Angular - ES6
⬇️
Babel
⬇️
Webpack & Gulp & JSPM
⬇️
⬇️
Debug & Unit Test
⬇️
React , Node, Meteor - ES6
The pluggable linting utility for JavaScript and JSX
Angular - ES6
⬇️
Babel
⬇️
Webpack & Gulp & JSPM
⬇️
ESlint
⬇️
⬇️
React , Node, Meteor - ES6
Angular - ES6
⬇️
Babel
⬇️
Webpack & Gulp & JSPM
⬇️
ESlint
⬇️
⬇️
React , Node, Meteor - ES6
Setting up the test environment:
ES6 化的单元测试
// karma.config.js
module.exports = function(config) {
config.set({
browsers: ['PhantomJS'],
frameworks: ['jasmine'],
webpack: {
module: {
loaders: [{
test: /\.js/,
loader: 'babel-loader',
exclude: /node_modules/
}]
},
watch: true
}
});
};
// test.js
export class Calculator{
add(op1,op2){
return op1 + op2;
}
subtract(op1,op2){
return op1 - op2;
}
}
// calculator-spec.js
import {Calculator} from './calculator';
describe('Calculator', () => {
it('should add two numbers', () => {
let calculator = new Calculator();
let sum = calculator.add(1,4);
expect(sum).toBe(5);
});
it('should subtract two numbers', () => {
let calculator = new Calculator();
let sum = calculator.subtract(4,1);
expect(sum).toBe(3);
});
});
Angular - ES6
⬇️
Babel
⬇️
Webpack & Gulp & JSPM
⬇️
ESlint
⬇️
Debug & Unit Test
⬇️
export class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: props.initialCount};
}
tick() {
this.setState({count: this.state.count + 1});
}
render() {
return (
<div onClick={this.tick.bind(this)}>
Clicks: {this.state.count}
</div>
);
}
}
Counter.propTypes = {
initialCount: React.PropTypes.number
};
Counter.defaultProps = { initialCount: 0 };
Angular - ES6
⬇️
Babel
⬇️
Webpack & Gulp & JSPM
⬇️
ESlint
⬇️
Debug & Unit Test
⬇️
Angular - ES6
⬇️
Babel
⬇️
Webpack & Gulp & JSPM
⬇️
ESlint
⬇️
Debug & Unit Test
⬇️
ES6 is now the official JavaScript
of the Meteor platform.
Every new Meteor project now uses ES6
by default, in every JS file.
方案生命周期 - stages:
Stage 0 : Strawman 建议方案
Stage 1 : Proposal 提案
Stage 2 : Draft 草案
Stage 3 : Candidate 候选方案
Stage 4 : Finished 定案
EMCAScript 2016
2. Exponentiation Operator (乘方)
[1,2,3,NaN].includes(NaN) === true
[1,2,3, -0].includes(0) === true
['a', 'b', 'c'].includes('a', 'b') === true
// 数字vs字母vs数字字符串混合
let cubed = 3 ** 4; // 3*3*3*3
Stage 0
Stage 1
Stage 2
Stage 3
{
"plugins": [
["transform-async-to-module-method", {
"module": "bluebird",
"method": "coroutine"
}]
]
}
<thank-you author="汤桂川" [date]="'2016.04'">
</thank-you>
Homework