JS函数

131 阅读3分钟

定义函数

  • 具名函数
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()
  1. fn 保存了匿名函数的地址;
  2. 这个地址被赋值给了fn2;
  3. fn()调用了匿名函数;
  4. fn 和 fn2 都是匿名函数的引用而已
  5. 真正的函数既不是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时

  1. 查找a声明时,向上取最近作用域,简称“就近原则”
  2. 查找a的过程与函数执行无关
  3. 但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,就是个指定名称

立即执行函数

  • 用途:得到局部变量

  • 方法:在匿名函数前面加个运算符!、~、()、+、-即可,推荐加!