1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>ECMAScript6 入门</title> </head> <body> 1.let命令 基本用法,ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块有效。 上面代码在代码块之中,分别用let和var声明了两个变量。然后再代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明let声明的变量只在它所在的代码块有效。
for循环的计数器,就很适合使用let命令。
2.不存在变量提升 var 命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该再声明语句之后才可以使用,为了纠正这种现象,let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
3.暂时性死区 只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。ES6明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死去”(temporal dead zone,简称 TDZ)。
“暂时性死区“也意味着typeof不再是一个百分之百安全的操作。
上面代码中,变量x使用let命令声明,所以在声明之前,都属于x的”死区“,只要用到该变量就会报错。因此,typeof运行时就会抛出一个ReferenceError。
作为比较,如果一个变量根本没有被声明,使用typeof反而不会报错。
4.不允许重复声明
let不允许在相同作用域内,重复声明同一个变量。
2.块级作用域
为什么需要块级作用域?
ES5只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。
第一种场景,内层变量可能会覆盖外层变量。
3.ES6的块级作用域
let实际上为JavaScript新增了块级作用域。
上面的函数有两个代码块,都声明了变量n,运行后输出5。这表示外层代码块不受内层代码块的影响。如果两次都使用var定义变量n,最后输出的值才是10。
ES6 允许块级作用域的任意嵌套。
内层作用域可以定义外层作用不的同名变量。
窥觊作用域的出现,实际上是的获得广泛应用的匿名立即执行函数表达式(匿名IIFE)不再必要了。
4.块级作用域和函数声明
ES5固定,函数智能在顶层作用域和函数作用域之中声明,不能再块级作用域声明。
ES6引入了块级作用域,明确允许在块级作用域之中声明函数。ES6规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
为了减轻因此产生的不兼容问题,ES6在附录B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式。
- 允许在块级作用域内声明函数 - 函数声明类似于var,即会提升到全局作用域或函数作用域的头部 - 同时,函数声明还会提升到所在的块级作用域的头部。
注意,上面三条规则只对ES6的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当做let处理。
根据这三条规则,浏览器的ES6环境中,块级作用域内声明的函数,行为类似于var声明的变量。
考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式而不是函数声明语句。
另外,还有一个需要注意的地方。ES6的块级作用域必须有大括号如果没有大括号,JavaScript引擎就认为不存在块级作用域。
3.const命令
基本用法,const声明一个只读的常量,一旦声明,常量的值就不能改变。const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
const的作用域与let命令相同;挚爱声明所在的块级作用域内有效。
const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
const声明的常量,也与let一样不可重复声明。
本质,const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const智能保证这个指针是固定的(即总是指向一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明未常量必须非常小心。
ES6声明变量的六种方法
ES5只有两种声明变量的方法:var命令和function命令。ES6除了添加let和const命令,另外两种声明变量的方法:import命令和class命令。
4.顶层对象的属性
顶处对象,在浏览器环境指的是window对象,在Node指的是global对象。ES5之中,顶层对象的属性与全局变量是等价的。
顶层对象的属性与全局变量挂钩,被认为是JavaScript语言最大的设计败笔之一。这样额设计带来了几个很大的问题,首先是没法在编译时就报出变量未声明的错误,只有运行时才能知道(因为全局变量可能是顶层对象的属性创造的,而属性的创造是动态的);顶层对象的属性是到处可以读写的,这非常不利于模块化变成,另一个方面,window对象有实体含义,指的是浏览器的窗口对象,顶层对象是一个有实体含义的对象,也是不合适的。
ES6为了改变这一点,一方面固定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令,const命令、class命令声明的全局变量,不属于顶层对象的属性,也就是说,从ES6开始,全局变量将逐步与顶层对象的属性脱钩。
5.gobalThis对象
JavaScript语言存在一个顶层对象,它提供全局环境(即全局作用域),所有代码都是在这个环境中运行。但是,顶层对象在各种实现里面是不统一的。
- 浏览器里面,顶层对象是window,单Node和WebWorker没有window。 - 浏览器和WbeWorker里面,self也指向顶层对象,但是Node没有self。 - Node里面,顶层对象是global,但其他环境都不支持。
同一段代码为了能够在各种环境,都能取到顶层对象,现在一般是使用this变量,但是有局限性。
- 全局环境中,this会返回顶层对象。但是,Node模块和ES6模块中,this返回的是当前模块。 - 函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。 - 不管是严格模式,还是普通模式,new Function('return this')(), 总是会返回全局对象。但是,如果浏览器用了CSP(Content Security Policy,内容安全策略),那么eval、new Function这些方法都可能无法使用。
综上所述,很难找到一种方法,可以在所有情况下,都取到顶层对象。 <script type="text/javascript"> // { // let a = 10; // var b = 1; // } // console.log(b); // console.log(a);
// for(let i = 0; i < 10; i++) { // ... // } // console.log(i);
// var tmp = 123;
// if(true){ // tmp = 'abc'; // let tmp; // } // typeof x; // let x;
// typeof undeclared_variable;
// function func () { // // body... // let a = 10; // var a = 1; // }
// function func () { // let a = 10; // let a = 1; // }
// function func(arg){ // let arg; // }
// func(); // 报错
// function func(arg){ // { // let arg; // } // }
// func() // 不报错
// var tmp = new Date();
// function f() { // console.log(tmp); // if(false){ // var tmp = 'hello world'; // } // }
// f();
// function f1() { // let n = 5; // if(true){ // let n = 10; // } // console.log(n); // } // f1();
// 情况一 // if(true){ // function f() {} // }
// // 情况二 // try { // function f() {
// } // } catch(e) { // // statements // console.log(e); // }
// 上面两种函数声明,根据ES5的规定都是非法的。
// 浏览器的ES6环境
// function f() { console.log('I am outside!');}
// (function(){ // var f = undefined; // if(false){ // function f() {console.log('I am inside!');} // }
// f();
// })();
// Uncaught TYpeError: f is not a function
// const foo = {};
// 为 foor添加一个属性,可以成功 // foo.prop = 123; // foo.prop
// 将foo指向另一个对象,就会报错
// foo = {};
// 方法一 // (typeof window !== 'undefined' // ? window // : (typeof process === 'object' && // typeof require === 'function' && // typeof global === 'object') // ? global // : this);
// 方法二 // var getGlobal = function () { // if (typeof self !== 'undefined') { return self; } // if (typeof window !== 'undefined') { return window; } // if (typeof global !== 'undefined') { return global; } // throw new Error('unable to locate global object'); // }; </script> 变量的解构赋值 1.数组的解构赋值
基本用法,ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
以前,为变量赋值,智能直接指定值
let a = 1; let b = 2; let c = 3; ES6允许写成下面这样 let [a,b,c] = [1,2,3];
本质上,这种写法属于”模式匹配“,只要等号两边的模式相同,左边的变量就会被赋予对应的值。 如果解构不成功,变量的值就等于undefined.
2.默认值
解构赋值允许指定默认值。注意,ES6内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。
3.对象的解构赋值
解构不仅可以用于数组,还可以用于对象。
对象的解析与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
4.默认值
对象的解构也可以指定默认值。
5.注意点
- 如果要将一个已经声明的变量用于解构赋值,必须非常小心。 - 解构赋值允许等号左边的模式之中,不放置任何变量名。因此,可以写出非常古怪的赋值表达式。 - 由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。
6.字符串的解构赋值
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。
类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。
7.数值和布尔值的解构赋值
解构赋值时,如果等号左边是数值和布尔值,则会先转为对象。
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对他们进行解构赋值,都会报错。
8.函数参数的解构赋值,函数的参数也可以使用解构赋值。
9.圆括号问题
解构赋值虽然很方面吧,但是解析起来并不容易,对于编译器来说某一个式子到底是模式,还是表达式,没有办法从一开始就知道,必须解析到(或解析不到)等号才能知道。ES6的规则是,只要有可能导致解构的歧义,就不得使用圆括号。
10.不能使用圆括号的情况
- 变量声明语句 - 函数参数 - 赋值语句的模式 11.可以使用圆括号的情况
可以使用圆括号的情况只有一种:赋值语句的非模式部分,可以使用圆括号。
12.用途 变量的解构赋值用途很多 - 交换变量的值 - 从函数返回多个值 - 函数参数的定义 - 提取JSON数据 - 函数参数的默认值 - 遍历Map结构 - 输入模块的指定方法
<!-- 字符串的扩展 -->
1.字符的Unicode表示法
ES6加强了对Unicode的支持,允许采用\uxxxx形式表示一个字符,其中xxxx表示字符的Unicode码点。但是,这种表示法只限于码点在\u0000~\uFFFF之间的字符。超出这个范围的字符,必须用两个双字节的形式表示。
ES6对这一点做出改进,只要将码点放入大括号,就能正确解读该字符。
大括号标识符与四字节的UTF-16编码是等价的。有了这种表示法之后,JavaScript共有6中方法可以表示一个字符。
'\z' === 'z' // true '\172' === 'z' // true '\x7A' === 'z' // true '\u007A' === 'z' // true '\u{7A}' === 'z' // true
2.字符串的遍历接口
ES6为字符串添加了遍历器接口,是的字符串可以被for...of循环遍历。
除了遍历字符串,这个遍历器最大的优点是可以识别大于0xFFFF的码点,传统的for循环无法识别这样的码点。
3.直接输入U+2028盒U+2029
4.JSON.stringify()的改造
根据标准,JOSN数据必须是UTF-8编码。但是,现在的JSON.stringify()方法有可能返回不符合UTF-8标准的字符串。
5.模板字符串
ES6引入了模板字符串解决这个问题。模板字符串是增强版的字符串,用反引号(`)表示。
6.实例:模板编译
7.标签模板
模板字符串的功能,不仅仅是上面这些。它可以紧跟在一个函数名后面,该函数将被调用了爱处理这个模板字符串。这个被称为"标签模板"功能。
8.模板字符串的限制
前面提到标签模板里面,可以内嵌其他语言。但是,模板字符串默认会将字符串转义,导致无法嵌入其他语言。
<!-- 字符串的新增方法 --> 1.String.fromCodePoint()
ES5 提供String.fromCharCode()方法,用于从 Unicode 码点返回对应字符,但是这个方法不能识别码点大于0xFFFF的字符。
2.String.raw()
ES6 还为原生的 String 对象,提供了一个raw()方法。该方法返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串,往往用于模板字符串的处理方法。
3.codePointAt()
ES6 提供了codePointAt()方法,能够正确处理 4 个字节储存的字符,返回一个字符的码点。
4.normalize()
ES6 提供字符串实例的normalize()方法,用来将字符的不同表示方法统一为同样的形式,这称为 Unicode 正规化。
5.ES6 又提供了三种新方法。 - includes():返回布尔值,表示是否找到了参数字符串。 - startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。 - endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
6.repeat()
repeat方法返回一个新字符串,表示将原字符串重复n次。
7.padStart(),padEnd()
ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。
8.trimStart(),trimEnd()
ES2019 对字符串实例新增了trimStart()和trimEnd()这两个方法。它们的行为与trim()一致,trimStart()消除字符串头部的空格,trimEnd()消除尾部的空格。它们返回的都是新字符串,不会修改原始字符串。
9.matchAll()
matchAll()方法返回一个正则表达式在当前字符串的所有匹配,详见《正则的扩展》的一章。
<!-- 正则的扩展 -->
1.RegExp 构造函数
- 第一种情况是,参数是字符串,这时第二个参数表示正则表达式的修饰符(flag)。 - 第二种情况是,参数是一个正则表示式,这时会返回一个原有正则表达式的拷贝。
2.字符串的正则方法 字符串对象共有 4 个方法,可以使用正则表达式:match()、replace()、search()和split()。
3.u 修饰符 ES6 对正则表达式添加了u修饰符,含义为“Unicode 模式”,用来正确处理大于\uFFFF的 Unicode 字符。也就是说,会正确处理四个字节的 UTF-16 编码。 - 点字符 - Unicode 字符表示法 - 量词 - 预定义模式 - i 修饰符 - 转义
4.RegExp.prototype.unicode 属性 正则实例对象新增unicode属性,表示是否设置了u修饰符。
5.y 修饰符
除了u修饰符,ES6 还为正则表达式添加了y修饰符,叫做“粘连”(sticky)修饰符。
6.RegExp.prototype.sticky 属性
与y修饰符相匹配,ES6 的正则实例对象多了sticky属性,表示是否设置了y修饰符。
7.RegExp.prototype.flags 属性 ES6 为正则表达式新增了flags属性,会返回正则表达式的修饰符。
8.s 修饰符:dotAll 模式
正则表达式中,点(.)是一个特殊字符,代表任意的单个字符,但是有两个例外。一个是四个字节的 UTF-16 字符,这个可以用u修饰符解决;另一个是行终止符(line terminator character)。
所谓行终止符,就是该字符表示一行的终结。以下四个字符属于“行终止符”。
- U+000A 换行符(\n) - U+000D 回车符(\r) - U+2028 行分隔符(line separator) - U+2029 段分隔符(paragraph separator)
9.后行断言 JavaScript 语言的正则表达式,只支持先行断言(lookahead)和先行否定断言(negative lookahead),不支持后行断言(lookbehind)和后行否定断言(negative lookbehind)。ES2018 引入后行断言,V8 引擎 4.9 版(Chrome 62)已经支持。
10.Unicode 属性类
ES2018 引入了一种新的类的写法\p{...}和\P{...},允许正则表达式匹配符合 Unicode 某种属性的所有字符。
11.具名组匹配
正则表达式使用圆括号进行组匹配。ES2018 引入了具名组匹配(Named Capture Groups),允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用。 - 解构赋值和替换,有了具名组匹配以后,可以使用解构赋值直接从匹配结果上为变量赋值。 - 引用,如果要在正则表达式内部引用某个“具名组匹配”,可以使用\k<组名>的写法。 12.String.prototype.matchAll
如果一个正则表达式在字符串里面有多个匹配,现在一般使用g修饰符或y修饰符,在循环里面逐一取出。目前有一个提案,增加了String.prototype.matchAll方法,可以一次性取出所有匹配。不过,它返回的是一个遍历器(Iterator),而不是数组。
<!-- 数值的扩展 -->
1.二进制和八进制表示法
2.Number.isFinite(), Number.isNaN()
3.Number.parseInt(), Number.parseFloat()
4.Number.isInteger()
5.Number.EPSILON
6.安全整数和 Number.isSafeInteger()
7.Math 对象的扩展
8.指数运算符
<!-- 函数的扩展 -->
1.函数参数的默认值 2.rest 参数 3.严格模式 4.name 属性 5.箭头函数 6.尾调用优化 7.函数参数的尾逗号 8.Function.prototype.toString() 9.catch 命令的参数省略
<!-- 数组的扩展 -->
1.扩展运算符 2.Array.from() 3.Array.of() 4.数组实例的 copyWithin() 5.数组实例的 find() 和 findIndex() 6.数组实例的 fill() 7.数组实例的 entries(),keys() 和 values() 8.数组实例的 includes() 9.数组实例的 flat(),flatMap() 10.数组的空位 <!-- 对象的扩展 -->
1.属性的简洁表示法 2.属性名表达式 3.方法的 name 属性 4.属性的可枚举性和遍历 5.super 关键字 6.对象的扩展运算符
<!-- 对象的新增方法 -->
1.Object.is() 2.Object.assign() 3.Object.getOwnPropertyDescriptors() 4.__proto__属性,Object.setPrototypeOf(),Object.getPrototypeOf() 5.Object.keys(),Object.values(),Object.entries() 6.Object.fromEntries()
<!-- Symbol -->
1.概述
ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
2.Symbol.prototype.description
3.作为属性名的 Symbol
4.实例:消除魔术字符串
5.属性名的遍历
6.Symbol.for(),Symbol.keyFor()
7.实例:模块的 Singleton 模式
8.内置的 Symbol 值
<!-- Set 和 Map 数据结构 -->
1.Set ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set本身是一个构造函数,用来生成 Set 数据结构。
Set 结构的实例有以下属性。
- Set.prototype.constructor:构造函数,默认就是Set函数。 - Set.prototype.size:返回Set实例的成员总数。
Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。下面先介绍四个操作方法。
- Set.prototype.add(value):添加某个值,返回 Set 结构本身。 - Set.prototype.delete(value):删除某个值,返回一个布尔值,表示删除是否成功。 - Set.prototype.has(value):返回一个布尔值,表示该值是否为Set的成员。 - Set.prototype.clear():清除所有成员,没有返回值。
Set 结构的实例有四个遍历方法,可以用于遍历成员。
- Set.prototype.keys():返回键名的遍历器 - Set.prototype.values():返回键值的遍历器 - Set.prototype.entries():返回键值对的遍历器 - Set.prototype.forEach():使用回调函数遍历每个成员
2.WeakSet WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。
首先,WeakSet 的成员只能是对象,而不能是其他类型的值。
WeakSet 结构有以下三个方法。
- WeakSet.prototype.add(value):向 WeakSet 实例添加一个新成员。 - WeakSet.prototype.delete(value):清除 WeakSet 实例的指定成员。 - WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在 WeakSet 实例之中。
3.Map
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
Map 结构原生提供三个遍历器生成函数和一个遍历方法。
- Map.prototype.keys():返回键名的遍历器。 - Map.prototype.values():返回键值的遍历器。 - Map.prototype.entries():返回所有成员的遍历器。 - Map.prototype.forEach():遍历 Map 的所有成员。 4.WeakMap
WeakMap结构与Map结构类似,也是用于生成键值对的集合。
WeakMap与Map的区别有两点。
首先,WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名。
其次,WeakMap的键名所指向的对象,不计入垃圾回收机制。
WeakMap只有四个方法可用:get()、set()、has()、delete()。
<!-- ECMAScript 6 Iterator和for...of循环 -->
1.Iterator(遍历器)的概念
Iterator的遍历过程是这样的。
(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
(2)第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
(3)第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
(4)不断调用指针对象的next方法,直到它指向数据结构的结束位置。 2.数据结构的默认Iterator接口 Iterator接口的目的,就是为所有数据结构,提供了一种统一的访问机制,即for...of循环(详见下文)。当使用for...of循环遍历某种数据结构时,该循环会自动去寻找Iterator接口。
在ES6中,有三类数据结构原生具备Iterator接口:数组、某些类似数组的对象、Set和Map结构。
3.调用Iterator接口的场合
- 解构赋值,对数组和Set结构进行解构赋值时,会默认调用Symbol.iterator方法。 - 扩展运算符,扩展运算符(...)也会调用默认的iterator接口。 - yield*,yield*后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口。 - 其他场合,由于数组的遍历会调用遍历器接口,所以任何接受数组作为参数的场合,其实都调用了遍历器接口。下面是一些例子。 for...of Array.from() Map(), Set(), WeakMap(), WeakSet()(比如new Map([['a',1],['b',2]])) Promise.all() Promise.race() 4.字符串的Iterator接口 5.Iterator接口与Generator函数 6.遍历器对象的return(),throw() 7.for...of循环
<!-- ECMAScript 6 Generator 函数 -->
1.简介
Generator函数有多种理解角度。从语法上,首先可以把它理解成,Generator函数是一个状态机,封装了多个内部状态。 2.next方法的参数 yield句本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield语句的返回值。
3.for...of循环
for...of循环可以自动遍历Generator函数时生成的Iterator对象,且此时不再需要调用next方法。 4.Generator.prototype.throw()
Generator函数返回的遍历器对象,都有一个throw方法,可以在函数体外抛出错误,然后在Generator函数体内捕获。 5.Generator.prototype.return()
Generator函数返回的遍历器对象,还有一个return方法,可以返回给定的值,并且终结遍历Generator函数。 6.yield*语句
如果在Generater函数内部,调用另一个Generator函数,默认情况下是没有效果的。 7.作为对象属性的Generator函数 8.Generator函数的this
Generator函数总是返回一个遍历器,ES6规定这个遍历器是Generator函数的实例,也继承了Generator函数的prototype对象上的方法。 9.含义
Generator与状态机 - Generator是实现状态机的最佳结构。比如,下面的clock函数就是一个状态机。
Generator与协程 - 协程与子例程的差异 - 协程与普通线程的差异 10.应用 Generator可以暂停函数执行,返回任意表达式的值。这种特点使得Generator有多种应用场景。 - 异步操作的同步化表达 - 控制流管理 - 部署Iterator接口 - 作为数据结构
<!-- ECMAScript 6 Promise对象 -->
1.Promise的含义 Promise是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了Promise对象。所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。Promise提供统一的API,各种异步操作都可以用同样的方法进行处理。
Promise对象有以下两个特点。
- 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。
Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
2.基本用法
ES6规定,Promise对象是一个构造函数,用来生成Promise实例。 3.Promise.prototype.then() 4.Promise.prototype.catch() 5.Promise.all() 6.Promise.race() 7.Promise.resolve() 8.Promise.reject() 9.两个有用的附加方法 10.应用 <!-- ECMAScript 6 异步操作和Async函数 -->
1.基本概念
ES6诞生以前,异步编程的方法,大概有下面四种。
- 回调函数 - 事件监听 - 发布/订阅 - Promise 对象 ES6将JavaScript异步编程带入了一个全新的阶段,ES7的Async函数更是提出了异步编程的终极解决方案。 2.Generator函数 3.Thunk函数 4.co模块 5.async函数
<!-- ECMAScript 6 Class -->
1.Class基本语法 2.Class的继承 3.原生构造函数的继承 4.Class的取值函数(getter)和存值函数(setter) 5.Class的Generator方法 6.Class的静态方法 7.Class的静态属性和实例属性 8.new.target属性 9.Mixin模式的实现
<!-- ECMAScript 6 修饰器(Decorator) --> 1.类的修饰 2.方法的修饰 3.为什么修饰器不能用于函数? 4.core-decorators.js 5.使用修饰器实现自动发布事件 6.Mixin 7.Trait 8.Babel转码器的支持
<!-- ECMAScript 6 Module -->
1.严格模式 2.export命令 3.import命令 4.模块的整体加载 5.export default命令 6.模块的继承 7.ES6模块加载的实质 8.循环加载 9.跨模块常量 10.ES6模块的转码
<!-- ECMAScript 6 编程风格 -->
1.块级作用域 2.字符串 3.解构赋值 4.对象 5.数组 6.函数 7.Map结构 8.Class 9.模块 10.ESLint的使用
</body> </html>
|