【转】js 箭头函数详解

原文:https://blog.csdn.net/weixin_45112114/article/details/123358639

1. 认识箭头函数

es6 新增了使用胖箭头(=>)语法定义函数表达式的能力,很大程度上,箭头函数实例化的函数对象与正式的函数表达式创建的函数对象行为是相同的。任何可以使用函数表达式的地方,都可以使用箭头函数:

// 普通函数
let sum = function(a, b) {
	return a + b;
}

// 箭头函数
let sum1 = (a, b) => {
	return a + b;
}

箭头函数简洁的语法对开发者来说是十分友好的,从上面的例子可以得知箭头函数的简单用法:
(参数) => { 函数体 }

2. 箭头函数的一些用法

2.1. 省略包含参数的小括号

如果只有一个参数,那也可以不用括号。只有没有参数,或者多个参数的情况下,才需要使用括号:

// 有效
let sum = (x) => {
	return x;
};
// 有效
let sum1 = x => {
	return x;
};
// 没有参数需要括号
let sum2 = () => {
	return 1;
};
// 有多个参数需要括号
let sum3 = (a, b) => {
	return a + b;
};

2.2. 省略包含函数体的大括号

箭头函数也可以不用大括号,但这样会改变函数的行为。使用大括号就说明包含“函数体”,可以在一个函数中包含多条语句,跟常规的函数一样。

  • 省略大括号箭头后面就只能有一行代码;
  • 省略大括号会隐式返回这行代码的值;
  • 省略大括号不能写return。
// 有效
let sum = (a, b) => {
	return a + b;
};
// 有效
let sum1 = (a, b) => a + b; // 相当于 return a + b;
// 无效的写法
let sum2 = (a, b) => return a + b;

2.3. 嵌入函数

箭头函数简洁的语法非常适合嵌入函数的场景:

let arr = [1, 2, 3, 4, 5];
arr.map(val => val * 2); // [2, 4, 6, 8, 10]

3. 箭头函数不能使用arguments

如果函数是使用箭头语法定义的,那么传给函数的参数将不能使用 arguments 关键字访问:

// 普通函数
let sum = function() {
	return arguments.length;
}
sum(1, 2, 3); // 3

// 箭头函数
let sum1 = () => {
	return arguments.length;
}

sum1(1, 2); // Uncaught ReferenceError: arguments is not defined

虽然箭头函数中没有 arguments 对象,但可以在包装函数中把它提供给箭头函数:

function foo() {
	let bar = () => {
		console.log(arguments.length);
	}
	bar(); 
}
foo(5, 5, 5);  // 3

4. 箭头函数中this 指向

let num = 11;
const obj1 = {
	num: 22,
	fn1: function() {
		let num = 33;
		const obj2 = {
			num: 44,
			fn2: () => {
				console.log(this.num);
			}
		}
		obj2.fn2();
	}
}
obj1.fn1(); // 22

fn2中得到的结果为:22

原因箭头函数没有this,箭头函数的this是继承父执行上下文里面的this ,这里箭头函数的执行上下文是函数fn1(),所以它就继承了fn1()的this,obj1调用的fn1,所以fn1的this指向obj1, 所以obj1.num 为 22。
注意:简单对象(非函数)是没有执行上下文的!

如果fn1也是个箭头函数呢?

let num = 11; // 
const obj1 = {
	num: 22,
	fn1: () => {
		let num = 33;
		const obj2 = {
			num: 44,
			fn2: () => {
				console.log(this.num);
			}
		}
		obj2.fn2();
	}
}
obj1.fn1();

上述结果为undefined,因为fn1也是一个箭头函数,所以它就只能继续向上找也就是window了。

那为什么是undefined而不是11呢?

这里涉及到var和let声明变量的一个区别:使用 let 在全局作用域中声明的变量不会成为 window 对象的属性,var 声明的变量则会(不过,let 声明仍然是在全局作用域中发生的,相应变量会在页面的生命周期内存续,所以使用window访问会为undefined):

var a = 1;
window.a; // 1

let b = 1;
window.b; // undefined

将let改成var后:

var num = 11; // 
const obj1 = {
	num: 22,
	fn1: () => {
		let num = 33;
		const obj2 = {
			num: 44,
			fn2: () => {
				console.log(this.num);
			}
		}
		obj2.fn2();
	}
}
obj1.fn1();

此时结果为window.num => 11

posted @ 2022-09-17 17:44  tc310  阅读(78)  评论(0编辑  收藏  举报