JavaScript中你不知道的函数

时间:2021-1-8 作者:admin

本文档已更新于 【前端橘子君】 【Github】

函数声明

在JavaScript中,对于函数的声明有两种表达形式,声明式表达式,至于其他函数(如立即执行函数,箭头函数等)都是基于这两种形式衍生的。

// 声明式
function foo () {
  console.log('我是声明式')
}

// 表达式
var foo = function () {
  console.log('我是表达式')
}

具名函数

故名思意,具名函数就是有名称的函数,这是我们最常见的一种函数,我们先来看看它的写法。

// 具名函数
function foo () {
  console.log('我是具名函数')
}

上边说了,函数声明的表达形式有两种,具名函数是经典的声明式,具名函数表达式的另外一种表现形式引出了另外一种函数类型-具名函数表达式(NFE)

具名函数表达式

具名函数表达式就是具名函数的表达式写法,严格来说,它并不是一种函数类型,只是一种写法而已。

// 具名函数表达式
var fn = function foo () {
  console.log('我是具名函数表达式');
}
fn() // 输出:我是具名函数表达式

它有几个特点:

  • 函数名标识符私有化
  • 函数名标识符常量化

函数名标识符私有化:即具名函数表达式的函数名不能从外部调用,仅供函数体内部使用,当外部调用时就会报错。

// 函数名称私有化
var fn = function foo () {
  console.log(typeof foo);
}
fn() // function
foo() // Uncaught ReferenceError: foo is not defined

函数名标识符常量化:即具名函数表达式标识符的值不能修改,我们可以将其当作常量来使用。

var fn = function foo(){
    foo = 12;
    console.log(foo);
}

fn()
/*
输出:
ƒ foo(){
    foo = 12;
    console.log(foo);
}
*/

我们来看一道经典的面试题

// 改写以下代码,使其分别输出10、12
var foo = 10;
(function foo    (){
    foo = 12;
    console.log(foo);
})()

// 改写结果
var foo = 10;
(function foo    (){
    var foo = 12;
  console.log(window.foo); // 10
  console.log(foo); // 12
})()

匿名函数

匿名函数:即没有名称的函数,匿名函数不能像具名函数一样直接声明定义,在JavaScript中常见的用法就是将匿名函数当作回调参数使用或作为高阶函数的返回值。

// 作为回调参数
setTimeout(function () {
  console.log('我是匿名函数');
}, 1000);

// 作为高阶函数的返回值
function foo () {
  var num = 10;
  return function (i) {
    return num + i;
  }
}

foo()(5) // 输出:15

匿名函数有几个缺点我们需要注意一下:

  • 没有函数名,调试困难
  • 如需引用自身(如递归函数),需要用arguments.callee,但是arguments.callee在严格模式下禁用
  • 可读性差

立即执行函数

立即执行函数(IIFE):即当程序解析到该函数时就立即执行。

// 写法一
(function () {
  console.log('我是立即执行函数');
})()

// 写法二
(function () {
  console.log('我是立即执行函数');
}())

匿名函数的优点在于内部参数不会泄露,即变量私有化。

(function () {
  var x = 10
  console.log('我是立即执行函数');
}())

console.log(x); // Uncaught ReferenceError: x is not defined

有一道很经典的面试题,我们可以看一下。

// 改写以下代码,让其依次输出.
for (var i = 0; i < 5; i++) {
    setTimeout(function () {
        console.log(`值为${i}`)
    }, 0)
}
// 此时会输出5次 "值为5"

我们会立马想到用let,但是还有没有其他写法呢?当然有,立即执行函数就是了。

// 改写方法一
for (var i = 0; i < 5; i++) {
  (function(num){
    console.log(`值为${num}`)
  })(i)
}

// 改写方法二
for (var i = 0; i < 5; i++) {
  var num = (function(){
    return i;
  })()
  console.log(`值为${num}`)
}

更多相关文档,请见:

线上地址 【前端橘子君】

GitHub仓库【前端橘子君】

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。