ES6是什么?JavaScript的第六版,在ES5的基础上增加了许多特性:箭头函数、字符串插值、代理、生成器、结构赋值、块级作用域等等。一、let和const1.作用:声明变量ES6中明确规定,如果区块中存在let和const命令,则这个区块对这些命令声明的变量从一开始就形成封闭作用域。只要在声明之前就使用这些变量,就会报错(暂时性死区)。2.let使用注意:作用域只局限于当前代码块使用let声明的变量作用域不会被提升在相同的作用域下不能声明相同的变量for循环体现let的父子作用域3.const使用注意:const声明一个只读的常量只在当前代码块中有效作用域不会被提升不能重复声明声明的常量必须赋值二、解构赋值1.基本用法let [name, age, sex] = [‘李四’, 20, ‘女’];console.log(name); // 李四console.log(age); // 20console.log(sex); // 女2.对象的结构赋值let { name, age, friends, pet } = { name: ‘张三’, age: 55, friends: [’lulu’, ‘王五’], pet: { name: ‘土豆’, age: 5 } }; console.log(name); // 张三 console.log(age); // 55 console.log(friends); // [“lulu”, “王五”] console.log(pet); // {name: “土豆”, age: 5}let { name: str } = { name: ‘张三’ }; console.log(name); // console.log(str); // 张三3.数组的解构赋值let [arr1, [arr2, arr3, [arr4, arr5]]] = [1, [2, 3, [4, 5]]];console.log(arr1, arr2, arr3, arr4, arr5);// 1 2 3 4 5let [arr1] = [];console.log(arr1);// undefinedlet [a, , c] = [1, 2, 3];console.log(a); // 1console.log(c); // 34.基本类型的解构赋值let [a, b, c, d, e] = ‘我是中国人’;console.log(a); // 我 console.log(b); // 是console.log(c); // 中console.log(d); // 国console.log(e); // 人三、数据集合-set类似于数组,但是成员是唯一的,没有重复。1.创建一个集合let set = new Set([‘张三’, ‘李四’, ‘王五’, ‘张三’, ‘李四’]);console.log(set); //{“张三”, “李四”, “王五”}console.log(Array.from(set)); // [“张三”, “李四”, “王五”]2.一个属性console.log(set.size); //33.四个方法//addconsole.log(set.add(‘刘德华’).add(‘LHH’));//{“张三”, “李四”, “王五”, “刘德华”, “LHH”}console.log(set);//{“张三”, “李四”, “王五”, “刘德华”, “LHH”}//deleteconsole.log(set.delete(‘张三’)); // trueconsole.log(set.delete(‘李四’)); // trueconsole.log(set);//hasconsole.log(set.has(‘张三’)); // trueconsole.log(set.has(‘张三1’)); // false//clearconsole.log(set.clear()); // undefinedconsole.log(set); // {}4.keys valuesconsole.log(set.keys()); // SetIterator {“张三”, “李四”, “王五”}console.log(set.values()); // SetIterator {“张三”, “李四”, “王五”}四、数据集合-map类似于对象,也是键值对集合,但“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键.1. 创建一个Maplet obj1 = { a: 1 }, obj2 = { b: 2 };const map = new Map([ [’name’, ‘张三’], [‘age’, 18], [‘sex’, ‘男’], [obj1, ‘今天天气很好’], [obj2, ‘适合敲代码’], [ [1, 2], ‘hhh’ ]]);console.log(map);console.log(map.size);2.set和getmap.set(‘friends’, [‘赵六’, ‘力气’]).set([‘dog’], ‘小花’);console.log(map);console.log(map.get(’name’));console.log(map.get(obj1));3.deletemap.delete(obj1);console.log(map.delete(‘xxxx’));console.log(map);4.hasconsole.log(map.has(obj1)); // trueconsole.log(map.has(obj2)); //true5.clearmap.clear();console.log(map); // {}6.keys() values() entries()console.log(map);console.log(map.keys());console.log(map.values());console.log(map.entries());7.遍历map.forEach(function(value, index) { console.log(index + ‘:’ + value);})8.注意事项map.set({}, ‘呵呵呵呵呵’);map.set({}, ‘哈哈哈哈’);console.log(map);console.log({} === {});五、Symbol1.定义let str1 = Symbol();let str2 = Symbol();console.log(str1 === str2); // falseconsole.log(typeof str1); // symbolconsole.log(typeof str2); // symbol2.描述let str3 = Symbol(’name’);let str4 = Symbol(’name’);console.log(str3); // Symbol(name)console.log(str4); // Symbol(name)console.log(str3 === str4); // false 3. 对象的属性名const obj = {};obj.name = ‘张三’;obj.name = ‘李四’;obj[Symbol(’name’)] = ‘张三’;obj[Symbol(’name’)] = ‘李四’;let a = Symbol(‘aa’);let b = Symbol(‘bb’);obj[a] = ‘王五’obj[b] = ‘kk’console.log(obj);console.log(Object.getOwnPropertySymbols(obj)); // 获取指定对象的所有Symbol属性名console.log(Reflect.ownKeys(obj)); // 返回所有类型的键名,包括常规键名和Symbol键名注意,Symbol函数前不能使用new命令,因为Symbol是一个原始类型的值,不是对象,所以也不能添加属性。4.Symbol.for() 和 Symbol.keyfor()var s1 = Symbol.for(‘foo’);var s2 = Symbol.for(‘foo’);s1===s2; // true上面代码中,s1和s2都是Symbol的值,但它们都是同样参数的Symbol.for方法生成的,所有实际上是同一个值。Symbol.for()与Symbol()这两种写法都会生成新的Symbol。它们的区别是,前者会被登记在全局环境中供搜索,而后者不会。Symbol.for()不会再每次调用时都返回一个新的Symbol类型的值,而是会先检查给定的key是否已经存在,如果不存在才会新建一个值,比如,如果调用Symbol.for(‘cat’)30次,每次都会返回同一个Symbol值,但是调用Symbol(‘cat’)30次则会返回30个不同的Symbol值。Symbol.keyFor()方法返回一个已登记的Symbol类型值得keyvar s1 = Symbol.for(“foo”);Symbol.keyFor(s1); // “foo"var s2 = Symbol(“foo”);Symbol.keyFor(s2); // undefined注:Symbol.for为Symbol值登记的名字是全局环境的,可以在不同的iframe或service worker 中取到同一个值。iframe = document.createElement(‘iframe’);iframe.src = String(window.location);document.body.appendchild(iframe);iframe.contentWindow.Symbol.for(‘foo’) === Symbol.for(‘foo’); // true六、class的基本运用1.构造函数function Person(name, age) { this.name = name; this.age = age; }Person.prototype = { constructor: Person, print(){ console.log(‘我叫’ + this.name + ‘,今年’ + this.age + ‘岁’); } };//或//Person.prototype.print = function() { // console.log(‘我叫’ + this.name + ‘,今年’ + this.age + ‘岁’);//}let person = new Person(‘张三’, 19);console.log(person);person.print(); 2. 通过class面向对象class Person { constructor(name, age) { this.name = name; this.age = age; } print() { console.log(‘我叫’ + this.name + ‘,今年’ + this.age + ‘岁’); } }let person = new Person(‘张三’, 19);console.log(person);person.print();3.class实现继承class Animal { //构造函数 constructor(props) { this.name = props.name || ‘未知’; } eat() { alert(this.name + “在吃东西…”); } } //class继承 class Bird extends Animal { //构造函数 constructor(props) { //调用实现父类的构造函数 super(props); this.type = props.type || “未知”; } fly() { alert(this.name + “在飞…”); } } var myBird = new Bird({ name: ‘鹦鹉’ }) myBird.eat() // 鹦鹉在吃东西… myBird.fly() // 鹦鹉在飞…七、内置对象扩展1. 模板字符串let str = ‘适合敲代码!’;let className = ’test’;let html = &lt;html&gt; &lt;head&gt;&lt;/head&gt; &lt;body&gt; &lt;p&gt;今天的天气很好!&lt;/p&gt; &lt;div class="${className}"&gt;${str}&lt;/div&gt; &lt;/body&gt; &lt;/html&gt;;console.log(html);2. 数组的扩展Array.from// 在body中写了几个li节点let allLis = document.querySelectorAll(’li’);console.log(allLis); // NodeList(6) [li, li, li, li, li, li]console.log(Array.isArray(allLis)); // falseconsole.log(Array.from(allLis)); // [li, li, li, li, li, li]console.log(Array.isArray(Array.from(allLis))); // trueArray.ofconsole.log(Array.of(1, 2, 3, 4)); // [1, 2, 3, 4]console.log(Array.of(‘张三’, ‘李四’, ‘王五’)); // [“张三”, “李四”, “王五”]3. 对象的扩展key 和 value是一样的,写一个就够了let name = ‘张三’;let age = 18;let person = { name, age };console.log(person); // {name: “张三”, age: 18}Object.assign()let obj1 = { name: ‘张三’ };let obj2 = { age: 18 }; let obj3 = { sex: ‘男’ };let obj4 = { friends: ‘李四’ };let obj = {};Object.assign(obj, obj1, obj2, obj3, obj4);console.log(Object.assign(obj, obj1, obj2, obj3, obj4)); // {name: “张三”, age: 18, sex: “男”, friends: “李四”}console.log(obj); // {name: “张三”, age: 18, sex: “男”, friends: “李四”}延展操作符let str = ‘今天的天气很好!’;let strArr = […str];console.log(strArr); // [“今”, “天”, “的”, “天”, “气”, “很”, “好”, “!"]let student = { name: ‘张三’, age: 18, sex: ‘男’ }< Person {…student}/>let myArr = [1, 2, 10, ‘张三’, 20, 2, 1];console.log(new Set(myArr)); // {1, 2, 10, “张三”, 20}console.log([…new Set(myArr)]); // [1, 2, 10, “张三”, 20]八、函数的扩展1. 形参设置默认值function sum(num1 = 20, num2 = 10) { console.log(num1 + num2);}/* function sum(num1, num2) { num1 = num1 || 10; num2 = num2 || 10; console.log(num1 + num2);} /sum(10, 30); // 40sum(); // 302.参数形式 延展操作符function sum(name, sex, …nums) { let result = 0; console.log(name); console.log(sex); for (let value of nums) { result += value; } return result; }/ function sum() { let result = 0; for(let value of arguments){ result += value; } return result;} */console.log(sum(‘张男’, ‘男’, 10, 20, 30, 50)); // 张男 // 男 // 1103.箭头函数 () => {}let sum = (num1, num2)=>{ return num1 + num2;};console.log(sum(100, 300)); // 400let nameArr = [‘张三’, ‘李四’, ‘王五’]; nameArr.forEach((value, index) => { console.log(index + ‘:’ + value);});// 0:张三// 1:李四// 2:王五this的指向不同function demo() { setTimeout(function() { console.log(this); }, 500); setTimeout(() => { console.log(this); }, 1000);}let obj = { a: 1};demo.call(obj);// Window // {a: 1}箭头函数的几个注意事项:函数体内的this对象就是定义时所在的对象,而不是使用时所在的对象;不可以当作构造函数。也就是不可以使用new命令,否则报错;不可以使用arguments对象,该对象在函数体内不存在;可以rest参数代替(…参数);不可以使用yield命令,因此箭头函数不能用作Generator函数;九、Iterator遍历器和for..of循环Iterator作用:一是为各种数据结构提供统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是ES6创建了一种新的遍历命令——for…of循环,Iterator接口主要供for…of消费模拟next方法返回值得例子: var it = makeIterator([‘a’, ‘b’]); console.log(it.next()); // {value: “a”, done: false} console.log(it.next()); // {value: “b”, done: false} console.log(it.next()); // {value: undefined, done: true} function makeIterator(array) { var nextIndex = 0; return { next: function() { return nextIndex < array.length ? { value: array[nextIndex++], done: false } : { value: undefined, done: true } } } }具备Iterator接口的数据结构如下:Array Map Set String TypedArray 函数的arguments对象 NodeList对象下面例子是数组的Symbol.iterator属性: let arr = [‘a’, ‘b’, ‘c’]; let iter = arrSymbol.iterator; console.log(iter.next()); // {value: “a”, done: false} console.log(iter.next()); // {value: “b”, done: false} console.log(iter.next()); // {value: “c”, done: false} console.log(iter.next()); // {value: undefined, done: true}注意:对象(Object)之所以没有默认部署Iterator接口,是因为对象属性的遍历先后顺序是不确定的。for…of循环一个数据结构只要部署了Symbol.iterator属性,就被视为具有Iterator接口,就可以用for…of循环它的成员。注意:有些数据结构是在现有数据结构的基础上计算生成的,比如ES6的数组、Set、Map都部署了一下三个方法,调用后都返回遍历器对象entries()返回一个遍历器对象,用于遍历[键名,键值]组成的数组。对于数组,键名就是索引值;对于Set,键名与键值相同。Map结构的Iterator接口默认就是调用entries方法keys()返回一个遍历器对象,用于遍历所有的键名values()返回一个遍历器对象,用于遍历所有的键值