函数的要素
每个函数都有这些东西
- 调用时机
- 作用域
- 闭包
- 形式参数
- 返回值
- 调用栈
- 函数提升
- arguments(除了箭头函数)
- this(除了箭头函数)
一、调用时机
调用函数的时机就像是刻舟求剑,时机很重要。
看到函数先直接跳过,一定要看到调用语句才会执行函数。
例1
- 以下代码打印出什么?
let a = 1
function fn(){
console.log(a)
}
a = 2
fn()
- 答:2,先
a=2
,再调用fn
例2
- 以下代码打印出什么?
let a = 1
function fn(){
setTimeout(()=>{
console.log(a)
},0)//setTimeout是等一会执行里面的箭头函数
}
fn()
a = 2
- 答案:2
setTimeout
是等一会执行- 比喻:一个人在打游戏,妈妈喊他吃饭,他说等一下去吃饭,意思是吃饭之前要把游戏打完。
- 因此:这里
setTimeout
中的0
表示执行完了马上做等一会做的事情
例3
- 以下代码打印出什么?
let i = 0
for(i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
- 答案:6个6
- 等一会执行,则是要
for
循环结束后马上执行,一共执行了6次,当for
循环结束后i=6
,因为只有一个i
,所以是6个6
例4
- 以下代码打印出什么?
for(let i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
- 答: 0,1,2,3,4,5
- 因为JS在
for
和let
一起用的时候会加东西(满足有些新手程序员的想象) - 每次循环就会复制一个
i
,i=0、i=1....
,6次循环一共生成除了6个新的i
setTimeout
会打印出当时的值
作用域
每个函数都会默认创建一个作用域
作用域的重点就是:就近原则
例5
function fn(){
let a = 1
}
fn()
console.log(a)//a不存在
- a不存在
fn
执行了,也访问不到作用域里面的a
,因为a
的作用域就在{}
里let
的作用域:往前找到一个{
,往后找到一个}
,出了{}
就不存在
1.全局变量 V.S. 局部变量
- 在顶级作用域里声明的变量是全局变量
window
的属性是全局变量 (如果是在window
上面,则不需要写在顶级作用域,可以写在任何地方)- 其他都是局部变量
let b= 1
function f2(){
window.c = 2//只要是添加在window上,放哪都可以
}
f2()
function f1(){
console.log(c)
}
f1()
2.函数可嵌套
作用域也可嵌套,局部作用于套局部作用域
2.1作用域规则
如果多个作用域有同名变量a
- 那么查找
a
声明时,就向上取最近的作用域 - 简称[就近原则]
- 查找
a
的过程与函数执行无关
和函数执行无关的作用域叫做静态作用域,也叫做词法作用域(了解即可) - 但a的值和函数执行有关
在确定a
的值时,才需要注意执行函数和a
的先后顺序
例5 - 找出f3中a是什么?
- 答:a是作用域2里的a
闭包
JS的函数会就近寻找最近的变量
1.定义
如果一个函数用到了外部的变量,那么这个函数加这个变量叫做闭包
下例中,a
和f3
组成了闭包
形式参数
1.形式参数的意思就是非实际参数
function add(x,y){
return x+y
}
add(1,2)
- 其中
x
和y
就是形式参数(xy并不代表任何实际的值,只代表参数的顺序和位置),因为并不是实际的参数 - 调用
add
时,1
和2
是实际参数,会被赋值给x y
- 赋值:
1.传统说法 JS传参分为 值传递 和 地址传递
2.新的理解:不需要区分值和地址,所有都是根据内存图全部复制,值的复制和地址的复制
3.也就是:根据内存图,Stack记的什么,就是什么
例1.数字
例2.对象
- 形参可以认为是变量声明
上面的代码近似等价于下面的代码
function add(){
var x = arguments[0] //x是参数的第0个,arguments是所有参数
var y = arguments[1]
return x+y
}
2.形参可多可少
形参只是给参数取名字
没必要把形参全部声明完
返回值
1.每个函数都有返回值
返回值是执行之后才使用的
- 没写
return
,返回值是undefined
function hi(){
console.log('hi')
}
hi()
console.log('hi')
的返回值是undefined
注意:只是打印了一个hi
,返回值还是undefined
(区分打印值和返回值)
因此下面hi()
的值是undefined
function hi(){
return console.log('hi')
}
hi()
- 函数执行完了才会返回
- 只有函数有返回值
1+2
的值为3(不是返回值为3)