JavaScript 函数

45 阅读2分钟

函数的定义

具名函数

function 函数名(形式参数1,形式参数2){
    语句
    return 返回值
}

匿名函数

  • 去掉函数名的具名函数就是匿名函数
let a = function(x,y){return x+y}
  • 函数表达式

注意:如果有等于号的,只能作用于右边,也就是如果要使用函数,只能用a。相反地,如果是function直接定义,那就全局可用。

箭头函数

let f1 = x => x*x
let f2 = (x,y) => x+y //圆括号不能省略
let f3 = (x,y) => {return x+y }//花括号不能省
let f4 = (x,y) => ({name:x , age:y })

直接返回对象会出错,需要加括号,不然就变成标签了。

构造函数

let f = new Function('x','y','return x+y')
  • 基本没人使用,但是可以让你知道函数是谁构造的。
  • 所有函数都是Function构造(including Object、Array 、Function)

函数的要素

  • 调用时机
  • 作用域
  • 闭包
  • 形式参数
  • 返回值
  • 调用栈
  • 函数提升
  • arguments(除了箭头函数)
  • this(除了箭头函数)

JS函数的执行时机

//为什么如下代码会打印 6 个 6
let i = 0
for(i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}

JS 函数的执行时机与其在代码中的位置有关,常见的执行时机包括函数声明、函数表达式、立即执行函数、事件回调等。

在上述代码中,由于使用了 setTimeout 函数,导致回调函数中的 console.log(i) 不会立即执行,而是会被放入一个任务队列中,等待主线程空闲后才会被执行。而在 for 循环执行过程中,变量 i 的值一直在不断地被更新,因此在回调函数被执行时,i 的值已经被更新为 6,导致打印出 6 个 6。

为了让上述代码打印 0、1、2、3、4、5,可以使用闭包的方式来保存当前的 i 值,代码如下:

for(let i = 0; i < 6; i++){ 
    (function(i){ 
        setTimeout(() => { console.log(i) }, 0)
        })(i) 
       }

还有个更简洁的办法,就是直接在for里面let i = 0就行。

除了使用 for(let i = 0; i < 6; i++) 的方式,还有一种可以使用 Array.fromArray.prototype.map 方法来实现,代码如下:

jsCopy code
// 打印 0、1、2、3、4、5
Array.from({length: 6}).map((_, i) => {
  setTimeout(() => {
    console.log(i)
  }, 0)
})

这种方法使用了 Array.from 方法创建一个包含 6 个 undefined 元素的数组,然后使用 Array.prototype.map 方法来对数组进行遍历,对于每个元素使用一个回调函数来设置对应的定时器。由于使用了箭头函数,因此可以访问到外部的 i 变量,从而保证每个回调函数中的 i 值都是独立的。