函数
大约 3 分钟约 914 字...
定义
function fun() {
// 函数体语句
}
// 函数表达式
var fun = function () {
// 函数体语句
}
函数声明的提升
和变量声明提升类似,函数声明也可以被提升
如果函数是用函数表达式的写法定义的,则没有提升特性
fun() //引发错误
var fun = function () {
console.log(1)
}
而且函数是优先变量进行提升的:
fun() //2
function fun() {
console.log(2)
}
// 变量声明提升,无法覆盖提升的函数
var fun = function () {
console.log(1)
}
fun() //1
JS 的预解析机制
全局作用域,函数(局部)作用域,都是通过以下两个步骤进行预解析的。
先读取有 var 的变量(没有使用 var 的变量是不会被预解析的),给赋值为:
undefined
。如果两个变量重名,并不影响预解析的过程,就写一个变量就行,因为都将变量赋值为 undefined(在逐行读取时,只是不同的赋值而已。),如果有函数名和变量重名,那就直接去掉变量,不进行解析。如果函数中存在参数,那么参数也一样使用 var 进行解析。如:var argument=undefined;再读取 function 后面的函数---fn,如果有多个函数名重复,那么取最后面一个函数进行声明。
console.log(a) // 打印函数a函数体(function a() { console.log('a') })
var a = 10
console.log(a) // 10
function a() {
console.log('a')
}
console.log(a) // 10
预解析过程
- 首先预解析到有
变量 a
存在,因此记录下a
这个名字,和其值undefined
- 接着预解析到有
函数 a
声明,记录下函数名 a
- 但是发现已经记录了一个
a
,因此第 1 步操作无效,(如果有函数名和变量重名,那就直接去掉变量,不进行解析)将函数体与 a 这个名字相关联 - 解析完毕
结果:a = function () { console.log('a') }
执行过程
- 打印变量 a 的值
function a() { console.log('a') }
- 变量 a 赋值为 10,将原来关联的函数覆盖
- 打印变量 a 的值 10
- 打印变量 a 的值 10
- 执行完毕
函数的参数
函数的参数是局部变量
arguments
所有属性均为从 0
开始的自然数序列,并且有 length
属性,和数组类似可以用方括号书写下标访问对象的某个属性值,但是不能调用数组的方法
函数内 arguments
表示它接收到的实参列表,它是一个类数组对象
function fun(a, b) {
console.log(arguments)
console.log('arguments长度' + arguments.length)
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i])
}
}
fun(1, 2)
闭包
作用域应用的特殊情况,有两种情况:
- 函数作为参数被传递
function print(fn) {
let a = 200
fn()
}
let a = 100
function fn() {
console.log(a)
}
print(fn)
- 函数作为返回值被返回
function create() {
let a = 100
return function () {
console.log(a)
}
}
let fn = create()
let a = 200
fn()
立即执行函数 IIFE
IIFE( Immediately Invoked Function Expression,立即调用函数表达式)是一种特殊的 JavaScript 函数写法,一旦被定义,就立即被调用。
IIFE 会通过声明并立即执行一个函数来创建作用域------你不知道的 js(上)
;(function () {
console.log(1)
})()
IIFE 可以在一些场合(如 for 循环中)将全局变量变为局部变量:
var arr = []
for (var i = 0; i < 5; i++) {
arr.push(function () {
alert(i) // 变量i是全局变量,所有函数都共享内存中的同一个变量i
})
}
arr[2]() // 5
使用 IIFE 解决:
var arr = []
for (var i = 0; i < 5; i++) {
;(function (i) {
arr.push(function () {
alert(i)
})
})(i)
}
arr[2]() // 2