wangjing013 / blog

📝 记录

Home Page:https://wangjing013.github.io/blog/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ES6 之箭头函数

wangjing013 opened this issue · comments

ES6 中引入新的创建函数的方式 箭头函数

它与普通函数有什么区别 ? 下面先来看看它的语法特性.

箭头函数语法:

const getName = () => '张三';
const getAge = function(){ return 28 };

从语法层面看, 箭头函数与普通函数区别好像就是语法上的简写. 真的是这样 ? 显然不是.

下面了解箭头函数的特性,也就是它与普通函数的区别.

箭头函数特性:

1. 没有 this

指向的是全局上下文或外围最近一层非箭头函数的上下文.

2. 没有 arguments

通常函数内部都有一个 arguments 变量, 但箭头函数没有.

const arrowFunction = () => console.log(arguments); 
arrowFunction(); //=>  Uncaught ReferenceError: arguments is not defined

虽然自身没有, 但可以访问外围非箭头函数的 arguments:

const createArrowFunction = function(name){
   return () => arguments[0]
}
const arrowFunction = createArrowFunction('张三');
console.log(arrowFunction()); //=> 张三

之所以能够访问到, 因为作用域链的存在.

3. 不能通过 new 去调用

const arrowFunction = () => 'arrowFunction';
new arrowFunction();  // Uncaught TypeError: arrowFunction is not a constructor

箭头函数内部不包含 [[Construct]] 方法, 当使用 new 关键调用会调用[[Construct]] 从而生成实例对象.

4. 没有 prototype 属性

const fn = function (){};
console.log(fn.prototype); //=> {constructor: ƒ}
const arrowFunction = () => 'arrowFunction';
console.log(arrowFunction.prototype); //=> undefined

由于不能使用 new关键字调用箭头函数, 因而没有构建原型对象的需求. 所以箭头函数不存在 prototype 属性

5. 没有 super

连原型都没有,自然也不能通过 super 来访问原型的属性. 不过同 thisarguments 一样它由其外层的非箭头函数决定.

class Parent {
    show(msg) {
      console.log(`Parent#show: ${msg}`);
    }
}

class Child extends Parent {
   method(arg) {
    let inner = () => {
      super.show(`arg = ${arg}`);
    };
    inner();
   }
}
new Child().method('arg')

6. 没有 new.target

因为不能使用 new , 所以也就不存在 new.target.

const arrowFunction = () => new.target; //=> Uncaught SyntaxError: new.target expression is not allowed here

具体new.target可以参考这里

7. this 不可改变

通常JS允许我们通过 callapplybind 硬绑定的方式去更改 this 的值, 但是在箭头函数上无效.

const createArrowFunction = function(){
   return () => { console.log(this) }
}
const arrowFunction = createArrowFunction();
arrowFunction.call({}); //=> window

const foo = function(){
   console.log(this);
}
foo(); //=> window
foo.call({}); //=> {}

8. 不支持重复的函数命名参数(严格或非严格模式下)

const createArrowFunction = (name, name) => {};  //=>  Uncaught SyntaxError: Duplicate parameter name not allowed in this context

箭头函数常见应用

  • 事件绑定
const dom = {
  bindEvent(){
      const btn = document.querySelector("#btn");
      btn.addEventListener('click', function(event){
         this.show(); //=>  Uncaught TypeError: this.show is not a function
      }) 
  },
  show(){
    console.log("show");
  }
}

此时 this 表示当前点击当目标对象(event.target ), 它不存在 show 方法, 所以报错了.

在ES6之前, 通过闭包来解决这个问题, 修改如下:

const dom = {
  bindEvent(){
      const btn = document.querySelector("#btn");
      const that = this;
      btn.addEventListener('click', function(event){
         that.show(); 
      }) 
  },
  show(){
    console.log("show"); //=> show
  }
}

现在可以通过箭头函数来优雅解决该问题:

const dom = {
  bindEvent(){
      const btn = document.querySelector("#btn");
      btn.addEventListener('click', (event) => {
         that.show(); 
      }) 
  },
  show(){
    console.log("show"); //=> show
  }
}
  • 数组中的应用
    通过数组 map 函数修改对一个 number 类型数组中的每一项进行累加, 如下:
const arr = [1,2,3,4,5,6];

// 通常写法如下
arr.map(function(val, index, arr){
  return val + 1;
})  //=> [2, 3, 4, 5, 6, 7]

// 使用箭头函数
arr.map(val =>  val + 1); //=> [2, 3, 4, 5, 6, 7]

这里只是列举一些常见的用法. 其实还有很多用途.

总结

  • 没有 thissuperargumentsnew.target 绑定,箭头函数中的 thissuperargumentsnew.target 都是由外层的非箭头函数决定
  • 不能通过 callapplybind 等方式修改 this 的值
  • 不能使用 new 关键字
  • 没有 prototype 属性
  • 没有 arguments 变量
  • JS 中常见错误来源, 在函数内很容易对 ``this ` 值失去控制, 其经常导致程序出现意想不到的行为. 箭头函数很好的消除这方面的烦恼.