箭头函数和this

本文深入探讨了JavaScript箭头函数的语法糖特性,包括其与传统函数的区别,如this绑定、参数解析及函数体的实现方式。同时,文章还讨论了箭头函数在回调函数、setTimeout及setInterval中的应用,以及其在this指向、arguments对象和构造函数等方面的限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

箭头函数

var f = v => v;
//等同于
var f = function () {
	return v
}
  1. 多个参数或不需要参数

    var f = () => 5;
    //等同于
    var f = function () { return 5 }

    var sum = (num1, num2) => num1 + num2;
    //等同于
    var f = function (num1, num2) {
    return num1 + num2
    }

  2. 如果箭头函数的代码块部分多于一条语句,就要使用大括号将他们括起来,并且使用return语句返回。由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。

    //报错
    let getItem = id => {id: id, name: ‘temp’};

    //不报错
    let getItem = id => ({id: id, name: ‘temp’});

下面是一种特殊情况,虽然可以运行,但会得到错误的结果。

let foo = () => { a: 1 };
foo() // undefined

上面代码中,原始意图是返回一个对象{ a: 1 },但是由于引擎认为大括号是代码块,所以执行了一行语句a: 1。这时,a可以被解释为语句的标签,因此实际执行的语句是1;,然后函数就结束了,没有返回值。

如果箭头函数只有一行语句,且不需要返回值,可以采用下面的写法,就不用写大括号了。

let fn = () => void doesNotReturn();
注意
  1. 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

    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指向固定化,这种特性很有利于封装回调函数。

     var handle = {
     	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,总是指向handle对象。否则,回调函数运行时,this.doSomething这一行会报错,因为此时this指向document对象。

    this指向的固定化(箭头函数使得this从“动态”变成“静态”),并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this指向,所以也就不能用作构造函数。

    除了this,以下三个变量在箭头函数之中也是不存在的,指向外层函数的对应变量:arguments、super、new.target

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

  2. 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

  3. 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用rest参数代替。

  4. 不可以使用yield命令,因此箭头函数不能用作Generator函数。

什么是this

函数实际上是对象。每个函数都是Function类型的实例,而且都有与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定(函数是对象,函数名是指针)。

函数声明会在解析过程中得到提升,函数表达式则不会。

每个函数在被调用时都会自动取得两个特殊变量:this和arguments。

arguments.callee

this引用的是函数据以执行的环境对象——或者也可以说是this值。在调用函数之前,this的值并不确定,因此this可能会在代码执行过程中引用不同的对象。

call() apply()能够扩充函数赖以运行的作用域。(P117)
### 箭头函数与普通函数 `this` 绑定的区别 #### 普通函数的 `this` 行为 在 JavaScript 中,普通函数的 `this` 值取决于其 **调用方式**。具体而言: - 当普通函数作为一个对象的方法被调用时,`this` 指向该对象[^1]。 - 如果普通函数是以独立形式调用(即未通过任何对象调用),在非严格模式下,`this` 默认指向全局对象(如浏览器中的 `window` 对象)。而在严格模式下,此时的 `this` 将是 `undefined`[^2]。 此外,当使用诸如 `.call()`, `.apply()` 或者 `.bind()` 方法显式指定调用上下文时,可以更改普通函数内部的 `this` 值[^2]。 #### 箭头函数的 `this` 特性 相比之下,箭头函数并不具备自己的 `this` 上下文绑定机制。它的 `this` 是在其定义时由外层词法作用域决定并固定下来的,而非基于实际调用的方式动态调整[^3]。这意味着即使尝试利用 `.call()`, `.apply()` 或 `.bind()` 来修改箭头函数内的 `this`,这些操作也不会生效,因为箭头函数本身不支持重新绑定 `this`[^2]。 例如,在全局环境中声明的一个箭头函数,其中的 `this` 很可能就代表的是全局对象;而如果是在某个特定的对象方法里创建了一个箭头函数,则这个箭头函数里的 `this` 会继续沿用那个对象作为其上下文。 这种设计使得箭头函数非常适合用于那些希望保持当前执行上下文中 `this` 不变的情况,比如事件处理程序或者定时器回调等场景中经常遇到的问题——避免因意外改变了预期的 `this` 导致错误行为发生。 ```javascript // 示例代码展示两者差异 const obj = { name: 'Object', regularFunction: function () { console.log(this.name); }, // 使用常规函数表达式 arrowFunction: () => { console.log(this.name); } // 使用箭头函数表达式 }; obj.regularFunction(); // 输出 "Object" obj.arrowFunction(); // 可能输出 undefined (视环境而定) function testFunc() { const innerArrow = () => this; return innerArrow(); } console.log(testFunc.call({ key: 'value' }) === window ? 'Global Context' : 'Other'); // 结果依赖于运行环境 ``` 以上示例清晰表明了两种类型的函数对于 `this` 处理上的根本差别。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值