定义函数
- 具名函数
function 函数名(形式参数1,形式参数2){
语句
return 返回值
}
- 匿名函数
let a = function(x,y){return x+y}
- 箭头函数
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 构造出来的 包括 Object、Array、Function 也是
函数自身和调用
例如
let fn = () => console.log('hi')
fn//没有反应
fn()//打印出Hi,有圆括号才是调用
再进一步
let fn = () => console.log('hi')
let fn2 = fn
fn2()
- fn 保存了匿名函数的地址;
- 这个地址被赋值给了fn2;
- fn()调用了匿名函数;
- fn 和 fn2 都是匿名函数的引用而已
- 真正的函数既不是fn也不是fn2
函数的要素
调用时机
let a = 1
function fn(){
console.log(a)
}
打印出:不知,因为没有调用代码
let a = 1
function fn(){
console.log(a)
]
fn()
打印出1
let a = 1
function fn(){
console.log(a)
]
a = 2
fn()
打印出2
let a = 1
function fn(){
console.log(a)
]
fn()
a = 2
打印出1
执行时机
let i = 0
for(i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
打印出6个6
原因在于 setTimeout(),意思是此函数延迟执行,所以当系统执行console.log(i)时,for循环已经停止循环,i此时已经等于6,由于进行了6次循环,所以返回了6个6值。
for(let i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
这段代码打印出0,1,2,3,4,5,6
作用域
全局变量与局部变量
- 在顶级作用域声明的变量是全局变量
- window 的属性是全局变量
- 其他都是局部变量
函数可嵌套
fuction f1(){
let a = 1
fution f2(){
let a = 2
console.log(a)
}
console.log(a)
a = 100
f2()
}
f1() // 1,2
作用域规则:如果多个作用域有同名变量a时
- 查找a声明时,向上取最近作用域,简称“就近原则”
- 查找a的过程与函数执行无关
- 但a的值与函数执行有关
闭包
如果一个函数用到了外部的变量,那么这个函数加这个变量,就叫做闭包
形式参数
形式参与的意思就是非实际参与
function add(x,y){
return x+y
}
x和y就是形式参数
当调用函数时,如add(1,2),1和2就是实际参数被赋值给x、y
等同于
function add(){
var x = arrguments[0]
var y = arrguments[1]
return x+y
}
返回值
每个函数都有返回值(return),且只有函数才有返回值,函数执行完了后才会返回
调用栈
JS 引擎在调用一个函数前,需要把函数所在的环境 push 到一个数组里,这个数组叫做调用栈。等函数执行完了,就会把环境弹(pop)出来,然后 return 到之前的环境,继续执行后续代码。
- 调用栈最长数值: Chrome 12578;Firefox 26773;Node 12536
函数提升
function fn(){}无论具名函数声明在哪里,它都会跑到第一行let fn = function(){}这是赋值,右边的匿名函数声明不会提升
arguments和this
- 除了箭头函数,每个函数都有arguments和this
- 调用 fn 即可传 arguments
- fn(1,2,3) 那么 arguments 就是 [1,2,3] 伪数组
- 目前可以用 fn.call(xxx, 1,2,3) 传 this 和 arguments,而且 xxx 会被自动转化成对象
- this 是隐藏参数,arguments 是普通参数
- 用this获取对象的引用
fn(1,2) // 等价于 fn.call(undefined, 1, 2)
obj.child.fn(1) // 等价于 obj.child.fn.call(obj.child, 1)
箭头函数
console.log(this) // window
let fn = () => console.log(this)
fn() // window
fn.call({name:'frank'}) // window
this 就 this,就是个指定名称
立即执行函数
-
用途:得到局部变量
-
方法:在匿名函数前面加个运算符!、~、()、+、-即可,推荐加!