前言
虽然一直在关注前端的发展,也偶尔会上手练习一下,但更多的是为了了解一些框架和一些编程思想,其实很少自己动手写,尤其是近几年前后端分离盛行,更是基本上没有再写过。最近兴趣上来了,就想在学习一些,记录一下学习时候遇到的知识点。
匿名函数
和箭头函数
一直傻傻的分不清,一度以为是同一个东西的不同写法,慢慢的却也发现两者有不同,之前一直没有关注,学的时候都是看是不是报错,报错了就换一个方式,从来没有关注过到底有啥区别,这次心血来潮想把他搞清楚,并记录下来。
匿名函数
我不擅长记忆,尤其是各种概念,更喜欢把他们简单化,抽象成一个东西,然后去记一些抽象和个体的区别。之所以在这里说这个,是因为我一直说把匿名函数和函数都完全当函数来理解的。
在我的眼里,匿名函数就是一个很普通的函数,普通到他都没有名字,或者你都可以不关注他的名字。好像在javascript里谁也没有规定函数必须有名字(我也不确定有没有这个规定,但是有匿名函数出现,应该是没有这个规定的吧)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 普通函数
function sum(a,b){
console.log(a+b);
}
// 普通函数调用
sum(1,2);
// 匿名函数
function (a,b){
console.log(a+b);
}
// 匿名函数调用
(function (a,b){
console.log(a+b);
})(1,2);
上面就是一个普通的函数
和一个匿名函数
的定义及调用,普通函数没啥好说的,我一直觉得定义一个就是为了复用代码,普通函数很好的解决了复用问题,定义一次,可以多次调用。但是对于匿名函数,这方面就解释不通了,从上面的调用方式就会发现,这没法复用呀,有人说复制一些换个参数不就行了,那是复制,复制不等于复用。
1
2
3
4
5
6
// 匿名函数
var fun = function (a,b){
console.log(a+b);
}
// 匿名函数调用
fun(1,2);
上面这段代码还是定义一个匿名函数
,为啥这样说呢,因为我们的fun并不是放在函数名位置,而是变量名。我们其实是把一个匿名函数赋给了一个变量,然后通过这个变量去调用这个匿名函数,看上去也解决了复用问题。
1
2
3
4
5
setInterval(function(){
console.log("回调函数")
},1000)
这个匿名函数的用法应该说完全不是为了复用,而只是利用javascript的特点,把一个匿名函数作为一个实参传递进入一个函数里,用完就完了,连个名字都不需要。因为他的作用就是用于回调,所有成为回调函数
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function outFun() {
let outVar = '我是outVar!';
return function() {
console.log(outVar);
}
}
const fun = outFun();
// 输出: 我是outVar!
fun();
上面这个就是闭包
,其实闭包就是一个函数的返回值是一个函数,这里就有一个有趣的现象:函数调用完后本应该是把销毁内部的局部变量的,但是上面这个函数调用完后,会发现他返回的函数中用到了这个局部变量,所有这个局部变量就不能被销毁,通过这个现象我们可以实现跨作用域。这就是闭包
。
箭头函数
箭头函数
和匿名函数或者说普通函数可是有很大不同的,他们是有本质区别的。虽然他们也是看上去很像。这也是我记录他的原因。
1
2
3
4
5
let add = (a, b) => {
return a + b;
};
console.log(add(4, 6)); // 输出:10
上面这个函数就是一个箭头函数
,之所以叫箭头函数是因为函数定义的时候使用了=>
,看上去没啥区别呀,没有名字,只是多了个箭头,这就是我开始的想法,以为就是一个不同的写法(这也是因为我不太喜欢语法糖和简写的原因)。直到后来发现偶尔会有问题才意识到他俩的区别:
1、作用域问题:在箭头函数里没有自己的this,他的this是指的定义该函数的上下文。一下子把函数作用域的规则颠覆了。所以箭头函数中this的指向在它被定义的时候就已经确定了,之后不再改变。
2、箭头函数没有原型prototype:这个又颠覆了javascript中的规则。
上面这两个颠覆性的改变,直接导致箭头函数的特殊:
1、this指向不同,可以直接跨域作用域使用定义该函数的上下文的作用域。
2、this在定义的时候就确定了,之后不能改变,那么call()、apply()、bind()无法改变箭头函数中this的指向。
3、构造函数是构造自己,他没有自己的this,自然也不能作为构造函数。
4、没有原型prototype,那和prototype相关的都没来,比如不能作为构造函数,因为它本身不能构造自己的作用域,而且构造函数是在原型中指定的。
5、箭头函数没有自己的arguments
6、箭头函数不能用作Generator函数,不能使用yeild关键字
总结
箭头函数和函数有很大的区别,主要是作用域和没有原型,而不是只是没有名字的问题,这个和函数是有很大区别的。
以上是我对匿名函数和箭头函数的一些简单理解,不一定正确,如有问题还请大家指正。