定义函数
- 具名函数
function 函数名(形参){
语句
return 返回值
}
函数名(实参)
例子:这种函数调用不能执行函数,因为如果函数写到等于号右边,函数的作用域只作用于等于号右边,在别的位置fn不存在
let a=function fn(x,y){
return x+y
}
fn(1,2)
- 匿名函数
let a=function(x,y){
return x+y
}
- 箭头函数
let fn2=(x,y)=>{
return x*y
}
例子:
// 直接返回会出错,外面需要加一个圆括号
let f=(x)=>({name:x})
// 调用
f('frank')
- 构造函数
let fn1=new Function('x','y','console.log(\'hi\'); return x+y')
// 调用
fn1(1,2)
函数的调用时机
函数什么时候调用,什么时候函数才会执行,不要管函数声明写到哪个位置。
举例:
let a=1;
function fn(){
// 尽快将a打印出来
setTimeout(()=>{
console.log(a)
},0)
}
fn()
a=2
//打印结果2
函数什么时候调用,才能证明这个函数什么时候有效,在哪里声明不影响执行。这也被称之为函数提升。注意,如果是函数赋值给某个变量,这个函数是不会提升的。
for循环配合setTimeout的代码题
情况一:
let i
for(i=0;i<6;i++){
//等for循环忙完,再执行console.log(i)
setTimeout(()=>{
console.log(i)
},0)
}
// 打印的结果是6个6
情况二:
for(let i=0;i<6;i++){
setTimeout(()=>{
console.log(i)
},0)
}
// 打印结果是0、1、2、3、4、5
// 因为JS会在for和let一起用的时候会加东西,每次循环会多创建一个i
作用域
全局变量:顶级作用域声明的变量或者是挂载到window上面的属性,就是全局变量。
局部变量:如果在函数里面或者代码块里面,外面访问不到这个变量,这个变量就是局部变量。
作用域的规则
JS函数会寻找离他最近的作用域的变量,也称为就近原则。
闭包
概念:如果一个函数用到了外部的变量,这个函数加变量就是闭包。
举例:
function fn(){
let a=1;
function fn2(){
console.log(a)
}
fn2()
}
fn()
函数的参数
函数的参数分为形式参数、实际参数,简称为形参和实参。它们可以完成函数的传参的过程。
例如:
function add(x,y){
return x+y;
}
add(1,2)
这就相当于声明了x=1,y=2,且作用域是add函数内。
调用栈
什么是调用栈?
JS引擎在调用一个函数前,需要把函数所在的环境push到一个数组里面,这个数组叫做调用栈。等函数执行完毕,就把环境pop(弹出来),然后return到之前的环境,继续执行后续代码。
什么是爆栈?
如果调用栈中,压入的帧过多,程序就会崩溃。
this
arguments和this是JS中每个函数都要有的,箭头函数除外。arguments是伪数组。
如何传递arguments?
function fn(){
console.log(arguments)
console.log(this)
}
//调用
fn(1,2,3)
// arguments就是[1,2,3]的伪数组
如何传this?
fn.call(xxx,1,2,3)
// xxx就是被JS自动转化为对象,这个对象就是this
举例:
let person={
name:'frank',
sayHi(){
console.log(`我是:${this.name}}`)
}
}
// sayHi函数通过this,引用了person对象的地址,从而方便sayHi获取person对象
// 每个函数都能通过this获取到一个未知对象的地址引用
// 调用person里面的sayHi
person.sayHi() => person.sayHi.call(person)
上面有两种调用函数的方式:
// 省略形式
person.sayHi()
// 完整形式
person.sayHi.call(person)
call是可以指定this指向的对象是谁,比如说:
// 下面我给this手动传1
let person={
name:'frank',
sayHi(){
console.log(`我的名字是:${this.name}`)
}
}
person.sayHi.call({name:1})
//打印结果是:我的名字是1
call只是其中一种调用函数的方式,调用函数的方式由三种,call、apply、bind。call和apply的区别就是,call接收多个参数,apply接收两个参数,第二参数是数组的形式。bind调用和call类似。
function fn1(p1,p2){
console.log(this,p1,p2)
}
// 简略写法
fn1(1,2)
// call,undefined是为了占位,写其他的数也可以
fn1.call(undefined,1,2)
// apply
fn1.apply(undefined,[1,2])
//bind
fn1.bind(undefined,1,2)
箭头函数
箭头函数没有arguments和this,箭头函数的this指向window。
例如:
let a=(x)=>{
console.log(x)
}
立即执行函数
语法:
!function(){}()