函数声明与函数表达式

突然发现,虽然天天都写,但是这里头还有不少东西很模糊,放一下自己的探索过程。

创建普通函数的方式

此次只讨论该两种形式:

  • 函数声明
    function add(a, b) {
        return a + b;
    }
    
  • 函数表达式
    const add = (a, b) => a + b;
    

接下来对比一下两者之间差异,也许很多地方看起来都很针对函数声明。

函数提升

使用函数声明方式创建的函数,可以在其有效作用域的任何位置进行使用,包括函数声明之前使用也是可以的,这便是函数提升。

// OK
console.log(add(10, 20)); // 30

function add(a, b) {
  return a + b;
}

而函数表达式并不存在这个规则,其遵从变量声明规则:

// Err
console.log(add(10, 20));

const add = (a, b) => a + b;

那能不能用 var 进行声明,让其提升呢?不行,var 声明的变量只是变量本身提升了,值是不会跟上的,只能说你可以找到变量,但是在达到声明语句之前,都只是 undefined

重复声明

对于函数声明来说,是可以存在重复声明的,当存在重复声明时,最终落实的是最后一个函数:

console.log(add(10, 20)); // 0

// 被后者覆盖
function add(a, b) {
  return a + b;
}
// 该函数生效
function add(a, b) {
  return 0;
}

好,这个了解到了,那么再扩展一下:

如果在其中插入一个同名变量会怎么样,请问谁会覆盖谁?(分别给出 varconst 两者的执行结果)

先回答 const 的表现:但凡使用 const 导致重复声明(包括与函数名称冲突),统一异常停止。

至于 var,那就很有意思了,首先是,可以共存

console.log(add); // [Function: add]
console.log(add(10, 20)); // 0

var add = "add";

console.log(add); // "add"

function add(a, b) {
  return a + b;
}

function add(a, b) {
  return 0;
}

console.log(add); // "add"

可以看出,在达到变量声明之前,add 这个名称都归第二个函数所有,而变量完成声明之后,就成了字符串 "add"

至于为什么执行经过了函数声明却没有任何变化,因为函数声明语句在一开始就已经执行好了。

那么函数表达式呢,其表现已经在扩展题当中提到了:

console.log(add); // undefined

var add = (a, b) => a + b;

console.log(add(10, 20)); // 30

var add = () => 0;

console.log(add(10, 20)); // 0

当然,该表现只要知道 var 的行为逻辑就很容易理解。而对于函数表达式来说,通常都是 const 声明,所以通常不会存在重复声明问题,该问题也是需要自己避免的。

选择

这么看下来,你就是想捧函数表达式吧?

至少我个人更习惯如此,并不需要函数提升,先有声明再使用也符合正常。

函数表达式并不存在 this 问题,没用规定说函数表达式都是箭头函数形式是吧,而使用箭头函数恰恰是用来解决 this 绑定问题的。

函数声明 & 函数表达式

我在想反例时,发现好像有一种奇怪的存在,那就是非箭头函数形式的函数表达式:

const add = function (a, b) {
  return a + b;
}

因为我突然想起来,这个函数好像可以取一个名字,只是说多数情况下,不会特意给其一个名称,因为没什么意思。

但现在回头看,真的会没用吗,就想试试水,因为记得一规范指南当中提到,这是最推荐的写法(虽然我一直都没有照做)。

在这里插入图片描述

const fn = function add(a, b) {
  console.log(a, b);
};

console.log(fn); // [Function: add]
console.log(add); // ReferenceError: add is not defined

啊,这种写法导致函数声明不起效果,根本找不到 add。不过慢着,这个函数叫什么来着,居然是 [Function: add]?于是尝试在 add() 函数体内找 add,居然真的可以:

const fn = function add(a, b) {
  console.log(add); // [Function: add]
  return a + b;
};

console.log(fn(1, 2)); // 3

哇,看似好像发现了一个什么了不得的东西,但是别急,在这个场景下是没用的。若是真的想递归调用,可以选择直接找 fn(),而不需要在内部找。

当然,也可以这么玩:

(function dfs(n) {
  if (n === 0) {
    return;
  }
  dfs(n - 1);
  console.log(n);
})(5);
// 1
// 2
// 3
// 4
// 5

-END-

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值