普通函数与箭头函数的区别

箭头函数

let fun = () => {
    console.log('lalalala');
}

复制代码

普通函数:

function fun() {
    console.log('lalla');
}
复制代码

箭头函数至关于匿名函数,而且简化了函数定义。箭头函数有两种格式,一种只包含一个表达式,连{ ... }和return都省略掉了。还有一种能够包含多条语句,这时候就不能省略{ ... }和return。bash

箭头函数是匿名函数,不能做为构造函数,不能使用newapp

区别

箭头函数是匿名函数,不能做为构造函数,不能使用new

let FunConstructor = () => {
    console.log('lll');
}

let fc = new FunConstructor();

复制代码

箭头函数不绑定arguments,取而代之用rest参数...解决

function A(a){
  console.log(arguments);
}
A(1,2,3,4,5,8);  //  [1, 2, 3, 4, 5, 8, callee: ƒ, Symbol(Symbol.iterator): ƒ]


let B = (b)=>{
  console.log(arguments);
}
B(2,92,32,32);   // Uncaught ReferenceError: arguments is not defined


let C = (...c) => {
  console.log(c);
}
C(3,82,32,11323);  // [3, 82, 32, 11323]
复制代码

箭头函数不绑定this,会捕获其所在的上下文的this值,做为本身的this值

函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。函数

var obj = {
  a: 10,
  b: () => {
    console.log(this.a); // undefined
    console.log(this); // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
  },
  c: function() {
    console.log(this.a); // 10
    console.log(this); // {a: 10, b: ƒ, c: ƒ}
  }
}
obj.b(); 
obj.c();
复制代码
function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

var id = 21;

foo.call({ id: 42 });
// id: 42
复制代码

上面代码中,setTimeout的参数是一个箭头函数,这个箭头函数的定义生效是在foo函数生成时,而它的真正执行要等到 100 毫秒后。若是是普通函数,执行时this应该指向全局对象window,这时应该输出21。可是,箭头函数致使this老是指向函数定义生效时所在的对象(本例是{id: 42}),因此输出的是42。post

箭头函数可让setTimeout里面的this,绑定定义时所在的做用域,而不是指向运行时所在的做用域。下面是另外一个例子。ui

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指向固定化,这种特性颇有利于封装回调函数。下面是一个例子,DOM 事件的回调函数封装在一个对象里面。spa

var handler = {
  id: '123456',

  init: function() {
    document.addEventListener('click',
      event => this.doSomething(event.type), false);
  },

  doSomething: function(type) {
    console.log('Handling ' + type  + ' for ' + this.id);
  }
};
复制代码

上面代码的init方法中,使用了箭头函数,这致使这个箭头函数里面的this,老是指向handler对象。不然,回调函数运行时,this.doSomething这一行会报错,由于此时this指向document对象。prototype

this指向的固定化,并非由于箭头函数内部有绑定this的机制,实际缘由是箭头函数根本没有本身的this,致使内部的this就是外层代码块的this。正是由于它没有this,因此也就不能用做构造函数。rest

var obj = {
  a: 10,
  b: function(){
    console.log(this.a); //10
  },
  c: function() {
     return ()=>{
           console.log(this.a); //10
     }
  }
}
obj.b(); 
obj.c()();
复制代码

箭头函数经过 call() 或 apply() 方法调用一个函数时,只传入了一个参数,对 this 并无影响。

let obj2 = {
    a: 10,
    b: function(n) {
        let f = (n) => n + this.a;
        return f(n);
    },
    c: function(n) {
        let f = (n) => n + this.a;
        let m = {
            a: 20
        };
        return f.call(m,n);
    }
};
console.log(obj2.b(1));  // 11
console.log(obj2.c(1)); // 11
复制代码

箭头函数没有原型属性

var a = ()=>{
  return 1;
}

function b(){
  return 2;
}

console.log(a.prototype);  // undefined
console.log(b.prototype);   // {constructor: ƒ}
复制代码

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

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

(2)不能够看成构造函数,也就是说,不可使用new命令,不然会抛出一个错误。

(3)不可使用arguments对象,该对象在函数体内不存在。若是要用,能够用 rest 参数代替。

(4)不可使用yield命令,所以箭头函数不能用做 Generator 函数。

上面四点中,第一点尤为值得注意。this对象的指向是可变的,可是在箭头函数中,它是固定的。

相关文章
相关标签/搜索