[关闭]
@GivenCui 2017-05-24T22:01:08.000000Z 字数 33685 阅读 823

ES6学习

ES6


重点归纳

参考
ECMAScript6入门--阮一峰
Babel在线编译器

开发工具--atom

vim基本操作

  1. vi/vim package.json // 查看package.json
  2. ESC // 恢复到正常模式
  3. : // 进入命令模式
  4. :w // 保存 (write to disk)
  5. :q // 不保存退出
  6. :wq / ZZ / :x // 保存后退出
  7. :q! / ZQ // 强制退出(不保存)

TODO

前端模板和模板引擎

1.LoDash/underScore

不算模板引擎, 只是方法
Eng v4.17
中 v4.16

2. artTemplate

aui/artTemplate · GitHub

3. jade

需要运行node上 (算后端模板?)

express

mockjs


Chapter01 --课程简介

1~1 --课程简介

对象拷贝

ES6对象拷贝

  1. Object.assign({t:1},{k:2})

ES5对象拷贝

  1. //TODO

函数默认参数

ES6

  1. function hello(txt="hello world") {
  2. console.log(txt);
  3. }

ES5

  1. function hello(txt) {
  2. var txt = txt || 'hello world';
  3. console.log(txt);
  4. }

字符串模板

ES6

  1. var name = 'moe';
  2. var txt = `hello ${name}`; // 此处为` `

ES5

  1. // 引入 LoDash/undersore.js
  2. var compiled = _.template("hello: <%= name %>");
  3. compiled({name: 'moe'});

重点项

  1. 解构赋值
  2. 箭头函数
  3. Set和Map
  4. 异步操作
  5. 类与对象
  6. 模块化

必学原因

1.很多第三方库源码是ES6

vue.js
Element (饿了么的UI)
D3 (图表业务和图表动画)

2.Vue,React,Angular都用到了ES6

构建工具

  1. gulp
  2. balel
  3. webpack
  4. npm

学习顺序

构建工具 > 基础语法 > 实战演练 (express和mockjs)

实战项目介绍

  1. 是彩票业务
  2. 属于电商网站中较复杂的部分

预备知识

  1. 模块化概念
  2. 工程构建
  3. 编程经验

Chapter02 --项目构建

2~1 --项目构建介绍

2~2 --项目目录创建

安装express

  1. express 中文API
  2. express generator 中文API
  1. 1. 安装node
  2. 2. 配置npm的全局模块的存放路径以及cache路径
  3. npm config set prefix "...\nodejs\node_global"
  4. npm config set cache "...\nodejs\node_cache"
  5. 3. 安装Express Express应用生成器
  6. npm install express -g // express -V查看报错
  7. npm install express-generator -g // express -V查看成功
  8. 4. express -h // 查看支持的命令
  9. 5. express demo1 -e . // 当前目录下创建demo1应用, 以ejs为模板
  10. 6. win系统下树形结构显示文件目录结构
  11. tree // 查看
  12. tree /f > ***.txt // 输出当前目录结构到***.txt中

2~3 --命令行处理,编写js编译任务脚本

args.js (命令行参数解析)

  1. /* yargs包, 为了区分命令行中的option */
  2. // option('production') => gulp --production
  3. import yargs from 'yargs';
  4. const args = yargs
  5. .option('production',{
  6. boolean : true,
  7. default : false,
  8. describe : 'min all scripts'
  9. })
  10. .option('watch',{
  11. boolean : true,
  12. default : false,
  13. describe : 'watch all filse'
  14. })
  15. .option('verbose',{
  16. boolean : true,
  17. default : false,
  18. describe : 'log'
  19. })
  20. .option('sourcemaps',{
  21. describe : 'force the creation of sourcemaps'
  22. })
  23. .option('port',{
  24. string : true,
  25. default : 8080,
  26. describe : 'server port'
  27. })
  28. .argv
  29. export default args; // 模块暴露出去!!!!!

scripts.js

  1. import gulp from 'gulp';
  2. import gulpif from 'gulp-if'; // gulp语句中作if判断
  3. import concat from 'gulp-concat'; // gulp字符串拼接
  4. import webpack from 'webpack'; // webpack
  5. import gulpWebpack from 'webpack-stream'; // 让gulp支持webpack(流操作)
  6. import named from 'vinyl-named'; // 文件别名,标志
  7. import livereload from 'gulp-livereload'; // 热更新
  8. import plumber from 'gulp-plumber'; // 处理文件信息流 (水管工)
  9. import rename from 'gulp-rename'; // 文件重命名
  10. import uglify from 'gulp-uglify'; // js,css压缩
  11. import {log,colors} from 'gulp-util'; // 命令行输出加强
  12. import args from './util/args'; // 命令行参数解析 (自定义)
  13. gulp.task('scripts',()=>{
  14. return gulp.src(['app/js/index.js'])
  15. .pipe(plumber({
  16. errorHandler : function () {
  17. }
  18. }))
  19. .pipe(named()) // ? vinyl-named
  20. .pipe(gulpWebpack({
  21. module : {
  22. loaders : [{
  23. test:/\.js$/,
  24. loader:'babel'
  25. }]
  26. }
  27. }), null, (err, stats) => {
  28. log(`Finished '${colors.cyan('scripts')}'` ,stats.toString({
  29. chunks:false
  30. }))
  31. })
  32. .pipe(gulp.dest('server/public/js')) // 输出路径
  33. .pipe(rename({
  34. basename:'cp', // copy
  35. extname:'.min.js'
  36. }))
  37. .pipe(uglify({
  38. compress : {
  39. properties : false
  40. },
  41. output : {
  42. 'quote_keys' : true
  43. }
  44. }))
  45. .pipe(gulp.dest('server/public/js'))
  46. .pipe(gulpif(args.watch,livereload())) // 判断如果命令有watch则livereload热更新
  47. })

安装包

  1. // 注意 yargs
  2. npm install gulp gulp-if gulp-concat webpack webpack-stream vinyl-named gulp-livereload gulp-rename gulp-uglify gulp-util yargs --save-dev
  3. // yarn
  4. yarn add gulp gulp-if gulp-concat webpack webpack-stream vinyl-named gulp-livereload gulp-rename gulp-uglify gulp-util yargs --dev
  5. /* 注意 */
  6. yarn add package -dev/-D => npm install package --save-dev
  7. yarn add package => npm install package --save

2~4 --创建模板,服务器任务脚本

pages.js

  1. import gulp from 'gulp';
  2. import gulpif from 'gulp-if';
  3. import livereload from 'gulp-livereload';
  4. import args from './util/args';
  5. gulp.task('pages',()=>{
  6. return gulp.src('app/**/*.ejs')
  7. .pipe(gulp.dest('server'))
  8. .pipe(gulpif(args.watch,livereload()))
  9. })

css.js

  1. import gulp from 'gulp';
  2. import gulpif from 'gulp-if';
  3. import livereload from 'gulp-livereload';
  4. import args from './util/args';
  5. gulp.task('css',()=>{
  6. return gulp.src('app/**/*.css')
  7. .pipe(gulp.dest('server/public'))
  8. .pipe(gulpif(args.watch,livereload()))
  9. })

server.js

  1. import gulp from 'gulp';
  2. import gulpif from 'gulp-if';
  3. import liveserver from 'gulp-live-server';
  4. import args from './util/args';
  5. gulp.task('server',(cb)=>{
  6. if(!args.watch) return cb(); // args.watch 返回Boolean
  7. var server = liveserver.new(['--harmony','server/bin/www']); // --harmpny 在当前命令行执行后面的脚本 www.js
  8. server.start(); // 启动服务器
  9. // 监听server目录下的js和ejs文件的变化让浏览器热更新(自动刷新)
  10. gulp.watch(['server/public/**/*.js','server/views/**/*.ejs'],function(file){
  11. server.notify.apply(server,[file]);
  12. })
  13. // 监听路由改变时重新启动服务器
  14. gulp.watch(['server/routes/**/*.js', 'server/app.js'], function () {
  15. server.start.bind(server)()
  16. })
  17. })

2~5 --文件自动监听,项目构建测试

编写gulp任务

browser.js

  1. import gulp from 'gulp';
  2. import gulpif from 'gulp-if';
  3. import livereload from 'gulp-livereload';
  4. import gutil from 'gulp-util'; // 命令行输出加强
  5. import args from './util/args';
  6. gulp.task('browser',(cb)=>{
  7. if(!args.watch) return cb();
  8. gulp.watch('app/**/*.js',['scripts']); // 调用scripts任务, 在scripts.js
  9. gulp.watch('app/**/*.ejs',['pages']);
  10. gulp.watch('app/**/*.css',['css']);
  11. })

clean.js

  1. import gulp from 'gulp';
  2. import del from 'del';
  3. import args from './util/args';
  4. gulp.task('clean',()=>{
  5. return del(['server/public', 'server/views']) // 删除server/public和server/views目录中的内容
  6. })

build.js

  1. /* 按照特定的顺序串联所有的任务 */
  2. import gulp from 'gulp';
  3. import gulpSequence from 'gulp-sequence';
  4. gulp.task('build',gulpSequence('clean', 'css', 'pages', 'scripts', ['browser','server'])) // 仔细理解

default.js

  1. /* 为了偷懒 */
  2. import gulp from 'gulp';
  3. gulp.task('default',['build']);

gulpfile.babel.js

  1. /* 所有的任务都导入到gulpfile.js中 */
  2. import requireDir from 'require-dir';
  3. requireDir('./tasks');

.babelrc

  1. {
  2. "presets" : ["es2015"]
  3. }
  4. // TODO:想要支持IE8还需要其他配置

package.json

  1. {
  2. "name": "es6",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "index.js",
  6. "scripts": {
  7. "test": "echo \"Error: no test specified\" && exit 1"
  8. },
  9. "author": "",
  10. "license": "ISC",
  11. "devDependencies": {
  12. "babel-core": "^6.24.1",
  13. "babel-loader": "^7.0.0",
  14. "babel-preset-env": "^1.4.0",
  15. "babel-preset-es2015": "^6.24.1",
  16. "connect-livereload": "^0.6.0",
  17. "del": "^2.2.2",
  18. "gulp": "^3.9.1",
  19. "gulp-concat": "^2.6.1",
  20. "gulp-if": "^2.0.2",
  21. "gulp-live-server": "^0.0.30",
  22. "gulp-livereload": "^3.8.1",
  23. "gulp-plumber": "^1.1.0",
  24. "gulp-rename": "^1.2.2",
  25. "gulp-sequence": "^0.4.6",
  26. "gulp-uglify": "^2.1.2",
  27. "gulp-util": "^3.0.8",
  28. "require-dir": "^0.3.1",
  29. "vinyl-named": "^1.1.0",
  30. "webpack": "^2.5.1",
  31. "webpack-stream": "^3.2.0",
  32. "yargs": "^8.0.1"
  33. }
  34. }

gulp的cli

  1. gulp --watch // --watch对应args.watch 来自yargs包

修改server下的app.js

只有这样才能热更新

  1. // line23后新添加代码
  2. app.use(require('connect-livereload')()); // 后添加的中间件, 搜索热更新原理,用于接收热更新

Chapter03 --es6语法

3~1 --let/const命令 (块作用域)

const -> constant 常量;不变的
es6中很多功能都需要运行在"use strict";下
babel等默认添加严格模式语句

作用域

  1. // ES5
  2. 全局作用域
  3. 函数作用域 function(){}
  4. // ES6
  5. ES5基础上增加块作用域 {}

let

  1. /* 1. let声明变量只在块作用域内有效 (for, if, {}等) */
  2. for (let i = 0; i < 10; i++) {}
  3. console.log(i); //ReferenceError: i is not defined
  4. // for循环还有一个特别之处,就是循环语句部分是一个父作用域,而循环体内部是一个单独的子作用域
  5. for (let i = 0; i < 3; i++) { // 父作用域
  6. let i = 'abc'; // 子作用域
  7. console.log(i); // abc *3次
  8. }
  9. /* 2. let不能重复声明 */
  10. {
  11. let a =1;
  12. let a =2;
  13. }
  14. {
  15. let a=1;
  16. var a=1;
  17. }
  18. /* 3. 不存在变量提升 */
  19. // var 的情况
  20. console.log(foo); // 输出undefined
  21. var foo = 2;
  22. // let 的情况
  23. console.log(bar); // 报错ReferenceError
  24. let bar = 2;
  25. /* 4. 暂时性死区 (temporal dead zone,简称 TDZ) */
  26. // let在整个{}中都存在TDZ
  27. var tmp = 123;
  28. if (true) {
  29. tmp = 'abc'; // ReferenceError
  30. let tmp;
  31. }
  32. // 报错
  33. let x = x; // ReferenceError: x is not defined

const

用来定义常量, read-only(只读)
对于基本数据类型(值类型), 值不可变
对于引用类型, 值(指向堆内存的地址)不可变, 但对象的成员可以变
其他同let

块级作用域的好处


  1. // 自执行函数
  2. (function(){
  3. // do something
  4. })()
  5. // 块
  6. {
  7. // do something
  8. }

3~2 --解构赋值

  1. // 数组结构赋值
  2. {
  3. let a,b,rest;
  4. [a,b]=[1,2];
  5. console.log(a,b);
  6. }
  7. // ...rest的应用
  8. {
  9. let a,b,rest;
  10. [a,b,...rest]=[1,2,3,4,5,6];
  11. console.log(a,b,rest);
  12. }
  13. // 默认值情况
  14. {
  15. let a,b,c,rest;
  16. [a,b,c=3]=[1,2]; // 默认值可被覆盖, 若不设置c=undefined
  17. console.log(a,b,c);
  18. }
  19. /* 对象结构赋值 */
  20. {
  21. let a,b;
  22. ({a,b}={a:1,b:2}); // 括号不能省略, 为了区分模式还是表达式
  23. console.log(a,b);
  24. }
  25. {
  26. let {a,b}={a:1,b:2}; // 方法二, 不用括号
  27. console.log(a,b);
  28. }
  29. // 默认值
  30. {
  31. let {a=10,b=5}={a:3};
  32. console.log(a,b);
  33. }
  34. {
  35. let {a:a,b:b,c=100}={a:1,b:2}; // 实质,默认值
  36. console.log(a,b,c);
  37. }
  38. {
  39. let {a:x,b:y,c:z=1000}={a:1,b:2}; // 改变量名的情况,默认值
  40. console.log(x,y,z);
  41. // console.log(a,b,c); // a,b,c只是键而不是变量
  42. }
  43. /* 应用场景 */
  44. // 变量互换值
  45. {
  46. let a=1;
  47. let b=2;
  48. [a,b]=[b,a];
  49. console.log(a,b); // 2 1
  50. }
  51. // 对象返回数组
  52. {
  53. function f(){
  54. return [1,2]
  55. }
  56. let a,b;
  57. [a,b]=f();
  58. console.log(a,b); // 1 2
  59. }
  60. // 空位
  61. {
  62. function f(){
  63. return [1,2,3,4,5]
  64. }
  65. let a,b,c;
  66. [a,,,b]=f();
  67. console.log(a,b); // 1 4
  68. }
  69. // 其余,和空位
  70. {
  71. function f(){
  72. return [1,2,3,4,5]
  73. }
  74. let a,b,c;
  75. [a,,...b]=f();
  76. console.log(a,b); // 1 [3,4,5]
  77. }
  78. // json数据
  79. {
  80. let metaData={
  81. title:'abc',
  82. test:[{
  83. title:'test',
  84. desc:'description'
  85. }]
  86. }
  87. let {title:esTitle,test:[{title:cnTitle}]}=metaData;
  88. console.log(esTitle,cnTitle); // abc test
  89. }

3~3 --正则扩展

  1. /*
  2. * 正则拓展
  3. */
  4. /*
  5. * 回顾: ES5中正则的用法
  6. * 1. RegExp对象的方法 exec()和test()
  7. * var reg = /pattern/ 或 new RegExp() reg.lastIndex 匹配位置
  8. * reg.exec(string) 返回值为数组 [result],只有一个值, arr.index
  9. *
  10. reg.test(string) 返回值为true/false
  11. *
  12. *2. String对象的方法: search() match() repalce() split()字符串按规则拆分成数组
  13. *
  14. */
  15. /*
  16. * ES6新增
  17. *
  18. * 属性: flags, sticky
  19. *
  20. * u修饰符 针对Unicode中大于\uffff的部分
  21. * y修饰符 sticky粘连模式
  22. * 后行断言 (ES5有先行断言)
  23. *
  24. *
  25. */
  26. {
  27. // #构造函数#
  28. let regex = new RegExp('xyz', 'i'); //第一个参数是字符串,第二个是修饰符
  29. let regex2 = new RegExp(/xyz/i); //第一个参数是正则表达式,不接受第二个参数,否则会报错
  30. console.log(regex.test('xyz123'), regex2.test('xyz123')); // true true
  31. console.log(regex.test('xyZ123'), regex2.test('xyZ123')); // true true
  32. let regex3 = new RegExp(/abc/ig, 'i'); // ES6中改变
  33. //原有正则对象的修饰符是ig,它会被第二个参数i覆盖
  34. console.log(regex3.flags); // i new RegExp()中的第二个参数
  35. }
  36. // 字符串对象的4个使用正则表达式的方法: match(),replace(),search(),split()这四个方法全部调用RegExp的实例的方法。
  37. {
  38. let regex = new RegExp('xyz', 'ig');
  39. console.log(regex.test('xyz0XYZ1xyz2'), regex.exec('xyz0XYZ1xyz2'));
  40. }
  41. // y修饰符
  42. {
  43. let s = 'bbbb_bbb_bb_b';
  44. var a1 = /b+/g;
  45. var a2 = /b+/y;
  46. console.log(a1.exec(s), a2.exec(s)); // ["bbbb"],["bbbb"]
  47. console.log(a1.exec(s), a2.exec(s)); // ["bbb"],null
  48. console.log(a1.sticky, a2.sticky); //表示是否开启了粘连模式
  49. }
  50. // u修饰符
  51. {
  52. console.log('u修饰符',/^\uD83D/.test('\uD83D\uDC2A')); // true
  53. console.log('u修饰符',/^\uD83D/u.test('\uD83D\uDC2A')); // false
  54. // 大括号表示Unicode字符,只有加上u才能识别
  55. console.log(/\u{61}/.test('a')); // false
  56. console.log(/\u{61}/u.test('a')); // true
  57. console.log(/\u{20BB7}/u.test('𠮷')); // true
  58. // 点(.)字符不能识别码点大于0xFFFF的Unicode字符,必须加上u修饰符。
  59. let s = '𠮷';
  60. console.log('大于0xFFFF的Unicode字符',/^.$/.test(s)); // false
  61. console.log('使用u字符',/^.$/u.test(s)); // true
  62. // 使用u修饰符后,所有量词都会正确识别大于码点大于0xFFFF的Unicode字符。
  63. console.log('量词',/a{2}/.test('aa')); // true
  64. console.log('量词',/a{2}/u.test('aa')); // true
  65. console.log('量词',/𠮷{2}/.test('𠮷𠮷')); // false
  66. console.log('量词',/𠮷{2}/u.test('𠮷𠮷')); // true
  67. }
  68. {
  69. // #正则表达式中,点(.)是一个特殊字符,代表任意的单个字符,但是行终止符(line terminator character)除外
  70. // U+000A 换行符(\n)
  71. // U+000D 回车符(\r)
  72. // U+2028 行分隔符(line separator)
  73. // U+2029 段分隔符(paragraph separator)
  74. // 只是一个提案目前还不支持
  75. // let reg=/test.go/s;
  76. // console.log(reg.test('test\ngo'));
  77. // console.log(reg.test('test\ngo'));
  78. console.log('s变通方法',/foo.bar/.test('foo\nbar'));
  79. console.log('s变通方法',/foo[^]bar/.test('foo\nbar'));
  80. }

3~4/5 --字符串拓展(上/下)

  1. /*
  2. * 字符串的拓展
  3. *
  4. *Unicode > \uffff 需要{}
  5. */
  6. // /u{****} 正确识别 > \uffff
  7. {
  8. console.log('a',`\u0061`); // a
  9. console.log('s',`\u20BB7`); // /u20BB 和7
  10. console.log('s',`\u{20BB7}`); // 𠮷
  11. }
  12. // stri.codePointAt()
  13. {
  14. let s='𠮷';
  15. console.log('length',s.length); // 2 识别错误
  16. console.log('0',s.charAt(0));
  17. console.log('1',s.charAt(1));
  18. console.log('at0',s.charCodeAt(0)); // 55362
  19. console.log('at1',s.charCodeAt(1)); // 57271
  20. let s1='𠮷a';
  21. console.log('length',s1.length);
  22. console.log('code0',s1.codePointAt(0)); // 134071
  23. // "20bb7" 十六进制 parseInt("20bb7",16) 或 parseInt(0x20bb7)--> 134071
  24. console.log('code0',s1.codePointAt(0).toString(16));
  25. console.log('code1',s1.codePointAt(1)); // 𠮷的另一部分 (错误)
  26. console.log('code2',s1.codePointAt(2)); // 97 -> a
  27. }
  28. // String.fromCodePoint()
  29. {
  30. console.log(String.fromCharCode("0x20bb7"));
  31. console.log(String.fromCodePoint("0x20bb7")); // 正确
  32. }
  33. // for-of才能正确处理字符串的个数
  34. {
  35. let str='\u{20bb7}abc';
  36. for(let i=0;i<str.length;i++){
  37. console.log('es5',str[i]);
  38. }
  39. for(let code of str){
  40. console.log('es6',code);
  41. }
  42. }
  43. // str.includes()
  44. // str.startsWith()
  45. // str.endsWith()
  46. {
  47. let str="string";
  48. console.log('includes',str.includes("c"));
  49. console.log('start',str.startsWith('str'));
  50. console.log('end',str.endsWith('ng'));
  51. }
  52. // str.repeat() 重复
  53. {
  54. let str="abc";
  55. console.log(str.repeat(2));
  56. }
  57. // ` `和 ${} 字符串模板
  58. {
  59. let name="list";
  60. let info="hello world";
  61. let m=`i am ${name},${info}`;
  62. console.log(m);
  63. }
  64. // str.padStart() 前补白 eg. 时间日期的补全 15:3:2 --> 15:03:02
  65. // str.padEnd() 后补白
  66. {
  67. let [a,b] = ['1','8']
  68. console.log(a.padStart(2,'0'));
  69. console.log(b.padEnd(2,'0'));
  70. }
  71. // 标签模板 (tagged template)
  72. // 标签模板其实不是模板,而是函数调用的一种特殊形式。
  73. {
  74. let user={
  75. name:'list',
  76. info:'hello world'
  77. };
  78. console.log(abc`i am ${user.name},${user.info}`);
  79. function abc(s,v1,v2){ // s对应数组,其中s.raw指向数组本身 , v1,v2对应${}
  80. console.log(s,v1,v2); // ['i am ', ',', ''], 'list', 'hello world'
  81. return s+v1+v2
  82. }
  83. }
  84. // String.raw`标签模板用法` '\n' --> '\\n'
  85. {
  86. console.log(String.raw`Hi\n${1+2}`);
  87. console.log(`Hi\n${1+2}`);
  88. }

3~6 --数值拓展

  1. /*
  2. * 数值的拓展
  3. * console.dir(Number) 可以查看对象里面的属性和方法
  4. */
  5. // 规范了数字二进制和八进制表示法
  6. // 大小写都可以
  7. {
  8. console.log('B',0B1111); // 0b1111 b -> binary
  9. console.log(0O17); // 0o17 o -> octonary
  10. }
  11. // isFinite --> Number.isFinite
  12. // parseInt --> Number.parseInt
  13. // 'parseInt' in Number // true
  14. {
  15. console.log('15',Number.isFinite(15)); // true
  16. console.log('NaN',Number.isFinite(NaN)); // false
  17. console.log('1/0',Number.isFinite('true'/0)); // false
  18. console.log('NaN',Number.isNaN(NaN)); // true
  19. console.log('0',Number.isNaN(0)); // false
  20. }
  21. // 新增 Number.isInteger()判断整数
  22. {
  23. console.log('25',Number.isInteger(25)); // true
  24. console.log('25.0',Number.isInteger(25.0)); // true
  25. console.log('25.1',Number.isInteger(25.1)); // false
  26. console.log('25.1',Number.isInteger('25')); // false
  27. }
  28. // (-2^53 ,2^53)期间里的为安全整数, 超出后计算不准
  29. {
  30. Math.pow(2, 53); // 9007199254740992
  31. Math.pow(2, 53) === Math.pow(2, 53) + 1; // true 说明不准了
  32. console.log(Number.MAX_SAFE_INTEGER,Number.MIN_SAFE_INTEGER); // 9007199254740991 -9007199254740991
  33. console.log('10',Number.isSafeInteger(10)); // true
  34. console.log('a',Number.isSafeInteger('a')); // false
  35. }
  36. // Math.trunc() 去除一个数的小数部分,返回整数部分
  37. // 相当于 正数时, 相当于 Math.floor()
  38. // 相当于 负数时, 相当于 Math.ceil()
  39. {
  40. console.log(4.1,Math.trunc(4.1)); // 4
  41. console.log(4.9,Math.trunc(4.9)); // 4
  42. console.log(-4.1,Math.trunc(-4.1)); // -4
  43. console.log(4.1,Math.floor(4.1)); // 4
  44. console.log(-4.1,Math.floor(-4.1)); // -5
  45. // 原理
  46. Math.trunc = Math.trunc || function(x) {
  47. return x < 0 ? Math.ceil(x) : Math.floor(x);
  48. };
  49. }
  50. // 判断正数, 负数, 还是0, 它会返回五种值。
  51. // 参数为正数,返回+1;
  52. // 参数为负数,返回-1;
  53. // 参数为0,返回0;
  54. // 参数为-0,返回-0;
  55. // 其他值,返回NaN。
  56. {
  57. Math.sign(-5); // -1
  58. Math.sign(5); // +1
  59. Math.sign(0); // +0
  60. Math.sign(-0); // -0
  61. Math.sign(NaN); // NaN
  62. Math.sign('foo'); // NaN
  63. Math.sign(); // NaN
  64. }
  65. // 求立方根 cube root -> cbrt
  66. {
  67. console.log('-1',Math.cbrt(-1));
  68. console.log('8',Math.cbrt(8));
  69. }

3~7 --数组拓展

  1. // Array.of() 将一组值,转换为数组
  2. // Array.of基本上可以用来替代Array()或new Array(),并且不存在由于参数不同而导致的重载。它的行为非常统一
  3. {
  4. let arr = Array.of(3,4,7,9,11);
  5. console.log('arr=',arr); // [3,4,7,9,11]
  6. let empty=Array.of();
  7. console.log('empty',empty); // []
  8. }
  9. // Array.from() 两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象
  10. // 类数组 对象中有length属性的
  11. // arrayLike = {
  12. // '0': 'a',
  13. // '1': 'b',
  14. // '2': 'c',
  15. // length: 3
  16. // };
  17. // dom集合
  18. {
  19. let p = document.querySelectorAll('p'); // 类数组
  20. let pArr = Array.from(p); // 转为数组
  21. pArr.forEach(function(item){ // 使用数组的forEach方法
  22. // console.log(item.textContent); // 获取文本节点
  23. console.log(item.innerHTML); // 获取文本节点
  24. });
  25. // Array.from(arg1,arg2) arg2类似map
  26. console.log(Array.from([1,3,5],function(item){return item*2})); // 返回结果组成的数组
  27. }
  28. // 数组实例的fill() 填充数组
  29. {
  30. console.log('fill-7',[1,'a',undefined].fill(7)); // [7,7,7]
  31. console.log('fill,pos',['a','b','c'].fill(7,1,3)); // [a,7,7]
  32. }
  33. // 数组实例keys()和values()和entries()
  34. {
  35. for(let index of ['1','c','ks'].keys()){
  36. console.log('keys',index); // 0 1 2
  37. }
  38. // values未实现,需要 babel-polyfill
  39. for(let value of ['1','c','ks'].values()){
  40. console.log('values',value); // 1 2 ks
  41. }
  42. for(let [index,value] of ['1','c','ks'].entries()){
  43. console.log('entries',index,value);
  44. }
  45. }
  46. // [].copyWithin(target, start, end)
  47. {
  48. console.log([1,2,3,4,5].copyWithin(0,3,4)); // [4,2,3,4,5]
  49. }
  50. // [].find(cb), [].findIndex(cb) 返回符合回调函数中条件的项
  51. {
  52. console.log([1,2,3,4,5,6].find(function(item){return item>3}));
  53. console.log([1,2,3,4,5,6].findIndex(function(item){return item>3}));
  54. }
  55. // [].includes() 类似indexOf(), 但能处理NaN
  56. {
  57. console.log('number',[1,2,NaN].includes(1));
  58. console.log('number',[1,2,NaN].includes(NaN));
  59. }

3~8 --函数拓展

  1. // 默认值
  2. {
  3. function test(x, y = 'world',z){ //
  4. console.log('默认值',x,y);
  5. }
  6. test('hello'); // 默认值 hello world
  7. test('hello','kill'); // 默认值 hello world
  8. }
  9. { // 作用域问题
  10. let x='test';
  11. function test2(x,y=x){
  12. console.log('作用域',x,y);
  13. }
  14. test2('kill'); // kill kill
  15. test2(); // undefined undefined
  16. }
  17. // rest参数 (函数定义时)
  18. {
  19. function test3(...arg){ // rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中
  20. for(let v of arg){
  21. console.log('rest',v);
  22. }
  23. }
  24. test3(1,2,3,4,'a'); // 正常传参
  25. }
  26. // 拓展运算符 (在函数调用时使用) 去掉数组的[]
  27. {
  28. console.log(...[1,2,4]);
  29. console.log('a',...[1,2,4]);
  30. }
  31. // 箭头函数
  32. {
  33. let arrow = v => v*2;
  34. let arrow2 = () => 5;
  35. console.log('arrow',arrow(3)); // 6
  36. console.log(arrow2()); // 5
  37. }
  38. // 尾调用 (尾调用是函数的最后一步操作) 提升性能的, 用来尾递归
  39. {
  40. function tail(x){
  41. console.log('tail',x);
  42. }
  43. function fx(x){
  44. return tail(x) // 尾调用
  45. }
  46. fx(123)
  47. // 也是尾调用
  48. function f(x) {
  49. if (x > 0) {
  50. return m(x)
  51. }
  52. return n(x);
  53. }
  54. }

3~9 --对象拓展

  1. // 对象
  2. // 简洁表示法
  3. {
  4. // 属性
  5. let o=1,k=2;
  6. let es6={
  7. o,
  8. k
  9. };
  10. console.log(es6);
  11. // 方法
  12. let es6_method={
  13. hello(){
  14. console.log('hello');
  15. }
  16. };
  17. console.log(es6_method.hello());
  18. }
  19. // 属性表达式
  20. // [Symbol]
  21. {
  22. let a='b';
  23. let es6_obj={
  24. [a]:'c' // b:'c'
  25. }
  26. console.log(es6_obj); // {b:'c'}
  27. }
  28. // 新增API
  29. // Object.is(a,b) 判断a,b是否相等
  30. // Object.assign(o1,o2) 浅拷贝 o2->o1
  31. // Object.entries() 配合iterator, 返回[key,value]
  32. {
  33. console.log('字符串',Object.is('abc','abc'),'abc'==='abc');
  34. console.log('NaN',Object.is(NaN,NaN),NaN===NaN);
  35. console.log('数组',Object.is([],[]),[]===[]);
  36. console.log('拷贝',Object.assign({a:'a'},{b:'b'}));
  37. let test={k:123,o:456};
  38. for(let [key,value] of Object.entries(test)){
  39. console.log([key,value]);
  40. }
  41. }
  42. // 拓展运算符
  43. // {...o1,...o2} <=> 相当于 Object.assign(o1,o2)
  44. // ES7的方案
  45. {
  46. // 扩展运算符
  47. // let {a,b,...c}={a:'test',b:'kill',c:'ddd',d:'ccc'};
  48. // c={
  49. // c:'ddd',
  50. // d:'ccc'
  51. // }
  52. }

3~10 --Symbol用法

第七种原生数据类型

  1. {
  2. // Symbol为第七种原生数据类型
  3. let s = Symbol(); // 不用new(), Symbol不是构造函数
  4. typeof s // "symbol"
  5. /* Symbol的用法 */
  6. // Symbol.for('tag')会注册在全局作用域
  7. // Symbol.for('a3')多次运行结果唯一
  8. // Symbol()每次运行返回新结果
  9. let a1=Symbol();
  10. let a2=Symbol();
  11. console.log(a1===a2); // false
  12. let a3=Symbol.for('tag3');
  13. let a4=Symbol.for('tag3');
  14. console.log(a3===a4); // true
  15. }
  16. {
  17. let a1=Symbol.for('abc');
  18. let obj={
  19. [a1]:'123', // 对象的属性表达式
  20. 'abc':345,
  21. 'c':456
  22. };
  23. console.log('obj',obj);
  24. // 不能遍历Symbol属性
  25. for(let [key,value] of Object.entries(obj)){
  26. console.log('let of',key,value);
  27. }
  28. // Object.getOwnPropertySymbols()只获取Symbol的属性,返回值数组
  29. console.log(Object.getOwnPropertySymbols(obj));
  30. Object.getOwnPropertySymbols(obj).forEach(function(item){
  31. console.log(obj[item]); // 123
  32. })
  33. // Reflect.ownkeys()获取包括Symbol的所有属性, 返回值为数组
  34. console.log(Reflect.ownKeys(obj));
  35. Reflect.ownKeys(obj).forEach(function(item){
  36. console.log('ownkeys',item,obj[item]);
  37. })
  38. }

3~11 --set/map数据结构

  1. /* Set和Map */
  2. // Set
  3. // 声明和add添加值
  4. // Set中的key值唯一
  5. // size属性获取长度
  6. {
  7. let list = new Set();
  8. list.add(5);
  9. list.add(7);
  10. console.log(list,list.size); // Set{5,7} 2
  11. }
  12. // 接收数组为参数初始化化
  13. {
  14. let arr = [1,2,3,4,5,1,2,3];
  15. let list = new Set(arr);
  16. console.log(list,list.size); // Set{1,2,3,4,5} 5
  17. }
  18. {
  19. let list = new Set();
  20. list.add(1);
  21. list.add(2);
  22. list.add(1); // 重复值可以操作, 但不生效
  23. console.log('list',list); // Set{1,2}
  24. let arr=[1,2,3,1,'2',NaN,NaN];
  25. let list2=new Set(arr);
  26. console.log('unique',list2); // Set{1,2,3,'2',NaN}
  27. // 利用Set的key不能重复,为数组去重
  28. function unique(arr) {
  29. return Array.from(new Set(arr)); //等价 [...new Set(arr)]
  30. }
  31. }
  32. // Set的API
  33. // add 添加key
  34. // delete 删除key
  35. // has 判断key是否存在
  36. // clear 清空所有key
  37. {
  38. let arr=['add','delete','clear','has'];
  39. let list=new Set(arr);
  40. console.log('has',list.has('add')); // true
  41. console.log('delete',list.delete('add'),list); // true Set{'delete','clear','has'}
  42. list.clear();
  43. console.log('list',list); // Set{} 完全清空
  44. }
  45. //遍历Set中的内容
  46. // for-of 配合keys()
  47. // for-of 配合values()
  48. // for-of 配合entries()
  49. // forEach遍历
  50. {
  51. let arr=['add','delete','clear','has'];
  52. let list=new Set(arr);
  53. for(let key of list.keys()){
  54. console.log('keys',key);
  55. }
  56. for(let value of list.values()){
  57. console.log('value',value);
  58. }
  59. for(let [key,value] of list.entries()){
  60. console.log('entries',key,value);
  61. }
  62. for(let a of list.entries()){
  63. console.log('entries',a);
  64. }
  65. list.forEach(function(item){console.log(item);})
  66. }
  67. // WeakSet
  68. // 成员只能是对象,而不能是其他类型的值
  69. // WeakSet 不可遍历
  70. // 没有size属性
  71. // 对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用
  72. // 没有clear方法
  73. // API: add, has, delete
  74. {
  75. let weakList=new WeakSet();
  76. let arg={};
  77. console.log(weakList.size); // undefined
  78. console.log(weakList.forEach); // undefined
  79. let add = weakList.add(arg);
  80. let has = weakList.has(arg);
  81. let d = weakList.delete(arg);
  82. console.log(add,has,d); // WeakSet {} true true
  83. }
  84. // Map
  85. // “键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键
  86. // Object 结构提供了“字符串—值”的对应,Map结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现
  87. // API:
  88. // size属性
  89. // set(key,value) // 而Set添加时add()
  90. // get(key) // Set没有get, 因为只有一个值
  91. // has(key)
  92. // delete(key)
  93. // clear
  94. {
  95. let map = new Map();
  96. let arr=['123'];
  97. map.set(arr,456);
  98. console.log('map',map,map.get(arr)); // Map {["123"] => 456} 456
  99. }
  100. {
  101. let map = new Map([['a',123],['b',456]]);
  102. console.log('map args',map); // Map {"a"=>123,"b"=>456}
  103. console.log('size',map.size); // 2
  104. console.log('delete',map.delete('a'),map); // Map {"b"=>456}
  105. console.log('clear',map.clear(),map); // Map{}
  106. }
  107. // weakMap
  108. // key只能是对象
  109. // 没有size属性, 没有clear方法
  110. // 键名所指向的对象,不计入垃圾回收机制
  111. {
  112. let weakmap=new WeakMap();
  113. let o={};
  114. weakmap.set(o,123);
  115. console.log(weakmap.get(o));
  116. weakmap.size // undefined
  117. weakmap.forEach // undefined
  118. weakmap.clear // undefined
  119. }

3~12 --set/map与数组和对象的对比

  1. /* Array, Map, Set数据结构的横向对比 */
  2. {
  3. // map与array
  4. let map = new Map();
  5. let array = [];
  6. // 增
  7. map.set('t',1);
  8. array.push({t:1});
  9. console.log('(map | array 增)',map,array);
  10. // 查
  11. let m = map.has('t');
  12. let a = array.find(item=>item.t); // find中的回调表示若对象存在item.t属性, 返回该对象
  13. console.log('(map | array 查)',m,a);
  14. // 改
  15. map.set('t',2);
  16. array.forEach(item=>item.t?item.t=2:''); // 先匹配后修改
  17. console.info('(map | array 改)',map,array)
  18. // 删
  19. map.delete('t');
  20. let idx = array.findIndex(item=>item.t);
  21. array.splice(idx,1);
  22. console.info('(map | array 删)',map,array)
  23. }
  24. {
  25. // set和array的对比
  26. let o1 = {t:1};
  27. let o2 = {t:2};
  28. let set = new Set();
  29. let array = [];
  30. // 增
  31. set.add(o1);
  32. array.push(o2);
  33. console.info('(set | array 增)',set,array);
  34. // 查
  35. let s = set.has(o1);
  36. let a = array.find(item=>item===o2);
  37. console.info('(set | array 查)',s,a)
  38. // 改
  39. set.forEach(item=>item.t?item.t=111:'');
  40. array.forEach(item=>item.t?item.t=222:'')
  41. console.info('(set | array 改)',set,array)
  42. // 删
  43. set.forEach(item=>item.t?set.delete(item):undefined); // 间接用到set.delete()
  44. let idx = array.findIndex(item=>item.t);
  45. array.splice(idx,1);
  46. console.info('(set | array 删)',set,array)
  47. }
  48. {
  49. // set,map,Objec
  50. let item = {t:1};
  51. let map = new Map();
  52. let set = new Set();
  53. let obj = {};
  54. // 增
  55. map.set('t',1)
  56. set.add(item)
  57. obj.t = 1;
  58. console.info('(map|set|obj 增)',map,set,obj);
  59. // 查
  60. console.info('(map|set|obj 查)',map.has('t'),set.has(item),'t' in obj)
  61. // 改
  62. map.set('t',3);
  63. item.t = 4; // set中的是引用
  64. obj.t = 2;
  65. console.info('(map|set|obj 改)',map,set,obj);
  66. // 删
  67. map.delete('t');
  68. set.delete(item);
  69. delete obj.t;
  70. console.info('(map|set|obj 删)',map,set,obj);
  71. }

3~13 --Proxy和Reflect

Proxy 对象代理, 拦截
Reflect 用来代替Object的部分方法 (Reflect.ownKeys()必会)

  1. /* Proxy和Reflect */
  2. {
  3. let obj={
  4. time:'2017-03-11',
  5. name:'net',
  6. _r:123
  7. };
  8. // monitor为Proxy实例
  9. // monitor映射obj, 改变obj某些操作的默认行为
  10. // monitor拦截/代理了对obj的相关操作
  11. let monitor=new Proxy(obj,{
  12. // 拦截对象属性的读取
  13. get(target,key){
  14. return target[key].replace('2017','2018')
  15. },
  16. // 拦截对象设置属性
  17. // 限制处name属性外的其他属性修改
  18. set(target,key,value){
  19. if(key==='name'){
  20. return target[key]=value; // 只有name属性可写
  21. }else{
  22. return target[key];
  23. }
  24. },
  25. // 拦截key in object操作
  26. has(target,key){
  27. if(key==='name'){
  28. return target[key] // 只有name被 in
  29. }else{
  30. return false;
  31. }
  32. },
  33. // 拦截delete
  34. deleteProperty(target,key){
  35. if(key.indexOf('_')>-1){ // 属性中有'_'可以被删除
  36. delete target[key];
  37. return true;
  38. }else{
  39. return target[key]
  40. }
  41. },
  42. // 拦截Object.keys,Object.getOwnPropertySymbols,Object.getOwnPropertyNames
  43. ownKeys(target){
  44. return Object.keys(target).filter(item=>item!='time') // 返回不等time的属性, 返回值为数组
  45. }
  46. });
  47. // Proxy实例get,读取相关操作
  48. console.log('get',monitor.time,monitor); // 2017-> 2018
  49. // Proxy实例set,写入相关操作
  50. monitor.time='2018';
  51. monitor.name='mukewang';
  52. console.log('set',monitor.time,monitor,typeof monitor);
  53. console.log(obj);
  54. // key in object操作
  55. console.log('has','name' in monitor,'time' in monitor); // true false
  56. // delelte操作
  57. // delete monitor.time;
  58. // console.log('delete',monitor);
  59. //
  60. delete monitor._r;
  61. console.log('delete',monitor);
  62. // 拦截Object.keys,Object.getOwnPropertySymbols,Object.getOwnPropertyNames
  63. // Reflect.ownKeys也受影响??
  64. console.log('keys',Object.keys(monitor));
  65. console.log('getOwnPropertySymbols',Object.getOwnPropertySymbols(monitor));
  66. console.log('getOwnPropertyNames',Object.getOwnPropertyNames(monitor));
  67. console.log('ownKeys',Reflect.ownKeys(monitor)); // Reflect.ownKeys也受影响
  68. }
  69. // Reflect对象放置一些属于Object中属于语言内部的方法
  70. // Object.defineProperty() <--> Reflect.defineProperty()
  71. // 对象命令式操作
  72. // delete obj.name --> Reflect.deleteProperty(obj,name)
  73. // name in obj --> Reflect.has(obj,name)
  74. {
  75. let obj={
  76. time:'2017-03-11',
  77. name:'net',
  78. _r:123
  79. };
  80. console.log('Reflect get',Reflect.get(obj,'time')); // 读属性
  81. Reflect.set(obj,'new','Reflect test'); // 写
  82. console.log('set',obj);
  83. console.log('has',Reflect.has(obj,'name')); // [prop] in Object
  84. Reflect.deleteProperty(obj,'new'); // delete object[prop]
  85. console.log('deleteProperty',obj);
  86. // Reflect.apply(target,thisArg,args)
  87. // 一般来说,如果要绑定一个函数的this对象,
  88. // 可以这样写fn.apply(obj, args),
  89. // 但是如果函数定义了自己的apply方法,
  90. // 就只能写成Function.prototype.apply.call(fn, obj, args)
  91. // 采用Reflect对象可以简化这种操作。
  92. // 老写法
  93. let f1 = Function.prototype.apply.call(Math.floor, undefined, [1.75]) // 1
  94. let f2 = Math.floor.apply(undefined,[1.75]) // 1
  95. // 新写法
  96. let f3 = Reflect.apply(Math.floor, undefined, [1.75]) // 1
  97. console.log('Reflect.apply()',f1,f2,f3)
  98. // Reflect.ownKeys(target)
  99. let cc = Symbol('c');
  100. let o11 = {
  101. a : 'aa',
  102. b : 'bb',
  103. [cc] : 'cc'
  104. }
  105. Object.defineProperty(o11, 'key', {
  106. enumerable: false,
  107. value : 'enumerable_false'
  108. });
  109. console.log(Object.keys(o11)); // 能枚举的和不是Symbol的
  110. console.log(Object.getOwnPropertyNames(o11)); // 包括不能枚举的
  111. console.log(Object.getOwnPropertySymbols(o11)); // 只包括Symbol
  112. console.log(Reflect.ownKeys(o11)); // 所有
  113. }
  114. // Proxy的应用场景
  115. // 和数据类型解耦的校验模块
  116. {
  117. function validator (target, validator) {
  118. return new Proxy(target,{
  119. _validator: validator,
  120. set(target,key,value,proxy){ // proxy-> receiver proxy对象本身或原型链上的
  121. if (target.hasOwnProperty(key)) {
  122. let va = this._validator[key];
  123. if(!!va(value)) { // 比如执行了name(val)
  124. return Reflect.set(target,key,value,proxy) // 正常赋值
  125. } else {
  126. throw Error(`不能设置${key}到${value}`)
  127. }
  128. } else{
  129. throw Error(`${key} 不存在`)
  130. }
  131. }
  132. })
  133. }
  134. // 对应handler的校验规则对象
  135. const personValidators = {
  136. name(val){
  137. return typeof val === 'string'
  138. },
  139. age(val){
  140. return typeof val === 'number' && val>18
  141. }
  142. }
  143. class Person{
  144. constructor(name,age){
  145. this.name = name;
  146. this.age=age;
  147. return validator(this,personValidators)
  148. }
  149. }
  150. const person = new Person('Lilei',30) // 是一个Proxy对象
  151. console.log(person);
  152. // person.name = 123; // 不是字符串, 报错
  153. // person.age = 12; // 小于18 报错
  154. person.name = '韩梅梅';
  155. console.log(person.name);
  156. }

3~14 --类与对象

class, constructor, extends, static(只适用静态方法)
super()
getter, setter

  1. /*
  2. * class类
  3. * 关键字 : class constructor extends super() static
  4. */
  5. {
  6. // 基本定义和生成实例
  7. class Parent {
  8. constructor(name='mukewang') { // 构造函数
  9. this.name =name;
  10. }
  11. }
  12. let v_parent = new Parent('v');
  13. console.log('构造函数和实例', v_parent);
  14. }
  15. {
  16. /*继承*/
  17. class Parent {
  18. constructor(name = 'GivenCui 父类') {
  19. this.name = name;
  20. }
  21. }
  22. class Child extends Parent {
  23. constructor(name='child'){
  24. // super(); // 不传参数,默认使用父类参数
  25. super(name); // 传参覆盖父类
  26. this.type = 'child'; // 子类的参数必须放在super()后
  27. }
  28. }
  29. var p = new Parent('父类 -')
  30. var child = new Child('子类 --')
  31. console.log('父类', p);
  32. console.log('继承extends & super', child)
  33. }
  34. {
  35. // getter, setter
  36. class Parent{
  37. constructor(name="父类"){
  38. this.name = name;
  39. }
  40. get longName(){
  41. return 'getter' + this.name;
  42. }
  43. set longName(value){
  44. this.name = value;
  45. }
  46. }
  47. let v= new Parent();
  48. console.log('getter',v, v.longName);
  49. v.longName = 'Kitty';
  50. console.log('setter',v,v.longName);
  51. }
  52. {
  53. // 静态方法
  54. class Parent{
  55. constructor(name="父类"){
  56. this.name = name;
  57. }
  58. static tell(){ // 类上的方法
  59. return '我是静态方法--通过类调用';
  60. }
  61. }
  62. console.log('static静态方法',Parent.tell());
  63. }
  64. {
  65. // 静态属性
  66. class Parent{
  67. constructor(name="父类"){
  68. this.name = name;
  69. }
  70. }
  71. Parent.type = '静态属性(暂时还没有关键字)';
  72. console.log('静态属性',Parent.type);
  73. }

3~15 --Promise

  1. /*
  2. * Promise
  3. * Promise 是异步编程的一种解决方案
  4. * Promise对象代表一个异步操作,有三种状态:
  5. * Pending(进行中)、
  6. * Resolved(已完成,又称 Fulfilled)
  7. * Rejected(已失败)
  8. */
  9. { // 普通的回调的写法
  10. let ajax = function(callback){
  11. console.log('callback: 执行01');
  12. setTimeout(function(){
  13. callback&&callback.call()
  14. }, 1000)
  15. console.log('callback: 执行03')
  16. };
  17. ajax(function () {
  18. console.log('callback: 执行02');
  19. })
  20. }
  21. {
  22. // Promise的写法
  23. let ajax = function () {
  24. console.log('Promise1: 执行1');
  25. return new Promise(function (resolve, reject) {
  26. setTimeout(function () {
  27. resolve();
  28. }, 1000)
  29. console.log('Promise1: 执行3');
  30. })
  31. // return 后面写代码没用
  32. }
  33. ajax().then(function () {
  34. console.log('Promise1: 执行2');
  35. }, function () {
  36. console.log('Promise1: 执行2');
  37. })
  38. }
  39. {
  40. // Promise的多步回调 A->B->C
  41. // then()的回调中返回new Promise即可
  42. // new Promise(function(resolve,reject){}).then(rs,rj).then(rs,rj).then(rs,rj)
  43. let ajax = function () {
  44. console.log('Promise2: 执行1');
  45. return new Promise(function (resolve, reject) {
  46. setTimeout(function () {
  47. resolve();
  48. }, 1000)
  49. })
  50. // return 后面写代码没用
  51. }
  52. var step2 = ajax().then(function () {
  53. /* resolve */
  54. console.log('Promise2: 执行2');
  55. return new Promise(function (resolve,reject) {
  56. setTimeout(function () {
  57. resolve();
  58. },1000)
  59. })
  60. }, function () {
  61. /* reject */
  62. })
  63. step2.then(function () {
  64. /* resolve */
  65. return new Promise(function (resolve,reject) {
  66. console.log('Promise2: 执行3');
  67. setTimeout(function () {
  68. resolve()
  69. },1000)
  70. })
  71. },function () {
  72. /* reject */
  73. }).then(function () {
  74. /* resolve */
  75. console.log('Promise2: 执行4');
  76. },function () {
  77. /* reject */
  78. })
  79. }
  80. { // catch()捕获错误
  81. // catch()也接收reject的情况
  82. let ajax=function(num){
  83. console.log('执行4');
  84. return new Promise(function(resolve,reject){
  85. if(num>5){
  86. resolve()
  87. }else{
  88. reject()
  89. throw new Error('出错了')
  90. }
  91. })
  92. }
  93. ajax(6).then(function(){
  94. console.log('log',6);
  95. }).catch(function(err){
  96. console.log('catch',err);
  97. });
  98. // ajax(3).then(function(){
  99. // console.log('log',3);
  100. // }).catch(function(err){
  101. // console.log('catch',err);
  102. // });
  103. }
  104. { // Promise.all()静态方法
  105. // 所有图片加载完再添加到页面
  106. function loadImg(src){
  107. return new Promise((resolve,reject)=>{
  108. let img=document.createElement('img');
  109. img.src=src;
  110. img.onload=function(){
  111. resolve(img); // 创建的img
  112. }
  113. img.onerror=function(err){
  114. reject(err);
  115. }
  116. })
  117. }
  118. function showImgs(imgs){
  119. let box = document.createElement('div');
  120. box.className = 'imgBox_all';
  121. imgs.forEach(function(img){
  122. box.appendChild(img); // 插入
  123. })
  124. document.body.appendChild(box);
  125. }
  126. // Promise.all([promise对象])
  127. // 返回值为新的promise实例
  128. Promise.all([
  129. loadImg('http://mvimg1.meitudata.com/5555435ce56169374.jpg'),
  130. loadImg('http://img5.duitang.com/uploads/item/201603/03/20160303200058_nXiHv.jpeg'),
  131. loadImg('http://mvimg1.meitudata.com/563369a719e204730.jpg')
  132. ]).then(showImgs)
  133. }
  134. { // Promise.race() 静态方法
  135. function loadImg(src){
  136. return new Promise((resolve,reject)=>{
  137. let img=document.createElement('img');
  138. img.src=src;
  139. img.onload=function(){
  140. resolve(img);
  141. }
  142. img.onerror=function(err){
  143. reject(err);
  144. }
  145. })
  146. }
  147. function showImgs(img){
  148. document.querySelector('.imgBox_race').appendChild(img)
  149. }
  150. // Promise.race([promise实例数组])
  151. // 最快的那个
  152. Promise.race([
  153. loadImg('http://mvimg1.meitudata.com/5555435ce56169374.jpg'),
  154. loadImg('http://img5.duitang.com/uploads/item/201603/03/20160303200058_nXiHv.jpeg'),
  155. loadImg('http://mvimg1.meitudata.com/563369a719e204730.jpg')
  156. ]).then(showImgs)
  157. }

3~16 --Iterator

  1. /*
  2. * Iterator和for...of循环
  3. 遍历器的本质: 指针对象 , 指针是next()
  4. */
  5. {
  6. let arr = ['hello','world'];
  7. let map = arr[Symbol.iterator]();
  8. console.log(map,typeof map);
  9. console.log('第1次',map.next()); // {value: "hello", done: false}
  10. console.log('第2次',map.next()); // {value: "world", done: false}
  11. console.log('第3次',map.next()); // {value: undefined, done: true}
  12. }
  13. {
  14. // object默认没有iterator接口
  15. // 自定义object的iterator接口
  16. let obj = {
  17. start : [1,3,2],
  18. end : [7,9,8],
  19. [Symbol.iterator](){ // 111
  20. let self = this;
  21. let index = 0;
  22. let arr = self.start.concat(self.end); // [1,3,2,7,9,8]
  23. let len = arr.length;
  24. return { // 2222
  25. next(){ // 333
  26. if(index < len){
  27. return { // 444
  28. value:arr[index++],
  29. done:false
  30. }
  31. }else{
  32. return {
  33. value:undefined,
  34. done:true
  35. }
  36. }
  37. }
  38. }
  39. }
  40. }
  41. // 用 for-of验证
  42. for(let key of obj) {
  43. console.log(key)
  44. }
  45. console.log('start' in obj);
  46. }

3~17 --Generator

Generator 函数是 ES6 提供的一种异步编程解决方案

    从语法上,首先可以把它理解成,Generator函数是一个状态机,封装了多个内部状态。

    执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。

    形式上,Generator函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。

  1. /*
  2. * Generator (返回为itorator接口)
  3. * next函数的用法
  4. * yield*的语法
  5. * function* (){yield或yield*}
  6. */
  7. {
  8. // genertaor基本定义
  9. let tell=function* (){
  10. console.log('a阶段')
  11. /* step1 */
  12. yield 'a'; // .next() step1
  13. console.log('b阶段')
  14. /* step2 */
  15. yield 'b'; // .next() step2
  16. console.log('c阶段')
  17. /* step3 */
  18. return 'c' // .next() step3
  19. };
  20. let k=tell(); // 不运行, 返回一个指针对象(iterator)
  21. console.log('yield',k, typeof k); // Generator{} object
  22. console.log(k.next()); // {value:'a',done:false}
  23. console.log(k.next()); // {value:'b',done:false}
  24. console.log(k.next()); // {value:'c',done:true}
  25. console.log(k.next()); // {value:undefined,done:true}
  26. }
  27. {
  28. // 内部用yiled写可以简化
  29. let obj={};
  30. obj[Symbol.iterator]=function* (){
  31. yield 1;
  32. yield 2;
  33. yield 3;
  34. }
  35. for(let value of obj){
  36. console.log('value',value);
  37. }
  38. }
  39. { // 事物只有三种状态: A, B, C
  40. let state=function* (){
  41. while(1){
  42. yield 'A';
  43. yield 'B';
  44. yield 'C';
  45. }
  46. }
  47. let status=state();
  48. console.log(status.next());
  49. console.log(status.next());
  50. console.log(status.next());
  51. console.log(status.next());
  52. console.log(status.next());
  53. }
  54. // async语法 (generator的一个语法糖)
  55. // 去掉*, yiled换成await
  56. // 需要babel安装对应的插件
  57. // {
  58. // let state=async function (){
  59. // while(1){
  60. // await 'A';
  61. // await 'B';
  62. // await 'C';
  63. // }
  64. // }
  65. // let status=state();
  66. // console.log(status.next());
  67. // console.log(status.next());
  68. // console.log(status.next());
  69. // console.log(status.next());
  70. // console.log(status.next());
  71. // }
  72. /* 实例: 抽奖和长轮询 */
  73. // 抽奖逻辑
  74. {
  75. let draw=function(count){
  76. // 具体抽奖逻辑
  77. console.info(`剩余${count}次`)
  78. }
  79. let residue=function* (count){
  80. while (count>0) {
  81. count--;
  82. yield draw(count);
  83. }
  84. }
  85. let star=residue(5);
  86. let btn=document.createElement('button');
  87. btn.id='start';
  88. btn.textContent='抽奖';
  89. document.body.appendChild(btn);
  90. document.getElementById('start').addEventListener('click',function(){
  91. star.next();
  92. },false)
  93. }
  94. // 长轮循
  95. {
  96. // 长轮询
  97. let ajax=function* (){
  98. yield new Promise(function(resolve,reject){
  99. setTimeout(function () {
  100. resolve({code:0}) // code:0只执行1次, code:一直轮循不停
  101. }, 200);
  102. })
  103. }
  104. let pull=function(){
  105. let genertaor=ajax();
  106. let step=genertaor.next();
  107. step.value.then(function(d){
  108. if(d.code!=0){
  109. setTimeout(function () {
  110. console.info('wait');
  111. pull()
  112. }, 1000);
  113. }else{
  114. console.info(d);
  115. }
  116. })
  117. }
  118. pull();
  119. }

3~18 --Decorators

es6修饰器

修饰器(Decorator)是一个函数,用来修改类的行为, 不能用于普通函数.
修饰器可以自定义, 也可引用第三方模块core-decorators.js.

使用decorator之前,需要install一个babel插件 babel-plugin-transform-decorators-legacy,安装完成后配置.babelrc

  1. // 安装插件及配置
  2. yarn add babel-plugin-transform-decorators-legacy -D/--dev
  3. // .babelrc中
  4. "plugins": [
  5. "transform-decorators-legacy" // new add
  6. ]
  1. {
  2. let readonly=function(target,name,descriptor){
  3. // descriptor对象原来的值如下
  4. // {
  5. // value: specifiedFunction,
  6. // enumerable: false,
  7. // configurable: true,
  8. // writable: true
  9. // };
  10. // 定义 Object.defineProperty(obj,{}) | Object.defineProperties(obj,{})
  11. // 查看Object.getOwnPropertyDescriptor(obj,'prop')
  12. descriptor.writable=false;
  13. return descriptor
  14. };
  15. // 针对类的方法
  16. class Test{
  17. @readonly
  18. time(){ // 相当于Test.prototype.time()
  19. return '2017-03-11'
  20. }
  21. }
  22. let test=new Test();
  23. // test.time=function(){ // 赋值报错, 只读
  24. // console.log('reset time');
  25. // };
  26. console.log(test.time());
  27. }
  28. // 针对类
  29. {
  30. let typename=function(target,name,descriptor){
  31. target.myname='hello';
  32. }
  33. @typename
  34. class Test{
  35. }
  36. console.log('类修饰符',Test.myname);
  37. // 第三方库修饰器的js库:core-decorators; yarn add core-decorators -D
  38. }
  39. // 实例
  40. // 日志系统, 数据埋点
  41. // 网站数据统计分析 埋点技术(数据分析第一步)
  42. {
  43. // 自定义修饰器--日志埋点
  44. let log=(type)=>{
  45. return function(target,name,descriptor){
  46. let src_method=descriptor.value;
  47. descriptor.value=(...arg)=>{
  48. src_method.apply(target,arg);
  49. console.info(`log ${type}`);
  50. }
  51. }
  52. }
  53. class AD{
  54. @log('show') // 此处为埋点
  55. show(){
  56. console.info('ad is show')
  57. }
  58. @log('click') // 此处为埋点
  59. click(){
  60. console.info('ad is click');
  61. }
  62. }
  63. let ad=new AD();
  64. ad.show();
  65. ad.click();
  66. }

3~19 --Module模块化

兼容CommonJs(Node),AMD(require.js)
是尽量的静态化,使得编译时就能确定模块的依赖关系
CommonJs,AMD都是运行时确定依赖关系

  1. import 'babel-polyfill'; // 表示执行模块
  2. import './class/lesson3_19'; // 表示执行模块
  1. /* lesson3_19 */
  2. export let A=123; // 导出变量
  3. export function test(){ // 导出函数
  4. console.log('test');
  5. }
  6. export class Hello{ // 导出类
  7. test(){
  8. console.log('class');
  9. }
  10. }
  11. /* index.js */
  12. import {A,test,Hello} from './class/lesson3_19';
  13. console.log(A,test,Hello);
  14. // 只要A
  15. import {A} from './class/lesson3_19';
  16. console.log(A);
  17. // 设置别名
  18. import * as lesson from './class/lesson3_19';
  19. console.log(lesson.A,lesson.test,lesson.Hello);
  1. /* lesson3_19 */
  2. let A=123;
  3. let test=function(){
  4. console.log('test');
  5. }
  6. class Hello{
  7. test(){
  8. console.log('class');
  9. }
  10. }
  11. export default { // 最后一起导出
  12. A,
  13. test,
  14. Hello
  15. }
  16. /* index.js */
  17. import L19 from './class/lesson3_19';
  18. console.log(L19.A,L19.test,L19.Hello);

Chapter04 --项目实战

4~1 --需求分解和目录创建

4~2 --创建倒计时模块

4~3 --创建数据计算模块

4~4 --创建接口模块(上)

4~5 --创建接口模块(下)

4~6 --创建彩票基础模块(上)

4~7 --创建彩票基础模块(中)

4~8 --创建彩票基础模块(下)

4~9 --创建彩票业务模块

4~10 --创建服务接口和模拟数据

4~11 --前后端联调

Chapter05 --课程总结

5~1 --课程总结

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注