箭头函数

使用“箭头”(=>)定义函数
var f = v => v;
// 等同于
var f = function (v) {
  return v;
};
需要多个参数,就使用一个圆括号代表参数部分
var f = () => 5;
// 等同于
var f = function () { return 5 };

var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
  return num1 + num2;
};
如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。
var sum = (num1, num2) => { return num1 + num2; }
由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。
// 报错
let getTempItem = id => { id: id, name: "Temp" };

// 不报错
let getTempItem = id => ({ id: id, name: "Temp" });
如果箭头函数只有一行语句,且不需要返回值,可以采用下面的写法,就不用写大括号了
let fn = () => void doesNotReturn();
简化回调函数
// 正常函数写法
[1,2,3].map(function (x) {
  return x * x;
});

// 箭头函数写法
[1,2,3].map(x => x * x);
// 正常函数写法
var result = values.sort(function (a, b) {
  return a - b;
});

// 箭头函数写法
var result = values.sort((a, b) => a - b);
rest 参数与箭头函数结合的例子  
const numbers = (...nums) => nums;
numbers(1, 2, 3, 4, 5)
// [1,2,3,4,5]

const headAndTail = (head, ...tail) => [head, tail];
headAndTail(1, 2, 3, 4, 5)
// [1,[2,3,4,5]]

箭头函数有几个使用注意点。

箭头函数this总是指向 函数定义生效时所在的对象

function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}
var id = 21;
foo.call({ id: 42 });
// id: 42

箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域

 

function Timer() {
  this.s1 = 0;
  this.s2 = 0;
  // 箭头函数
  setInterval(() => this.s1++, 1000);
  // 普通函数
  setInterval(function () {
    this.s2++;
  }, 1000);
}

var timer = new Timer();

setTimeout(() => console.log('s1: ', timer.s1), 3100);
setTimeout(() => console.log('s2: ', timer.s2), 3100);
// s1: 3
// s2: 0
Timer函数内部设置了两个定时器,分别使用了箭头函数和普通函数。
前者的this绑定定义时所在的作用域(即Timer函数),
后者的this指向运行时所在的作用域(即全局对象)
所以,3100 毫秒之后,timer.s1被更新了 3 次,
timer.s2一次都没更新。

箭头函数根本没有自己的this,不能用作构造函数

内部的this就是外层代码块的this

// ES6
function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

// ES5
function foo() {
  var _this = this;

  setTimeout(function () {
    console.log('id:', _this.id);
  }, 100);
}

嵌套多个箭头函数

function foo() {
  return () => {
    return () => {
      return () => {
        console.log('id:', this.id);
      };
    };
  };
}

var f = foo.call({id: 1});

var t1 = f.call({id: 2})()(); // id: 1
var t2 = f().call({id: 3})(); // id: 1
var t3 = f()().call({id: 4}); // id: 1
上面代码之中,只有一个this
就是函数foothis
所以t1t2t3都输出同样的结果。
因为所有的内层函数都是箭头函数,
都没有自己的this
它们的this其实都是最外层foo函数的this

箭头函数之中不存在的:this、argumentssupernew.target

function foo() {
  setTimeout(() => {
    console.log('args:', arguments);
  }, 100);
}

foo(2, 4, 6, 8)
// args: [2, 4, 6, 8] 箭头函数内部的变量arguments,其实是函数fooarguments变量

箭头函数没有自己的this,所以当然也就不能用call()apply()bind()这些方法去改变this的指向。

(function() {
  return [
    (() => this.x).bind({ x: 'inner' })()
  ];
}).call({ x: 'outer' });
// ['outer'] 箭头函数没有自己的this,所以bind方法无效,内部的this指向外部的this

  eg1

const cat = {
  lives: 9,
  jumps: () => {
    this.lives--;
  }
}
如果是普通函数,该方法内部的this指向cat
箭头函数,使得this指向全局对象

  eg2

var button = document.getElementById('press');
button.addEventListener('click', () => {
  this.classList.toggle('on');
});
上面代码运行时,点击按钮会报错,
因为button的监听函数是一个箭头函数,导致里面的this就是全局对象。
如果改成普通函数,this就会动态指向被点击的按钮对象。

  

 

posted @ 2020-03-24 15:52  banzhuxiang  阅读(296)  评论(0)    收藏  举报