ES6 —— 新特性、快速入门
2019-10-19:
-- 对比学习:ES3、ES5、ES6怎么实现同一个东西
我的学习:
一、课程环境准备:
前端大杂烩:http://github.com/cucygh/fe-material
webpack: 自动编译ES6代码。
JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle。
二、常量:
// ES5 中常量的写法: Object.definceProperty(window,"PI2", { value: 3.1415926, writable: false, // read only }) console.log(window.PI2)
// ES6 中常量的写法: const PI = 3.1415926 console.log(PI) // 如果重新赋值会报错: PI = 4
三、作用域:
// ES5 中的作用域 var callbacks = []; for(var i=0; i<=2; i++){ callbacks[i] = function() { return i*2 } } console.table([ callback[0](), callback[1](), callback[2](), ]) // 结果都是6, 原因:i变量提升了,(i*2)是一个闭包,循环完对闭包求值,此时全局i已经是3了。
// ES6 中的作用域 const callbacks2 = [] for (let j = 0; j <= 2; j++){ callbacks2[j] = function(){ return j * 2 } } console.table([ callbacks2[0](), callbacks2[1](), callbacks2[2](), ]) // 结果分别是:0, 2, 4 // 原因是:let建立的对象只用于当前块作用域,它会保存到这个块中,供这个闭包使用
立即执行函数:
// ES6中会转成箭头函数 (() ==>{ const foo = function(){ return 1 } })() // ES5 常量作用域隔离写法:(复杂) ((function)(){ var foo = function(){return 1} console.log("foo() ===1", foo() === 1) ((function){ var foo = function(){return 2} console.log("foo() ===2", foo() === 2) }()) })())
// ES6 中常量的作用域隔离: { function foo() { return 1 } console.log("foo() ===1:", foo() === 1); { function foo() { return 2 } console.log("foo() ===2:", foo() === 2); } } // 结果: 两个都是true。一个花括号就是一个作用域的隔离
三、箭头函数:
省去function,简洁;
() 为了放参数,只有一个时可以省略;
{ } 里直接作为返回值的话,可以省略。
/* eslint-disable */ { // ES3, ES5 的遍历 var evens = [1, 2, 3, 4, 5]; var odds = evens.map(function(v){ return v + 1 }) console.log(evens, odds); }
// ES6 { let evens = [1, 2, 3, 4, 5]; let odds = evens.map(v => v + 1); console.log(evens, odds) }
// ES5 声明类 { var factory = function(){ this.a = 'a'; this.b = 'b'; this.c = 'c'; a: 'a+', b: function(){ return this.a } } } console.log(new factory().c.b()); // new factory() new一个对象 // c 是新的实例,b()是方法 // 运行结果是 'a+', 因为this的指向是该函数被调用的对象,b()是c调用的,所以this指向c
// 箭头函数this的指向:
{ var factory=function(){ this.a = 'a'; this.a = 'a'; this.a = { a: 'a+', b: () => { return this.a } } } } console.log(new factory().c.b()) // 结果是a。原因是箭头函数this指向是定义时实例,就是factory
四、默认参数:
(1):
// ES3/ES5 默认参数的写法 { function f(x, y, z){ if(y===undefined){ y = 7; } if (z===undefined){ z = 42 } return x+y+z } console.log(f(1,3)) } // 所有参数都要这样检查,很麻烦
// ES6 的默认参数: { function f(x, y = 7, z = 42){ return x+y+z } console.log(f(1,3)) }
// ES6 检查参数是否为空(没赋值): { function checkParameter(){ throw new ERROR('can\'t be empty') } function(x = checkParameter(), y=7, z=42){ return x+y+z } console.log(f(1)); try { f() } catch (e) { console.log(e); }finally{ } } // 利用异常函数提示错误
(2)函数对不定数量参数实现的区别:
// ES3/ES5 的可变参数: 不定数量参数的求和 { function f(x){ var a = Array.prototype.slice.call(arguments) car sum=0; a.forEach(function(item){ sum+=item*1; }) return sum } console.log(f(1,2,3,6)); } // Array.prototype.slice.call(arguments) 创建伪数组,利用数组实现不定量
// ES6 可变(数量)参数: { function f(...a){ var sum = 0; a.forEach(item=>{ sum+=item*1 }); return sum } console.log(f(1,2,3,6)) } // ... : 可变运算符,后面的a是一个列表表示可变数量
(3)合并数组的区别:
// ES5: { var params = ['hello', true, 7]; var other = [1, 2].concat(params); console.log(other); }
// ES6:利用扩展运算符合并数组 { var params = ['hello', true, 7]; var other = [ 1,2, ...params ]; console.log(other); }
五、对象代理:
proxyer是代理,打到保护proxy的目的。
(1):
//ES3 中数据保护: { var person = function(){ let data = { name: 'es3', sex: 'male', age: 15, } this.set = function(key, value){ if (key !== 'sex'){ data[key] = value } } } } // 声明一个实例: var person = new Person(); console.table({name: person.get('name')}) person.set('name', 'es3-cname'); console.table({name: person.get('name')}) // 名字被修改 person.set('sex', 'female'); console.table({sex: person.get('sex')}) // 性别修改无用
// ES5 中数据保护:只读要求固定死,过于死板 { var Person = { name: 'es5', age: 15 }; Object.defineProperty(Person, 'sex',{ writable: false, value: 'male' }); Person.name = 'es5-cname'; console.table({name: Person.name}); // 成功修改 Person.sex = 'female'; console.table({sex: Person.sex}); // 报错,实现保护 }
// ES6 数据保护实现:操作的都是代理,元数据不受影响和操作。 { let Person = { name: 'es6', sex: 'male', age: 15 }; let Person = new Proxy(Person, { get(target, key) { return target[key] }, set(target, key, value){ if (key!=='sex'){ target[key]=value; } } }); try{ person.sex='female'; } catch(e) { console.log(e); } finally { } console.table({}) }