箭头函数与()

计算机不智能,看见{}认为是块级作用域,不是对象,人可以分辨出这是个对象,但计算机不行,需要用()包裹{},告诉计算机{}是对象,{}里面的是对象

  1. let foo=(a,b)=>({a:3,b:4});
  2. // let foo=(a,b)=>{a:3,b:4};//SyntaxError: Unexpected token ':'
  3. console.log(foo());

箭头函数与函数的区别:特性

1.this,是外层的函数作用域来决定的
2.=>不能作为构造函数来使用;bind,apply,call();不能实现
this是new出来的,不能new也就没有this
bind,apply,call();不能实现,因为没有this
3 没有arguments对象,用rest(扩展运算符)替代
4 yield命令不能生效,在generator函数中

箭头函数this由外层作用域决定

  1. function foo(){
  2. console.log(this);//obj1{a:2}
  3. return (a)=>{
  4. console.log(this.a)
  5. }
  6. }
  7. var obj1={a:2};
  8. var obj2={a:3};
  9. var bar=foo.call(obj1);
  10. /*箭头函数作用域由外层作用域决定的,foo函数中的this指向的是obj1*/
  11. bar.call(obj2);//2 bar是返回的箭头函数,给箭头函数绑定this给obj2没有用
  12. /*没有办法以箭头函数.call的方式,来改变箭头函数的this指向*/

  1. const person={
  2. /*eat:function (){
  3. }*/
  4. eat(){
  5. console.log(this);
  6. },
  7. drink:()=>{
  8. console.log(this);
  9. }
  10. }
  11. person.eat();//person对象
  12. /*this默认window,只不过person.eat时候给转换成了person,再运行函数*/
  13. person.drink();//window
  14. /*箭头函数就不转了,那就走默认的window*/

箭头函数应用,按钮绑定

  1. <button id="button">button</button>
  2. <script !src="">
  3. (function (){
  4. function Button(){
  5. this.button=document.getElementById('button');
  6. }
  7. Button.prototype={
  8. init(){
  9. this.bindEvent();
  10. },
  11. bindEvent(){
  12. // this.button.addEventListener('click',this.clickBtn.bind(this),false);
  13. /*括号可写可不写,通过箭头函数的this指向this.button对象*/
  14. // this.button.addEventListener('click',(e)=>{this.clickBtn(e)},false);
  15. this.button.addEventListener('click',(e)=>this.clickBtn(e),false);
  16. // this.button.addEventListener('click',this.clickBtn,false);
  17. },
  18. clickBtn(e){
  19. console.log(e);
  20. console.log(this);
  21. }
  22. }
  23. new Button().init();
  24. })()
  25. </script>

多重箭头函数

  1. function foo() {
  2. return () => {
  3. return () => {
  4. return () => {
  5. console.log("id", this.id);
  6. }
  7. }
  8. }
  9. }
  10. var f = foo.call({id: 1});
  11. var f1 = f.call({id: 2})()();
  12. var f2 = f().call({id: 3})();
  13. var f3 = f()().call({id: 4});
  14. /*id 1 id 1 id 1*/
  15. /*箭头函数内部没有this机智,this指向是固化的*/
  1. /*箭头函数内部没有this机制,this指向是固化的=》函数的内部是并没有自己的this,
  2. * 只能够通过父级作用域来获取到this,闭包的this
  3. * 箭头函数拿着父级的this,返回箭头函数,这是个闭包*/
  4. function foo() {
  5. console.log(this);
  6. return () => {
  7. console.log(this)
  8. return () => {
  9. console.log(this)
  10. return () => {
  11. console.log(this);
  12. console.log("id", this.id);
  13. }
  14. }
  15. }
  16. }
  17. var f = foo.call({id: 1});
  18. var f1 = f.call({id: 2})()();
  19. var f2 = f().call({id: 3})();
  20. var f3 = f()().call({id: 4});

image.png

箭头函数没有argument

  1. var test = () => {
  2. console.log(arguments);
  3. //Uncaught ReferenceError: arguments is not defined
  4. }
  5. test();

箭头函数用外层函数作用域的argument

  1. function foo() {
  2. /*这两个是一样的,箭头函数的argument拿着父级函数arguments
  3. *相当于拿着a变量,相当于一个闭包
  4. * 父函数*/
  5. var a=1;
  6. console.log(arguments); //Arguments(7)[1, 2, 3, 4, 5, 6, 7, callee: ƒ, Symbol(Symbol.iterator): ƒ]
  7. setTimeout(() => {
  8. /*子函数*/
  9. console.log(a);//1
  10. console.log(arguments);
  11. console.log(this)//window
  12. })
  13. }
  14. foo(1, 2, 3, 4, 5, 6, 7);
  15. //Arguments(7)[1, 2, 3, 4, 5, 6, 7, callee: ƒ, Symbol(Symbol.iterator): ƒ]

闭包:一个函数的执行,导致另外一个函数的定义,会形成闭包;
foo是闭包,外层父函数是闭包

调试
image.png
image.png
closure就是闭包
foo运行,()=>{}箭头函数在foo函数中被定义,形成了闭包,子函数的scope存储父函数的AO,即使不使用父函数的变量
在这里面使用了父函数的变量

es6简写多重return函数

  1. function insert(value) {
  2. return {
  3. into: function (array) {
  4. return {
  5. after: function (afterValue) {
  6. array.splice(array.indexOf(afterValue) + 1, 0, value);
  7. return array;
  8. }
  9. }
  10. }
  11. }
  12. }
  13. console.log(insert(5).into([1, 2, 3, 4, 6, 7, 8]).after(4));
  14. /*
  15. [1, 2, 3, 4, 5, 6, 7, 8]把5插入数组的第下标为4的地方
  16. */

es6简写

  1. let insert = (value) => ({
  2. into: (array) => ({
  3. after: (afterValue) => {
  4. array.splice(array.indexOf(afterValue) + 1, 0, value);
  5. return array;
  6. }
  7. })
  8. })
  9. console.log(insert(5).into([1, 2, 3, 4, 6, 7, 8]).after(4));
  10. /*
  11. [1, 2, 3, 4, 5, 6, 7, 8]把5插入数组的第下标为4的地方
  12. */

其实是不建议这样写的,箭头函数其实是有相应的使用场景的,这里不是很复杂,如果再复杂会很麻烦,语义化不是很好,({})很像立即执行函数({})(),并不容易读懂代码

箭头函数使用场景

箭头函数使用场景
1简单的函数表达式,只有一行,比如仅仅是return一个计算值
简单的函数表达式,得出唯一的return的计算值,函数内部没有this的引用,递归,事件绑定、事件解绑定,用重构箭头函数的方式,是最好的

比如排序,这样简单明了,只用一行语句,非常容易读懂

  1. [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这时想想能不能用箭头函数加展开表达式

  1. function sortNumber() {
  2. return Array.prototype.slice.call(arguments).sort(function(a, b) {
  3. return a - b;
  4. })
  5. }
  6. -->ES6改写
  7. const sortNumber = (...numbers) => numbers.sort( (a, b) => a - b );

不适合用箭头函数的情况
函数声明,执行语句比较多的,还需要用到递归,需要引用函数名,事件绑定,解绑定,避免用=>