Understanding ES6学习笔记

Understanding ES6学习笔记

Chapter 1 let:  1.不能进行变量提升,所以变量一定要在声明后使用。 2.只在let所在的块内起作用。 3.let不允许在相同作用域内,重复声明同一个变量。在不同的作用域则可以。 4.ES5只有全局作用域和函数作用域,可能造成一些问题,如内层变量覆盖外层变量、for循环用来计数的循环变量泄露为全局变量等。let实际上为javaScript新增了块级作用域。 const: 1.一经定义,不得改变,也不能进行变量提升,在声明的时候一定要进行初始化,否则会报错。 2.也是在块内起作用 3.若const储存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把它指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性。 暂时性死区:

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

Chapter 4 对象扩展 对象字面量扩展 1.创建对象时,当属性名和变量名相等时,省略属性名 function createPerson(name, age) {     return {         name,         age     }; } 2.给对象添加方法时,省略function var person = {     name: "Nicholas",     sayName() {         console.log(this.name);     } }; 3.属性名 let lastName = "last name"; let person = {     "first name": "Nicholas",     [lastName]: "Zakas" }; console.log(person["first name"]);      // "Nicholas" console.log(person[lastName]);          // "Zakas" 用表达式作为属性名: var suffix = " name"; var person = {     ["first" + suffix]: "Nicholas",     ["last" + suffix]: "Zakas" }; console.log(person["first name"]);      // "Nicholas" console.log(person["last name"]);       // "Zakas" 4.新方法 1.Object.is()  比较两个值是否严格相等 2.Object.assign()  用于对象的合并,将源对象的所有属性复制到目标对象 var target = { a: 1 }; var source1 = { b: 2 }; var source2 = { c: 3 }; Object.assign(target, source1, source2); target // {a:1, b:2, c:3} 还可用于为对象添加属性、方法等。 5.重写 "use strict"; var person = {     name: "Nicholas",     name: "Greg"        // no error in ES6 strict mode }; console.log(person.name);       // "Greg" 6.属性枚举顺序 Object.getOwnPRopertyNames(obj) 数字按升序排列,字符串按它们添加到对象的顺序排列. 7.改变Prototype Object.setPrototypeOf()方法,接收两个对象最为参数 8.super 指向当前对象原型的指针 原为Object.getPrototypeOf(this).getGreeting.call(this); 改为super.getGreeting(); 【在简化的方法中】,可以通过super调用对象原型上的任何方法。 let friend = {     getGreeting: function() {         // syntax error         return super.getGreeting() + ", hi!";     } };

Chapter 5 解构赋值 ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值。 1.对象解构 let node = {     type: "Identifier",     name: "foo" }; let { type, name } = node; 变量名和属性名一致 var { foo, bar } = { foo: "aaa", bar: "bbb" }; foo // "aaa" bar // "bbb" 对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。 var { foo: baz } = { foo: "aaa", bar: "bbb" }; baz // "aaa" foo // error: foo is not defined 也可嵌套 var obj = {   p: [     'Hello',     { y: 'World' }   ] }; var { p: [x, { y }] } = obj; x // "Hello" y // "World" 指定默认值 let node = {     type: "Identifier",     name: "foo" }; let { type, name, value = true } = node; 2.数组解构 数据解构对items的位置操作 模式匹配 let colors = [ "red", "green", "blue" ]; let [ firstColor, secondColor ] = colors; console.log(firstColor);        // "red" console.log(secondColor);       // "green" 交换变量: let a = 1,     b = 2; [ a, b ] = [ b, a ]; 3.混合 Chapter 7 1.set: 类似数组,但成员的值唯一 let set=new Set(); 可接收一个数组作为参数,用来初始化。 添加:set.add(value) 判断是否存在:set.has(value) 删除一个:set.delete(value) 删除全部:set.clear()  forEach()方法:set.forEach(function(value,key,ownerSet){});forEach方法还可以有第二个参数,表示绑定的this对象。 key和value相等 set里的forEach()不能访问items索引,如需要,则应将其转换为数组。 Array.from方法可将Set结构转换为数组。 set转换为array: array=[...set];(会去除set中的重复项)。 Weak Sets:(对象引用)弱引用 (即垃圾回收机制不考虑WeakSet对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于WeakSet之中。这个特点意味着,无法引用WeakSet的成员,因此WeakSet是不可遍历的。) WeakSet结构与Set类似,也是不重复的值的集合,但WeakSet的成员只能是对象。 创建: let set=new WeakSet(); 三大集合对象:arrays, maps, sets 2.map:(key-value) let map=new Map(); 添加:map.set(key,value); 检索:map.get(); 对象也可以是key。 也有has(),delete(),clear()方法。 Weak Maps: 每一个key都必须是对象object,键名所指向的对象,不计入垃圾回收机制。 用处:和DOM元素进行数据交互。存储对象实例的专用数据。 (WeakMap的设计目的在于,键名是对象的弱引用(垃圾回收机制不将该引用考虑在内),所以其所对应的对象可能会被自动回收。当对象被回收后,WeakMap自动移除对应的键值对。典型应用是,一个对应DOM元素的WeakMap结构,当某个DOM元素被清除,其所对应的WeakMap记录就会自动被移除。基本上,WeakMap的专用场合就是,它的键所对应的对象,可能会在将来消失。WeakMap结构有助于防止内存泄漏。) Chapter 8 1.是一个方法,返回一个迭代器。function关键字与函数名之间有一个星号,函数体内部使用yield语句,定义不同的内部状态。 2.function *createIterator(){} let iterator=createIterator();  指向内部状态的指针对象 如果是匿名函数,星号的位置为: let createIterator=function *(){} 3.yield:执行完一条时,暂停执行,直到下一个next()调用的时候,再执行下一条yield。每次调用next(),返回一个有着value和done两个属性的对象。 4.因为是方法,可添加到对象。 5.for-of 如果只是迭代数组或集合里的值的话用for-of let values=[1,2,3]; for(let num of values){     console.log(num); } 6.通过Symbol.iterator访问默认迭代器 let values=[1,2,3]; let iterator=values[Symbol.iterator](); console.log(iterator.next()); 获取默认迭代器,并用于遍历数组中的items,也是for-of的内部过程。 还可以据此判断一个对象是否可迭代。 7.自定义迭代器 自己创建一个Symbol.iterator属性,该属性包含一个Generator函数。 8.内置迭代器 entries() 返回key-value对 values() 返回values keys() 返回keys 9.三大集合类型的for-of时的默认迭代器 arrays/sets: values() maps: entries() 10.字符串迭代器 for-of 可打印字符串的双字节字符 11. 节点列表迭代器 12.扩展运算符(...) 可将多个数组插入到一个数组中 13.高级迭代器功能 当将参数传递给next()方法时,该参数将成为上一个yield语句的返回值。 iterator.throw(new Error("boom")); 使用yield时,next()和throw()方法控制迭代器中的执行。next()可通过给定值来指示迭代器继续执行,throw()通过抛出错误来指示迭代器继续执行。 14. return 停止执行,done为true,value为undefined。若提供一个返回值,则value为该值,done为true。再执行一条next()时,value变为undefined。 15. 委托 在yield和函数名之间加*号,可以委托给别的Generator。 function *createCombinedIterator(){     yield *createNumberIterator();     yield *createColorIterator(); } 据此可以将多个Generator的value合成一个。 也可访问返回值。 16. 异步编程 因为生成器允许在执行的时候有效地暂停执行,这位异步处理提供了许多可能性。 一个简单的任务运行器,需定义一个函数,接受一个Generator作为参数,在函数内创建一个迭代器并start。 若要传递数据,可将result.value传入next()作为参数。 一个异步的任务运行器,result.value(function(err,data){} 有一个回调函数。 Chapter 9 类 1.类的声明: class PersonClass{     constructor(name){         this.name=name;     }     sayName(){          console.log(this.name);     } } let person=new PersonClass("Jack"); 2.类的声明类似let,存在暂时性死区。 3.在类的里面不能重写类名,在类外可以。 4.类表达式 匿名类表达式,省略类名。let PersonClass=class{} 若有类名,如let PersonClass=class PersonClass2{},则PersonClass2只存在于类内,类外为undefined。 5.ES6中,类可作为函数参数。 6.类表达式可通过立即调用类构造函数来创建实例。需要new。 let person=new Class{     constructor(name){         this.name=name;     }     sayName(){         console.log(this.name);     } }("Jack"); 创建一个匿名类表达式并立即执行。 7.访问器属性 类允许在原型上定义访问器属性。get和set class CustomHTMLElement{     constructor(element){         this.element=element;     }     get html(){         return this.element.inerHTML;     }     set html(vlaue){         this.element.innerHTML=vlaue;     } } var descriptor=Object.getOwnPropertyDescriptor(CustomHTMLElement.prototype,"html"); console.log("get" in descriptor);  //ture 【Object.getOwnPropertyDescriptor(object,propertyname)获取指定对象的自身属性描述符。自身属性描述符是指直接在对象上定义(而非从对象的原型继承)的描述符。】 8.[表达式]使用变量为类定义中的方法分配名称。 let methodName="sayName"; class PersonClass{     constructor(name){         this.name=name;     }     [methodName](){         cosole.log(this.name);     } }; 使用变量为类定义中的方法分配属性名 let propertyName="html"; class CustomHTMLElement{     ...     get [propertyName](){...}     ... } 9. Generator Methods 定义: class MyClass{     *createIterator(){         yield 1;         yield 2;     } } let instance=new MyClass(); let iterator=instance.createIterator(); 9.静态成员 class PersonClass{     ...     static create(name){         return new PersonClass(name);     } } let person=PersonClass.create("Jack"); 10.派生类继承,关键字extends class Rectangle {     constructor(length, width) {         this.length = length;         this.width = width;     }     getArea() {         return this.length * this.width;     } } class Square extends Rectangle {     constructor(length) {         // equivalent of Rectangle.call(this, length, length)         super(length, length);     } } var square = new Square(3); Square构造函数使用super()来调用具有指定参数的Rectangle构造函数。如果选择不使用构造函数,在创建一个新的类的实例时,super()会被自动调用。 11.继承静态成员 如果基类具有静态成员,那么这些静态成员也可在派生类上使用。 12.表达式派生类 只要表达式带有[[Construct]]的函数和原型,就可以对任何表达式使用extend。在extends之后接受任何类型的表达式提供了强大的可能性,例如动态确定要继承的内容。 chapter 10 数组 1.创建数组 Array.of() 参数为items 2.将一个类数组转换为数组 Array.from() 参数为items,可接收一个函数作为第二个参数,每个item在该函数运行后输出。还可接收第三个参数代表this。 还可在迭代器中使用: let numbers = {     *[Symbol.iterator]() {         yield 1;         yield 2;         yield 3;     } }; let numbers2 = Array.from(numbers, (value) => value + 1); console.log(numbers2);              // 2,3,4 3.find()&findIndex() let numbers = [25, 30, 35, 40, 45]; console.log(numbers.find(n => n > 33));         // 35 console.log(numbers.findIndex(n => n > 33));    // 2 4.fill()  对数组items的整体或部分进行重写 5.copyWithin() 6.Typed Arrays 数组缓存区 所有类型数组的基础是数组缓冲区,它是一个可以包含指定数量字节的内存位置。 创建数组缓冲区:let buffer=new ArrayBuffer(10); console.log(buffer.byteLength); //10 可用slice() 7.使用视图操作数组缓冲区 DataView 数组缓冲区表示内存位置,视图是用于操作该内存的接口。视图对数组缓冲区或数组缓冲区字节的子集进行操作,以一种数值数据类型读取和写入数据。 let buffer=new ArrayBuffer(10); let view=new DataView(buffer); //所有 let view=new DataView(buffer,5,2); //部分 5,6 检索视图信息有三个,buffer,byteOffset,byteLength 8.读写数据 getInt8(byteOffset,littleEndian), setInt8(byteOffset,value,littleEndian 视图允许在任何时间点以任何格式读取和写入,而不考虑之前数据时如何存储的。 9.创建特定类型视图 let buffer=new ArrayBuffer(10),      view1=new Int8Array(buffer),      view2=new Int8Array(buffer,5,2);