ES6箭头函数详解:语法、简写规则与this指向机制

作者:小括号时间:2026-10-25 23:48:18浏览:624

本文深入解析ES6箭头函数的语法特性,包括简写规则、对象返回注意事项及this绑定机制。通过对比ES5与普通函数,详细演示map、filter、reduce等数组方法中箭头函数的实际应用,并结合网络请求案例说明其在解决this指向问题时的优势与局限性。

箭头函数

ES6引入了箭头函数这一新语法,它不仅大幅简化了代码书写,使代码结构更加简洁优雅,还有效解决了传统函数中this指向容易混淆的问题。接下来将详细解析箭头函数的使用技巧。

语法规则

在介绍新语法之前,先回顾一下传统的函数定义方式。

function foo1(){}
var foo2 = function(name,age){
	console.log("函数体代码",this,arguments);
  console.log(name,age);
}

箭头函数的标准完整写法。

var foo3 = (name,age) => {
	console.log("箭头函数的函数体")
  console.log(name,age);
}

利用箭头函数遍历数组元素。

这是ES5及早期版本中常用的数组遍历写法。

var names = ["abc","cba","nba"];
names.forEach(function(item)){
	console.log(item);
})

使用箭头函数进行数组遍历的简化写法。

names.forEach((item,idx,arr)=>{
  console.log(item,idx,arr);
	} 
)

箭头函数

setTimeout(()=>{
	console.log("setTimeout");
},3000)

简写规则

当箭头函数仅包含一个形参时,包裹形参的小括号()可以省略。

name.forEach(item =>{
console.log(item);
}

结合filter()函数与箭头函数,可以高效地筛选出符合特定条件的数字。

var newNums = nus.filter(item =>{
  return item % 2;
})

若函数体仅包含一行执行代码,则可以省略大括号{}。此时,该行代码的执行结果将自动作为函数的返回值,无需显式使用return关键字。

names.forEach(item => console.log(item));

当filter()函数的回调逻辑仅有一行时,可以直接省略大括号{}以简化代码。

varans = worker.filter( item=>item % 2 )

若箭头函数的默认返回值是一个对象字面量,则必须将该对象包裹在小括号()中。

这一技巧在React结合Redux的状态管理代码中十分常见。

当箭头函数同时遇到执行体的大括号和对象的大括号时,JavaScript引擎可能无法正确区分两者。

var arrFn = () =>{<!--{C}%3C!%2D%2D%20%2D%2D%3E-->} //此大括号是执行体
var arrFn = () =>{<!--{C}%3C!%2D%2D%20%2D%2D%3E--> name : "why"}// 此大括号是对象

因此,为了明确区分执行体与返回的对象,必须给对象字面量加上小括号()。

var arrFn = () =>({<!--{C}%3C!%2D%2D%20%2D%2D%3E--> name : "why"})

常见应用

map

map()方法定义在JavaScript的Array原型中,它返回一个新数组,新数组中的元素是原始数组元素经过回调函数处理后的结果。

使用map()时需要注意以下几点:

  • map()函数不会检测空数组,若数组为空,回调函数不会执行。
  • map()函数不会修改原始数组,而是生成并返回一个全新的数组。
  • array.map(function(currentValue, index, arr), thisIndex)

参数说明:

  • function(currentValue,index,arr):必填
    • 数组中的每个元素都会依次执行该回调函数。
    • currentValue:必填参数,表示当前正在处理的元素值。
    • index:可选参数,表示当前元素的索引,即第几个数组元素。
    • arr:可选参数,表示当前元素所属的原数组对象。
  • thisValue:可选参数,当提供此参数时,它将被用作回调函数执行时的this值。

示例1:将原数组中的每个元素平方后,赋值给一个新数组。

let arry = [1,2,3,4];
let newArray = array.map((item)=>{
  return item*item;
})

上述逻辑可以简化为一行代码实现。

let newArray = array.map(item =>item * item)

示例2:筛选出原数组中的偶数,将其平方后赋值给新数组。

filter

filter()方法用于对数组进行过滤操作。

  • 其原理是创建一个新数组,新数组中包含所有通过指定数组中元素检查条件的项。
  • filter将传入的回调函数依次作用于每个元素,根据回调返回true或false来决定保留或丢弃该元素。
  • Array.filter(function(currentValue, index, arr), thisValue)

参数说明:

  • function(currentValue,index,arr):必填
    • 数组中的每个元素都会执行该回调函数。
    • currentValue:必填参数,表示当前元素的值。
    • index:可选参数,表示当前元素的索引,即第几个数组元素。
    • arr:可选参数,表示当前元素所属的原数组对象。
  • thisValue:可选参数,对象作为该执行回调时使用,传递给函数,用作“this”的值。
let newArray = array.filter(item=>item%2===0).map(item =>item * item)

示例3:筛选出原数组中偶数索引的元素,将其平方后赋值给新数组。

  let array = [1, 2, 3, 4];
  let newArray = array.filter((item,idx)=>idx%2===0).map(item =>item * item)

示例4:巧妙利用arr参数,结合indexOf实现数组去重。

var newArray = array.filter((item,idx,arr)=>arr.indexOf(item) === idx)

示例2(注:原文编号重复,此处按逻辑顺延):对原数组中的偶数进行平方后求累加和。

reduce

  • reduce方法用于遍历数组,支持设置初始值,这大大增强了代码的可读性,同时提供了一个参数用于累计计算。
  • array.reduce((pre, cur, index, arr),init)

参数说明:

  • function((pre, cur, index, arr)):必填
    • pre:必填参数,表示累积值。
    • cur:必填参数,表示当前元素。
    • index:可选参数,表示当前元素的索引。
    • arr:可选参数,表示当前元素所属的数组。
  • init:可选参数,传递给函数的初始值。当传入参数为两个时,init是累计值pre的初始值。

如果reduce的参数只有一个,那么累计值的初始值是数组的第一个值。

如果reduce的参数有两个,那么积累值初始值就是设置好的参数init初始值。

在每一次迭代中,返回的值都作为下一次迭代的pre累计值。

var ans = arr.filter(item=>item%2).map(item=>item*item).reduce((x,y)=>x+y,0);

箭头函数中的this使用

在普通函数中,this是一个动态绑定的标识符。

function foo(){
	console.log("foo",this);
}
foo()//window
foo.apply("aaa")//aaa

在箭头函数中,根本不存在this标识符。

var bar = ()=>{console.log("bar",this)}
bar()//window
bar.apply("AAA")//window

concat

concat()方法用于连接两个或多个数组,返回一个新的合并数组。

var arr  = [1, 2, 3, 4];
var arr2 = [7, 8, 9, 10];
var ans = [].concat(arr,arr2);

console.log(ans);//输出:(8) [1, 2, 3, 4, 7, 8, 9, 10]

this的查找规则

由于箭头函数内部没有this标识符,当在箭头函数内部调用this时。

JavaScript引擎会从当前作用域由内向外查找包含this指向的外层作用域。

var obj ={
	name:"obj",
  foo:function(){
    var bar = ()=>{
      console.log("bar",this);
    }
    return bar;
  }
}

第一层bar箭头函数:没有this。

第二层function函数:指向obj。

因此,示例中的this指向obj。

var obj ={
	name:"obj",
  foo:()=>{
  	var bar =()=>{
      console.log("bar:",this);
    }
    return bar;
  }
}
  • 第一层bar箭头函数:没有this。
  • 第二层foo箭头函数:没有this。
  • 第三层全局作用域:指向window。

因此,示例中的this指向window。

模拟网络发送请求

封装request工具函数

function request(url,callback){
  	var res = ["abc","cba","nba"];
    callback(res);
}

实际操作的位置

  • 早期的写法

因为此时传入request的function,实际上就是request定义中的callback()。

因此,function中的参数即为request定义中的res数组,随后将其赋值给当前对象中的names属性。

但由于普通函数作为回调函数时,其this指向window,因此需要在外部函数中定义一个_this变量来指向当前对象。

var _this = this;

然后,将获取到的res数组赋值给_this中的names属性。

_this.name = [].concat(ans);
var obj = {
	names:[],
  network:function(){
    var _this = this;
    request("/names",function(ans){
    _this.name = [].concat(ans);
  })
}

箭头函数的写法

由于箭头函数本身没有this,JavaScript引擎会由内向外查找this的指向。

发现外层函数的this指向obj,因此箭头函数中的this也指向obj。

var obj = {
	names:[],
  network:function(){
    request("/names",(ans)=>{
    this.name = [].concat(ans);
  })
}

下面对比ES5与ES6中关于箭头函数的直接使用差异。

//es5
var fn = function(a, b){return a+b}
//es6   直接被return时候可以省略函数体的括号
const fn=(a,b) => a+b;

//es5
var foo = function(){
    var a=20;
    var b= 30;
    return a+b;
}
//es6
const foo=()=>{
    const a= 20;
    const b=30;
    return a+b  
}

// 注意这里   箭头函数可以替代函数表达式但是不能替代函数声明

回到this问题上,从语义上讲,箭头函数没有this。如果使用了this,它一定是外层作用域的this,而不会自动指向window对象。因此,不能使用call/apply/bind来改变箭头函数的this指向。

var person = {
    name: 'tom',
    getName: function() {
        return this.name;
    }
}

使用es6 来重构上面的对象
const person = {
    name:'tom',
    getName:()=>this.name
}
这样编译的结果就是
var person ={
    name:'tom',
    getName:function getName(){return undefined.name}
}

在ES6中,默认采用严格模式,因此this不会自动指向window对象。而箭头函数本身没有this,所以其this值为undefined。这一点在使用时必须格外谨慎,否则容易陷入难以排查的bug。如果仍需使用this,应避免使用箭头函数写法。

// 可以稍做改动
const person = {
    name: 'tom',
    getName: function() {
        return setTimeout(() => this.name, 1000);
    }
}

// 编译之后变成
var person = {
    name: 'tom',
    getName: function getName() {
        var _this = this;  // 使用了我们在es5时常用的方式保存this引用

        return setTimeout(function () {
            return _this.name;
        }, 1000);
    }
};

完结散花

到此这篇关于JavaScript高级教程之如何玩转箭头函数的文章就介绍到这了,更多相关JS箭头函数内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

参考文献

coderwhy老师JS高级视频教程

作者最新文章