箭头函数与()
计算机不智能,看见{}认为是块级作用域,不是对象,人可以分辨出这是个对象,但计算机不行,需要用()包裹{},告诉计算机{}是对象,{}里面的是对象
let foo=(a,b)=>({a:3,b:4});// let foo=(a,b)=>{a:3,b:4};//SyntaxError: Unexpected token ':'console.log(foo());
箭头函数与函数的区别:特性
1.this,是外层的函数作用域来决定的
2.=>不能作为构造函数来使用;bind,apply,call();不能实现
this是new出来的,不能new也就没有this
bind,apply,call();不能实现,因为没有this
3 没有arguments对象,用rest(扩展运算符)替代
4 yield命令不能生效,在generator函数中
function foo(){console.log(this);//obj1{a:2}return (a)=>{console.log(this.a)}}var obj1={a:2};var obj2={a:3};var bar=foo.call(obj1);/*箭头函数作用域由外层作用域决定的,foo函数中的this指向的是obj1*/bar.call(obj2);//2 bar是返回的箭头函数,给箭头函数绑定this给obj2没有用/*没有办法以箭头函数.call的方式,来改变箭头函数的this指向*/
const person={/*eat:function (){}*/eat(){console.log(this);},drink:()=>{console.log(this);}}person.eat();//person对象/*this默认window,只不过person.eat时候给转换成了person,再运行函数*/person.drink();//window/*箭头函数就不转了,那就走默认的window*/
<button id="button">button</button><script !src="">(function (){function Button(){this.button=document.getElementById('button');}Button.prototype={init(){this.bindEvent();},bindEvent(){// this.button.addEventListener('click',this.clickBtn.bind(this),false);/*括号可写可不写,通过箭头函数的this指向this.button对象*/// this.button.addEventListener('click',(e)=>{this.clickBtn(e)},false);this.button.addEventListener('click',(e)=>this.clickBtn(e),false);// this.button.addEventListener('click',this.clickBtn,false);},clickBtn(e){console.log(e);console.log(this);}}new Button().init();})()</script>
function foo() {return () => {return () => {return () => {console.log("id", this.id);}}}}var f = foo.call({id: 1});var f1 = f.call({id: 2})()();var f2 = f().call({id: 3})();var f3 = f()().call({id: 4});/*id 1 id 1 id 1*//*箭头函数内部没有this机智,this指向是固化的*/
/*箭头函数内部没有this机智,this指向是固化的=》函数的内部是并没有自己的this,* 只能够通过父级作用域来获取到this,闭包的this* 箭头函数拿着父级的this,返回箭头函数,这是个闭包*/function foo() {console.log(this);return () => {console.log(this)return () => {console.log(this)return () => {console.log(this);console.log("id", this.id);}}}}var f = foo.call({id: 1});var f1 = f.call({id: 2})()();var f2 = f().call({id: 3})();var f3 = f()().call({id: 4});

var test = () => {console.log(arguments);//Uncaught ReferenceError: arguments is not defined}test();
function foo() {/*这两个是一样的,箭头函数的argument拿着父级函数arguments*相当于拿着a变量,相当于一个闭包* 父函数*/var a=1;console.log(arguments); //Arguments(7)[1, 2, 3, 4, 5, 6, 7, callee: ƒ, Symbol(Symbol.iterator): ƒ]setTimeout(() => {/*子函数*/console.log(a);//1console.log(arguments);console.log(this)//window})}foo(1, 2, 3, 4, 5, 6, 7);//Arguments(7)[1, 2, 3, 4, 5, 6, 7, callee: ƒ, Symbol(Symbol.iterator): ƒ]
闭包:一个函数的执行,导致另外一个函数的定义,会形成闭包;
foo是闭包,外层父函数是闭包
调试

closure就是闭包
foo运行,()=>{}箭头函数在foo函数中被定义,形成了闭包,子函数的scope存储父函数的AO,即使不使用父函数的变量
在这里面使用了父函数的变量
function insert(value) {return {into: function (array) {return {after: function (afterValue) {array.splice(array.indexOf(afterValue) + 1, 0, value);return array;}}}}}console.log(insert(5).into([1, 2, 3, 4, 6, 7, 8]).after(4));/*[1, 2, 3, 4, 5, 6, 7, 8]把5插入数组的第下标为4的地方*/
es6简写
let insert = (value) => ({into: (array) => ({after: (afterValue) => {array.splice(array.indexOf(afterValue) + 1, 0, value);return array;}})})console.log(insert(5).into([1, 2, 3, 4, 6, 7, 8]).after(4));/*[1, 2, 3, 4, 5, 6, 7, 8]把5插入数组的第下标为4的地方*/
其实是不建议这样写的,箭头函数其实是有相应的使用场景的,这里不是很复杂,如果再复杂会很麻烦,语义化不是很好,({})很像立即执行函数({})(),并不容易读懂代码
箭头函数使用场景
1简单的函数表达式,只有一行,比如仅仅是return一个计算值
简单的函数表达式,得出唯一的return的计算值,函数内部没有this的引用,递归,事件绑定、事件解绑定,用重构箭头函数的方式,是最好的
比如排序,这样简单明了,只用一行语句,非常容易读懂
[12,3,1234,1,4].sort((a,b)=>a-b);
2.内层的函数表达式,需要调用this,var self=this,bind(this),确保适当的this指向的时候
3.var args = Array.prototype.slice.call(arguments);
如果用到Array.prototype.slice.call这时想想能不能用箭头函数加展开表达式
function sortNumber() {return Array.prototype.slice.call(arguments).sort(function(a, b) {return a - b;})}-->ES6改写const sortNumber = (...numbers) => numbers.sort( (a, b) => a - b );
不适合用箭头函数的情况
函数声明,执行语句比较多的,还需要用到递归,需要引用函数名,事件绑定,解绑定,避免用=>
