函数是一个对象

定义一个函数:

具名函数

  1. function 函数名(形参1,形参2){
  2. 语句
  3. return 返回值
  4. }

匿名函数

  1. let a = function(x,y){return x+y}
  2. //也叫函数表达式

箭头函数

  1. let f1 = x => x*x
  2. let f2 = (x,y) => x+y //圆括号不能省
  3. let f3 = (x,y) => {return x+y} //写了return 花括号不能省
  4. let f4 = (x,y) =>({name: x , age:y}) //返回对象时需要加圆括号

用构造函数

  1. let f = new Function('x','y','return x+y')
  2. //基本没人用,但能让人知道函数是由谁构造的
  3. //所有函数都是Function 构造出来的
  4. //包括Object,Array,Function

函数自身和其调用

  1. //函数自身
  2. let fn =() => console.log('hi')
  3. fn
  4. //结果:不会有任何结果,因为fn没有执行,得到值是函数本身
  5. //函数调用
  6. let fn =()=>console.log('hi')
  7. fn()
  8. //结果:打印出hi,值是函数的返回值undefined
  9. //有圆括号才是调用
  10. //进一步衍生
  11. let fn = ()=> console.log('hi')
  12. let fn2 =fn
  13. fn2()
  14. //结果:打印出hi,值为函数的返回值undefined
  15. /**
  16. 注:
  17. fn保存了匿名函数的地址,这个地址被复制,然后赋值给了fn2
  18. 故fn2()也是调用了那个匿名函数
  19. fn和fn2都是匿名函数的引用而已,真正的函数既不是fn也不是fn2
  20. **/

函数的要素

每个函数都有以下这些东西

  1. 调用时机
  2. 作用域
  3. 闭包
  4. 形式参数
  5. 返回值
  6. 调用栈
  7. 函数提升
  8. arguments(除了箭头函数)

    调用时机

    时机不同,结果不同 ```javascript let a =1 function fn(){ setTimeout(()=>{ console.log(a) },0) } //问:打印出多少 //答:1

let i = 0 for(i=0;i<6;i++){ setTimeout(()=>{ console.log(i) },0) } //问:打印出多少 //答:6 6 6 6 6 6 //理解为执行了六遍console.log(i),但 for 形成的块级作用域内并没有声明变量i, //块级作用域内是{console.log(i)},因此向上一级去找i,而这个时候i早已等于6

for(let j=0; j<6; j++){ setTimeout(()=>{ console.log(j) },0) } //问:打印出多少 //答:0,1,2,3,4,5 //for形成的块级作用域是{let j=0;console.log(j)}……{let j=5;console.log(j)}

  1. <a name="xEamf"></a>
  2. ### 作用域
  3. 离语句最近的{}就是它的作用域(除去window的属性)<br />变量分为:全局变量和局部变量<br />在顶级作用域声明的变量是全局变量,window的属性是全局变量,其他的都是局部变量<br />函数可以嵌套。
  4. <a name="cY2N7"></a>
  5. #### 作用域规则:
  6. 如果多个作用域有同名变量a<br />那么查找a的声明时,就向上取最近的作用域<br />简称“就近原则”<br />查找a的过程与函数执行无关,但a的值与函数执行有关
  7. ```javascript
  8. function f1(){
  9. let a =1
  10. function f2(){
  11. let a =2
  12. function f3(){
  13. console.log(a)
  14. }a=22
  15. f3()
  16. }console.log(a)
  17. a =100
  18. f2()
  19. }
  20. f1()
  21. 问:输出结果是什么
  22. 答: 1 和 22

闭包

概念:如果一个函数用到了其作用域外部的变量,那么这个函数+这个外部变量就叫做闭包
作用:私有化变量
要求:暴露出操作函数
缺点:在IE浏览器里可能会导致内存泄漏

形式参数

形式参数可以理解为变量声明

返回值

只有函数有返回值,在函数执行完后返回

调用栈

调用栈是解释器追踪函数执行流的一种机制,当执行环境中调用了多个函数时,能够追踪到哪个函数正在执行,执行的函数体中又调用了哪些函数。
解释器会把执行函数压进调用栈,发现执行函数还调用了其他函数,那新函数也会被压进调用栈。
压栈出栈顺序为:先进后出FILO

函数提升

具名函数的声明无论在什么位置,它都会跑到第一行

arguments

是所有非箭头函数中可用的局部变量,是由传入参数构成的一个伪数组,可以通过索引访问到传入的参数