《ES标准入门》&《UNDERSTANDING ECMACHRIPT 6》 读书摘录笔记(上)

### 前言

*这两本书应该是目前ES6相关的比较好的了,网上有电子版本(文末有链接)。不过我买了书看,哈哈。这两篇摘录笔记分为上下两部分,本文是上半部分(1-6章),摘录了两本书里一些比较有用的知识点。*

### 目录

> #####1. 块级作用域绑定

> #####2. 字符串与正则表达式

> #####3. 函数的扩展

> #####4. 数组的扩展

> #####5. 对象的扩展

#####6. 集合(Set、Map)

> 7 . Symbol和Symbol属性

>

> 8 . Javascript中的类

>

> 9 . Promise、Generator函数、Async函数

>

> 10 . 代理(Proxy)和反射(Reflection)API

>

> 11 . 修饰器

>

> 12 . Module

### 一、块级作用域绑定

块级声明用于声明在指定块级作用域之外无法访问的变量。块级作用域存在于:1、函数内部;2、块中(字符‘{‘和‘}‘之间的区域)。Es6 中存在的两种变量声明就是Let和Const声明。

值得摘录的有以下六点:

##### 1. 不能重复声明

var count = 9;

//抛出语法错误

let count = 7;

##### 2. Const常量声明必须进行初始化

const age = 8;

//语法错误:常量未初始化

const name;

##### 3. 特殊的For循环

For循环设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

for(let i = 0;i< 3;i++){

let i = ‘can not change‘;

console.log(i);//输出‘can not change‘

}

##### 4. 暂时性死区

在区块中存在let和const命令,则这个区块对这些命令声明的变量从一开始就形成封闭的作用域。只要在声明之前就使用这些变量,就会报错。

情况一:

var tmp = 123;

if(true){

tmp = ‘abc‘;//ReferenceError

let tmp;

}

情况二:

function test(x = y,y = 2){

return [x,y];

}

test();//报错

情况三:

let x = x;//ReferenceError: x is not defined

##### 5. Const声明对象,对象属性可变

##### 6. 彻底冻结函数

constantize(obj) {//彻底冻结函数

Object.freeze(obj);

Object.keys(obj).forEach((key, i) => {

if (typeof obj[key] === ‘object‘) {

constantize(obj[key]);

}

})

obj.name = 777;//TypeError: Cannot add property name, object is not extensible

return obj;

}

### 二、字符串与正则表达式

Es6加强了对Unicode的支持,并且扩展了字符串对象。正则表达式则增加了修饰符和属性。

值得摘录的有以下几点:

##### 1. codePointAt()与String.fromCodePoint()方法

完全支持UTF-16,接受编码单元的位置而非字符位置作为参数,返回与字符串中给定位置对应的码位,即一个整数值:

var text = "??a";

console.log(text.charCodeAt(0));  //55362

console.log(text.codePointAt(0)); //134017

判断一个字符是2个字节还是4个字节组成:

function is32Bit(c){

return c.codePointAt(0) > 0xFFFF;

}

is32Bit("??"); // true

is32Bit("a"); // false

console.log(String.fromCodePoint(134071)); // "??"

##### 2. normalize()方法

Es6为字符串添加了一个Normalize()方法,它可以提供Unicode的标准化形式,接受一个参数,指明应用哪种Unicode标准化形式(NFC,NFD,NFKC,NFKD)。只需要记住,在对比字符串之前,一定要先把它们标准化为同一种形式:

let normalized = values.map((text) => {

return text.normalize();

})

console.log(this[normalize](‘\u01D1‘) === this[normalize](‘\u004F\u030C‘)) // true

##### 3. includes()、startsWith()、endsWith()、repeat()方法

let tempArray = [1, "4", "uu", 5];

let tempStr = "test123uuunit582";

console.log(tempArray.includes(5)); //true

console.log(tempStr.includes("test123", 1)); //从第二个位置进行匹配

console.log(tempStr.startsWith("test")); //true

console.log(tempStr.startsWith("test123", 0)); //从第一个位置进行匹配

console.log(tempStr.endsWith("12",6)); //从第六个位置进行匹配

console.log(tempStr.repeat(3));    //test123uuunit582test123uuunit582test123uuunit582

##### 4. 模板字符串

领域专用语言(DSL),可以生成、查询并操作其他语言里的内容,且可以免受注入攻击(XSS、SQL等)。

> A、去掉模板字符串中的换行

$(‘#list‘).html(`

<ul>

<li>first</li>

<li>second</li>

</ul>

`.trim());

> B、引用模板字符串本身

//写法一

let str = ‘return ‘ + ‘`ni hao ${name}`‘;

let func = new Function(‘name‘,str);

let data = func(‘uct‘);

//写法二

let str2 = ‘(name) => `ni hao ${name}`‘;

let func2 = eval.call(null,str2);

let data2 = func2(‘uct‘);

console.log(data + ‘  ‘ + data2);

> C、标签模板

alert`123`;

//等同于

alert(123);

var a = 1,b = 2;

tag`Hello ${a + b} world ${a * b}`;

//等同于

tag([‘Hello ‘,‘ world , ‘‘],1,2);//第一个参数是数组,存放模板中没有变量替换的部分,后续参数是变量。

> D、String.raw()转义模板字符串

String.raw`Hi\n${3+4}`;//"Hi\\n5"

[关于new Function][newFunction]

[关于eval][eval]

[newFunction]: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function

[eval]:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval

##### 5.U修饰符与Y修饰符

U修饰符,即为“Unicode模式”,用来正确处理大于\uFFFF的Unicode字符。Y修饰符,叫作“粘连”(Sticky)修饰符,它的后一次匹配都从上一次匹配成功的下一个位置开始。

> A、点(.)字符匹配(匹配除换行符外的所有字符)

var s = "??";

/^.$/.test(s); // false

/^.$/u.test(s); // true

> B、返回字符串长度的函数

function codePointLength(){

var result = text.match(/[\s\S]/gu);

return result ? result.length : 0;

}

> C、y修饰符隐含了头部匹配的标志(^)

const REGEX = /a/y;

REGEX.lastIndex = 2;

REGEX.exec("xaya"); // null

REGEX.lastIndex = 3;

const match = REGEX.exec("xaya");

match.index; // 3

### 三、函数的扩展

值得摘录的有以下几点:

##### 1.函数参数的默认值

> A、参数变量默认声明

function test(x = 1){

let x = 2;//error

}

> B、惰性求值

let x = 10;

function testLazy(p = x + 1){

console.log(p);

}

testLazy(); // 11

let x = 12;

testLazy(); // 13

> C、非尾部设置默认值,参数不可省略

function f(x = 1,y){

return [x,y];

}

f(,1); //报错

> D、默认参数的临时死区TDZ

function add(first = second,second){

return first + second;

}

console.log(add(1,1));    // 2

console.log(add(undefined,1));  // 抛出错误

//当初次调用add()时,绑定first和second被添加到一个专属于函数参数的临时死区

//表示调用add(1,1) 时的Javascript 代码

let first = 1;

let second = 2;

//表示调用add(undefined,1) 时的Javascript 代码

let first = second;

let second = 1; //所以抛出错误;

##### 2.默认参数表达式

初次解析函数声明时不会调用getValue()方法,只有当调用add()函数且不传入第二个参数时才会调用:

constructor() {

this.value = 5;

}

getValue(){

return this.value ++;

}

add(first,second = this.getValue()){

console.log(‘plus: ‘, first + second );

}

...

Es6Function.add(1,1); // plus:  2

Es6Function.add(1);    // plus:  6

Es6Function.add(1);    // plus:  7

##### 3. 只要函数参数使用了默认值、解构赋值或者扩展运算符,那么函数内部就不能严格模式

const doSomething = (a,b = a,...c) => { //error

‘use strict‘;

//code

}

##### 4. 不定参数限制使用

> 每个函数最多只能声明一个不定参数,而且一定要放在所有参数的末尾。

function any(a,...b,last){} //报错

> 不定参数不能用于对象字面量Setter中

let object = {

//语法错误,不可以在Setter中使用不定参数

set name(...value){}

}

> 取数组最大值

let values = [25,34,11,99];

console.log(Math.max(...values)); // 99

##### 5. 箭头函数

> A、箭头函数中的This值取决于该函数外部非箭头函数的this值,且不能通过call()、apply()或bind()方法来改变this值

thisScope(){

setTimeout(()=>{

console.log(‘id: ‘,this.id);

},100);

}

...

var id = 55;

Es6Function.thisScope.call({id:100}); // id : 100

> B、函数体内不可民使用Arguments对象,该对象在函数体内不存在,可以用Rest参数(...)代替

testArguments(){

setTimeout(() => {

console.log(‘args: ‘,arguments)

}, 100);

}

...

Es6Function.testArguments(1,2,5,6); // args:  Arguments(4) [1, 2, 5, 6, callee: (...), Symbol(Symbol.iterator): ?]

##### 6. 尾调用优化

> 尾调用就是指某个函数的最后一步是调用另一个函数,只在严格模式下开启。

"use strict";

function doSomething(){

//优化后,立即返回结果

return doSomethingElse();

}

function doSomething2(){

//无法优化,无返回

doSomethingElse();

}

> 非严格模式下实现尾递归优化,用“循环” 替换 “递归”

function sum(x,y){

if(y > 0){

return sum( x + 1,y - 1);

} else {

return x;

}

}

sum(1,1000000);// Uncaught RangeError: Maximum call stack size exceeded(...)

//用蹦床函数可以将递归执行转为循环执行

function trampoline(f){

while(f && f instanceof Function){

f = f();

}

return f;

}

//返回一个函数,然后执行该函数,而不是在函数里调用函数,避免递归,消除调用栈过大问题

### 四、数组的扩展

值得摘录的有以下几点:

##### 1. 扩展运算符(...)

扩展运算符背后调用的是遍历器接口(Symbol.iterator),如果一个对象没有部署该接口就无法转换

> 替代数组的 Apply方法

//Es5 的写法

function f(x,y,z){}

var args = [1,2,3];

f.apply(null,args);

//Es6 的写法

function f(x,y,z){}

var args = [1,2,3];

f(...args);

> 合并数组

Es5 合并数组

var arr1 = [1,2];

var arr2 = [3,4];

var arr3 = [5];

arr1.concat(arr2,arr3);

Es6 合并数组

[...arr1,...arr2,...arr3];

> 能够识别 32 位的 Unicode 字符的取字符串长度的方法

function length(str){

return [...str].length;

}

length(‘x\uD83D\uDE80y‘); // 3

##### 3. Array.from()方法,用于将类似数组对象和可遍历对象(包括Set和Map结构)转为真正的数组

Array.from()方法除了支持遍历器接口转换外,还支持类数组对象(类数组对象的本质就是有Length属性)

Array.from({length:3});

// [undefined,undefined,undefined]

> 映射转换,Array.from()的第二个参数用来遍历类数组对象并返回

translate() {

return Array.from(arguments, (value) => value + 1);

}

console.log(NewArray.translate(1,2,3)); // [2,3,4]

##### 4. 为所有数组添加新的方法

> Array.of(),为了弥补数组构造函数Array()的不足

Array.of(3,11,8); // [3,11,8]

Array.of(undefined); // [undefined] , 通过Vue 显示到页面则为 [null]

Array(3); // [,,]

> copyWithin(),把数组内部指定位置成员复制到其他位置(会覆盖其他成员)

//将3号位复制到0号位

[1,2,3,4,5].copyWithin(0,3,4); //[ 4, 2, 3, 4, 5 ]

// -2相当于3号位,-1相当于4号位

[1,2,3,4,5].copyWithin(0,-2,-1); //[ 4, 2, 3, 4, 5 ]

> find(),返回符合条件的第一个(可能有多个)成员,如果没有就返回undefined

testFind(){ // 返回 3

return [1,2,3,4,5].find((value,index,arr)=>{

return value > 2;

})

}

> findIndex(),返回第一个符合条件的成员的位置,如果没有就返回 -1

testFindIndex(){ // 返回 -1

return [1,2,3,4,5].findIndex((value,index,arr)=>{

return value > 6;

})

}

> fill(),填充一个数组,接受第二第三个参数(起始位置和结束位置)

testFill(){

console.log([‘a‘,‘b‘,‘c‘].fill(8,1,2)); // ["a", 8, "c"]

return new Array(3).fill(8); //[ 8, 8, 8 ]

}

> includes(),返回一个布尔值,表示某个数组是否包含给定的值,它与indexOf 比起来更加直观,并且可以判断NaN的情况

testIncludes(){

return [1,2,NaN].includes(NaN); // true

}

> entries(),keys(),values()方法,它们都返回一个遍历器对象

testEntries(){

for(let [key,value] of [‘a‘,‘b‘,‘c‘].entries()){

console.log(key,value); // 0 "a"  1 "b"  2 "c"

}

let letter = [‘a‘,‘b‘,‘c‘];

//手动调用遍历器对象的Next方法进行遍历

let entries = letter.entries();

console.log(entries.next().value); //[0, "a"]

console.log(entries.next().value); //[1, "b"]

console.log(entries.next().value); //[2, "c"]

}

### 五、对象的扩展

ECMAScript6 中,为了使某些任务更易完成,在全局Object 对象上引入了一些新方法

值得摘录的有以下几点:

##### 1. 可计算属性名

let suffix = " name";

var person = {

["first" + suffix]: "Nicholas", // Es5 版本,这里的名称是不可以计算的

["last" + suffix]: "Zakas",

}

console.log(person["first name"]); // "Nicholas"

console.log(person["last name"]);    // "Zakas"

##### 2. Object.is(),弥补全等(===)运算符的特殊情况判断不一致

testObjectIs(){

console.log(+0 == -0);             // true

console.log(+0 === -0);         // true

console.log(Object.is(+0 , -0)); // false

console.log(NaN == NaN);         // false

console.log(NaN === NaN);         // false

console.log(Object.is(NaN , NaN)); // true

}

##### 3. Object.assign(),只会复制对象自身可枚举属性,忽略enumerable为false的属性

> 多个对象复制具有同名属性,排位靠后的源对象会覆盖排位靠前的

testObjectAssign(){

let receiver = {};

Object.assign(receiver,{

type:‘girl‘,

name:‘superman‘,

},{

type:‘boy‘,

})

return receiver.type + " : " + receiver.name; // boy : superman

}

> 对象浅复制(源对象某个属性是对象,只复制这个对象的引用)

let target = { a: { b: ‘c‘, d: ‘e‘ } };

let source = { a: { b: ‘hello‘ } }

console.log(Object.assign(target, source)); // {a: {b:‘hello‘}}

// a属性被整体覆盖掉,不会得到 {a : {b:‘hello‘,d:‘e‘}} 的结果

##### 3. Object.values()

> 只返回对象自身可遍历属性

testObjectValues() { // p 的属性描述对象的 enumerable 默认是 false

var obj = Object.create({}, { p: { value: 42 } });

return Object.values(obj); // []

}

> Object.values 会过滤属性名为Symbol值的属性

console.log(Object.values({ [Symbol()]: 123, any: ‘abc‘ })); // [‘abc‘]

##### 3. Object.entries()

> 转换对象为真正的Map结构

testObjectEntries(){

let obj = { a: ‘bar‘, b: 23 };

let map = new Map(Object.entries(obj));

console.log(map.get(‘a‘)); // bar

}

### 六、集合(Set、Map)

Es6 中的Set和Map核心思想跟Java中的Set和Map类似,Set集合成员是唯一的,没有重复,Set本身是构造函数用来生成Set数据结构;Map类型是一种存储着许多键值对的有序列表,它的键名的判断是通过Object.is()方法来实现的(Set也是通过这个方法来判断两个值是否一致),所以 5 和字符串"5"会被判定为两种类型。

值得摘录的有以下几点:

##### 1. Set

> 添加元素用add()方法,删除用delete()方法,判断存在用has(),清空用clear()

testSet() {

let set = new Set();

set.add(5);

set.add(‘5‘);

console.log(set.has(5)); // true

set.delete(5);

console.log(set.has(5)); // false

console.log(set.size); // 1

set.clear();

console.log(set.has(‘5‘)); // false

console.log(set.size); // 0

}

> 数组去重

testArrayUniq(){

let set = new Set([1,2,3,3,3,3,4,4,4,4,5]);

let arr = [...set];

console.log(arr); //[ 1, 2, 3, 4, 5 ]

return arr; //[ 1, 2, 3, 4, 5 ]

}

> 改变原来的Set结构

changeSet(){

let set = new Set([1, 2, 3]);

//方法二

set = new Set([...set].map((val) => val * 2));

//方法二

set = new Set(Array.from(set, val => val * 2));

return set; // [ 4, 8, 12 ]

}

##### 2. Map

Map结构提供了“值-值”对应,而Object结构提供了“字符串-值”对应,Map结构是一种更加完善的Hash结构实现

> 设置值set(),获取值get(),判断存在has(),删除delete(),清空用clear(),多次对同一个键赋值,后面覆盖前面

testMap(){

const m = new Map();

const o = {p:‘hello uct‘};

m.set(o,‘content‘);

m.set(o,‘new content‘)

console.log(m.get(o)); // new content

console.log(m.has(o)); // true

m.delete(o);

console.log(m.has(o)); // false

}

> Map 和 对象互相转换

//Map转为对象

strMapToObj(strMap){//Map to Object

let obj = Object.create(null);

for(let [k,v] of strMap){

obj[k] = v;

}

return obj;

}

//对象转为Map

objToStrMap(obj){// Object to Map

let strMap = new Map();

for(let k of Object.keys(obj)){

strMap.set(k,obj[k]);

}

return strMap;

}

##### 3. WeakMap

WeakMap只接受对象作为键名(Null除外)

> WeakMap 应用的典型场景就是以DOM节点作为键名的场景

const listener = new WeakMap();

listener.set(element1,handler1);

listener.set(element2,handler2);

element1.addEventListener(‘click‘,listener.get(element1),false);

element2.addEventListener(‘click‘,listener.get(element2),false);

//一旦DOM对象消失,与它绑定的监听函数也会自动消失

> 部署私有属性

const _counter = new WeakMap();

const _action = new WeakMap();

class Countdown {

constructor(counter, action) {

_counter.set(this, counter);//weakmap的私有属性

_action.set(this, action);  //weakmap的私有属性

}

dec() {

let counter = _counter.get(this);

if (counter < 1) return;

counter--;

console.log(counter);

_counter.set(this, counter);

if (counter === 0) {

_action.get(this)();

}

}

}

export default Countdown;

### 结语

*本来觉得没有必要写这个笔记,但是,看和写真的是两回事。书中的例子大都是抽象化的,也就是为了让大家看起来直观,去掉了上下文,有些还有错。自己动手写的话(运用实例),印象会非常深刻,在真实开发环境中会想到去用它。笔记的下篇已经在写了,相对上篇,我更期待下篇,NSL...*

### 参考链接

[ECMAScript 6 入门](http://es6.ruanyifeng.com/)

[UNDERSTANDING ES6 英文原版](https://leanpub.com/understandinges6/read)

原文地址:https://www.cnblogs.com/ChickenTang/p/8793613.html

时间: 2024-11-25 14:22:11

《ES标准入门》&《UNDERSTANDING ECMACHRIPT 6》 读书摘录笔记(上)的相关文章

C++ STL标准入门

C++:STL标准入门汇总 第一部分:(参考百度百科) 一.STL简介 STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称.它是由Alexander Stepanov.Meng Lee和David R Musser在惠普实验室工作时所开发出来 的.现在虽说它主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间. STL的代码从广义上讲分为三类:algorithm(算法).container(容器)和iterator(迭代

joelonsoftware 读书摘录

joelonsoftware 读书摘录 <五个为什么>  1.“黑天鹅难题”,代表外来因素,是一个超出正常预料之外的事件.  2.丰田佐吉的“五个为什么”,当某个地方出现问题时,你就一遍遍地追问,直到你找到根本性的原因为止.然后,你就针对根本性的原因开始着手解决问题,你要从根本上解决这个问题,而不是一些表面的症状.  3.解决问题的两种方式:一种是表面的.快速的解决方法,只求把问题解决了事.二是,防止类似问题发生的解决方法.    <确定优先顺序>  1.因为上架软件增加顾客的 边

ES6标准入门 论文随笔(二)

一.基本信息 标题:ES6标准入门 时间:2015 来源:电子工业出版社 关键词:ES6标准入门 二.研究内容 问题定义: ES6是什么?它是用来干嘛的?为什么要用ES6? 特点:(1)JavaScript新特性 (2)let.const (3)promise (4)iterator (5)proxy 三.结论 <ES6标准入门(第2版)>为中级难度,适合对 JavaScript 语言或 ES5 已经有所了解的读者,用来提高水平,了解这门语言的最新发展:也可当作参考手册,查寻 ES6/ES7

git入门学习(一):github for windows上传本地项目到github

Git是目前最先进的分布式版本控制系统,作为一个程序员,我们需要掌握其用法.Github发布了Github for Windows 则大大降低了学习成本和使用难度,他甚至比SVN都简单. 一.首先在github创建自己的账号 github官方网址为:https://github.com/,相信大家都应该有自己的github账号. 二.下载github for windows 官方下载网址为:https://desktop.github.com/,我下载的版本为3.2.0.0 三.安装github

[转] 《ES6标准入门》读书笔记

来源:https://segmentfault.com/a/1190000005863641 let和const命令 ES6新增let命令,用于声明变量,是块级作用域. let声明的变量不会像var声明的变量发生“变量提升”现象,所以,变量一定要在声明后使用,不然就会报错. 暂时性死区:只要块级作用域内存在let命令,它所声明的变量就会“绑定”在这个区域,不再受外部的影响.即在代码块内,使用let命令声明变量之前,这个变量都是不可用的,这在语法上称为“暂时性死区”. ES6规定暂时性死区和不存在

OpenGL ES编程入门资源集合

OpenGL ES 2.0中文手册:http://www.dreamingwish.com/articlelist/category/opengl-es-api 里边讲解了部分API的功能,作为基本的参考. OpenGL ES2.0 渲染管线:http://codingnow.cn/opengles/1504.html OpenGL ES2.0 绘制三角形:http://codingnow.cn/opengles/1514.html 一个OpenGL ES2.0的例子:http://blog.c

(转)OpenGL ES编程入门资源集合

出自:http://blog.csdn.net/u013467442/article/details/44498125 OpenGL ES 2.0中文手册:http://www.dreamingwish.com/articlelist/category/opengl-es-api 里边讲解了部分API的功能,作为基本的参考. OpenGL ES2.0 渲染管线:http://codingnow.cn/opengles/1504.html OpenGL ES2.0 绘制三角形:http://cod

《Github入门与实践》读书笔记 蟲咋先生的追求之旅(上)

<Github入门与实践>作者: [日] 大塚弘记 译者:支鹏浩/刘斌 简介 本书从Git的基本知识和操作方法入手,详细介绍了GitHub的各种功能,GitHub与其他工具或服务的协作,使用GitHub的开发流程以及如何将GitHub引入到企业中.在讲解GitHub的代表功能Pull Request时,本书专门搭建了供各位读者实践的仓库,邀请各位读者进行Pull Request并共同维护. 豆瓣地址:https://book.douban.com/subject/26462816/ 本以为对于

ES6标准入门 第一章:简介

ECMAScript 6 是JavaScript 语言的下一代标准:发布于2015年,又称为ECMAScript 2015. ECMAScript 方言还有 JScript 和 ActionScript. ECMAScript 与 JavaScript 的关系:前者是后者的规范,后者是前者的一种实现. 一个完整的JavaScript实现 包含 ECMAScript .DOM. BOM 三部分. babel 转码器: Babel 是一个广为使用的ES6转码器,可以将ES6代码转为ES5代码,从而在