你好C 2017-12-04
这里只做简单的ES6函数与ES5函数对比,把ES6函数中新增的方法或者用法介绍一下。方便大家学习、记忆。随着社会发展,浏览器肯定会在不久全部支持ES6语法,因为现在的IE8用户都很少了,做web前端将不再受此束缚!
其他语言已经支持函数参数默认值,咱们Js也不会落后的。例:
//es6写法 /** * @a {number} 默认值10 * @b {number} 默认值20 * */ function fn(a=10,b=20){ console.log(a,b); } fn();//没有传递参数 fn(1,3);//传递了参数 //es5写法 /** * @a {number} 默认值10 * @b {number} 默认值20 * */ function fn(a, b) { a = a || 10;//设置默认值 b = b || 20;//设置默认值 console.log(a, b); }
//修改es5写法让它实现类似于es6: //es5写法 /** * @a {number} 默认值10 * @b {number} 默认值20 * */ function fn(a, b) { a = a!==undefined?a:10;//设置默认值 b = b!==undefined?b:20;//设置默认值 console.log(a, b); }
/** * es6写法 * @a {number} 默认值10 * @b {number} 默认值20 * */ function fn(a=10,b=20){ let a=100;//会报错哦! const b=20;//会报错哦! console.log(a,b); }
/** * es6写法 * 默认值会产生单独的作用域,作用域的代码也是按照先左后右顺序执行。 * @a {number} 默认值10 * @b {number} 默认值10+20 * */ function fn(a=10,b=a+20){//如果这里是(a=b+20,b=10)调用时a没有传递参数此时会报错! console.log(a,b); } //复杂的例子 /*-----------一条华丽的分割线-------------*/ /** * ----------默认值会产生单独的作用域----------- * 调用函数fn 时,未传递参数,【默认参数单独作用域】a值为undefined,b值为undefined。 * 当执行b()函数时,则查找到a值为undefined,不在查找全局a。 * 因此为结果为:a的值为: undefined * */ var a='全局变量'; function fn(a,b=function(){ console.log('a的值为:',a);}){ b(); } fn();//a的值为: undefined /** * ----------默认值会产生单独的作用域----------- * 调用函数fn 时,未传递参数,b值为undefined。 * 当执行b()函数时,则寻找a值发现全局a。 * 因此为结果为:a的值为: 全局变量 * */ var a='全局变量'; function fn(b=function(){ console.log('a的值为:',a);}){ b(); } fn();//a的值为: 全局变量 ** * 现在再来理解一下这个。看看你能答对吗? * */ var a = '小小坤'; function fn(a, y = function() {a = '小小坤1';}) { var a = '小小坤2'; y(); console.log(a); } fn() // 答案是? console.log(a); // 答案是?
function fn(a,a,b){ console.log(a,b);//不报错 } function fn(a,a,b=1){ console.log(a,b);//报错 }
ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。例:
//es6写法 /** * @b {arry} 参数列表 * * */ function fn(...b){ b.push('小小坤'); console.log(b); } fn(1,'20');//[1, "20", "小小坤"] //es5写法 /** * @a {number} 参数a * @b {number} 参数b * */ function fn(a, b) { var arg=[].slice.call(arguments); arg.push('小小坤'); console.log(arg); }
需要注意的是:
(function(a) {}).length // 1 (function(...a) {}).length // 0 (function(a, ...b) {}).length // 1
function fn (a,...b,d){ //会报错! }
1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。 2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。 3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。 4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
/*-----------例子--1------*/ //es6写法 var fn = n => n; //等同于es5 写法 var fn = function(n) { return n; };
/*-----------例子--2------*/ //es6写法 var fn = () => 5; // 等同于 es5 写法 var fn = function () { return 5 };
/*-----------例子--3------*/ //es6写法 var sum = (n1, n2) => n1 + n2; // 等同于es5 写法 var sum = function(n1, n2) { return n1 + n2; };
如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。
/*-----------例子--4------*/ //es6写法 var sum = (n1, n2) => { return n1+n2; } //由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。 // 报错 let fn = id => { id: id, age: 18 }; // 不报错 let fn = id => ({ id: id, age: 18 });
/*-----------例子--5------*/ function fn() { setTimeout(() => { console.log('id:', this.id); }, 100); } var id = 21; fn.call({ id: 42 }); // id: 42 //ES5代码需要这样写 function fn() { var _this=this;//存储this setTimeout(function() { console.log('id:', _this.id); }, 100); } var id = 21; fn.call({ id: 42 }); /** * 上面代码中,setTimeout的参数是一个箭头函数,这个箭头函数的定义生效是在fn函数生成时, * 而它的真正执行要等到 100 毫秒后。如果是普通函数,执行时this应该指向全局对象window, * 这时应该输出21。但是,箭头函数导致this总是指向函数定义生效时所在的对象(本例是{id: 42}), * 所以输出的是42。 * 箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域。 * * 另外,由于箭头函数没有自己的this,所以当然也就不能用call()、apply()、bind()这些方法去改变this的指向。 * */
//this指向lib var lib={ option:{ name:'小小坤' }, init(){ this.click(); }, click(){ setTimeout(()=>{ console.log(this.option.name); },2000); } } lib.init();//小小坤
var des=(n)=>{this.n=n}; new des(1);//des is not a constructor //因为没有this
var des=(n)=>{console.log(arguments)}; des();//arguments is not defined //可以这样使用 var des=(...n)=>{console.log(n)}; des(1,2,3,4,5);//[1,2,3,4,5]
经过以上对比可以看出ES6写的代码会越来越少,代码质量也逐渐提升。比如默认参数,箭头函数,还有rest 参数,使用起来爽爆棚!没有在开发环境使用的ES6的同学我们也要抓紧学习啦!