Javascript中箭头函数与普通的函数的区别。
箭头函数(arrow functions),是一个来自ECMAScript 2015(又称ES6)的全新特性。箭头函数有时候也叫“lambda表达式”。箭头函数表达式的语法比函数表达式更简洁,并且没有自己的this,arguments,super或new.target。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。
以上是箭头函数的官方解释,简单说箭头函数就是匿名函数,为了简化了函数定义。
//普通函数
function fun(){
console.log('我是普通函数...');
}
//箭头函数
let arrFun = ()=>console.log('我是箭头函数...');
fun();
arrFun();
运行结果:
我是普通函数...
我是箭头函数...
箭头函数有两种格式,一种只包含一个表达式,连{ ... }和return都省略掉了。还有一种可以包含多条语句,这时候就不能省略{ ... }和return。
//只包含一个表达式的箭头函数
let fun = ()=>console.log('我是箭头函数...');
//包含{ ... }和return的箭头函数
let add = (x,y)=>{
let z = x+y;
return{
result: z
}
}
fun();
console.log(add(5,7));
运行结果:
我是箭头函数...
{ result: 12 }
箭头函数与普通函数的最大区别,体现在以下三点:
下来咱们分别探讨。
1)箭头函数不能作为构造函数使用;普通函数可以作为构造函数使用。
function Fun(){
console.log('Fun()...');
}
let ArrowFun = ()=>{
console.log('ArrowFun()...');
}
let f = new Fun();
//TypeError: ArrowFun is not a constructor
let fn = new ArrowFun(); //错误
2)箭头的this指向永远不变,普通函数中的this代表调用当前方法的对象。
<script>
var name = 'window'
function fun(){
console.log('in Fun=>'+this.name);
}
let arrowFun = ()=>{
console.log('in ArrowFun=>'+this.name);
}
fun();
arrowFun();
</script>
运行结果:
in Fun=>window
in ArrowFun=>window
因为此时name是绑定在window对象上,而调用者两个方法默认都是window对象,所以无论是箭头函数还是普通函数的this都是指向window。
改写如下:
<script>
var name = 'window'
function fun(){
console.log('in Fun=>'+this.name);
}
let arrowFun = ()=>{
console.log('in ArrowFun=>'+this.name);
}
let person = {
name: 'zhangsan',
fun: fun,
arrowFun: arrowFun
}
person.fun();
person.arrowFun();
</script>
运行结果:
in Fun=>zhangsan
in ArrowFun=>window
此时fun()里的this指向调用当前方法的那个对象,当然是person对象,所以fun()里的this指向person对象。而箭头函数里的this永远指向window对象。
有小伙伴会问:如果把arrowFun定义到person对象里面,情况会变化吗?答案是否定的。
<script>
var name = 'window'
function fun(){
console.log('in Fun=>'+this.name);
}
let person = {
name: 'zhangsan',
fun: fun,
arrowFun: ()=>{
console.log('in ArrowFun=>'+this.name);
}
}
person.fun();
person.arrowFun();
</script>
运行结果:
in Fun=>zhangsan
in ArrowFun=>window
这里一定要理解,箭头函数里的this永远绑定自己的上一层作用域对象的this,但是对象不构成作用域。我们把程序改写如下:
<script>
var name = 'window'
function fun() {
console.log('in Fun=>' + this.name);
}
let person = {
name: 'zhangsan',
fun: fun,
myFn: function () {
let arrowFun = () => {
console.log('in ArrowFun=>' + this.name);
}
arrowFun();
}
}
person.fun();
person.myFn();
</script>
运行结果:
in Fun=>zhangsan
in ArrowFun=>zhangsan
此时,箭头函数在一个普通函数内部,所以this指向会指向person对象。
但是如果咱们把myFn属性改为对象属性,因为对象不构成作用域,则箭头函数的this指向还是指向window对象。
<script>
var name = 'window'
function fun() {
console.log('in Fun=>' + this.name);
}
let person = {
name: 'zhangsan',
fun: fun,
myFn: {
arrowFun: () => {
console.log('in ArrowFun=>' + this.name);
}
}
}
person.fun();
person.myFn.arrowFun();
</script>
运行结果:
in Fun=>zhangsan
in ArrowFun=>window
需要注意的是,如果箭头函数在另一个箭头函数里面,那么作用域还是不会改变。
<script>
var name = 'window'
function fun() {
console.log('in Fun=>' + this.name);
}
let person = {
name: 'zhangsan',
fun: fun,
myFn: () => {
let arrowFun = () => {
console.log('in ArrowFun=>' + this.name);
}
arrowFun();
}
}
person.fun();
person.myFn();
</script>
运行结果:
in Fun=>zhangsan
in ArrowFun=>window
即便使用call(),apply(),bind()也无法改变箭头函数中this的指向。
<script>
var name = 'window'
function fun() {
console.log('in Fun=>' + this.name);
}
let lisi = {
name: 'lisi'
}
let person = {
name: 'zhangsan',
fun: fun,
myFn: function () {
let arrowFun = () => {
console.log('in ArrowFun=>' + this.name);
}
arrowFun.call(lisi);
}
}
person.fun.call(lisi);
person.myFn();
</script>
运行结果:
in Fun=>lisi
in ArrowFun=>zhangsan
小结:箭头函数里的this永远绑定自己的上一层作用域对象的this,但是有两种情况除外:1.对象不构成新的作用域。2.箭头函数在另一个箭头函数里面。
3)箭头函数没有自己的arguments
<script>
let add = ()=>{
console.log(arguments)
}
add(1,2,3)
</script>
运行结果:
Uncaught ReferenceError: arguments is not defined
普通函数有自己的arguments
<script>
function add(){
console.log(arguments);
}
add(1,2,3)
</script>
运行结果:
Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
但是箭头函数可以使用展开语法获取参数。
<script>
let add = (...args)=>{
console.log(args)
}
add(1,2,3)
</script>
运行结果:
(3) [1, 2, 3]
箭头函数与普通函数的最大区别,体现在以下三点:
注意:箭头函数在对象里面,或者箭头函数在另一个箭头函数里面都不构成新的作用域。