定义函数:
    具名函数

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

    匿名函数

    1. let a = function(x,y){return x+y}
    2. a(1,2);

    箭头函数

    1. let f1 = x => x*x
    2. f1(x)
    3. let f2 = (x,y) => x*y
    4. let f3 = (x,y) => {return x+y}

    函数自身 和 函数调用

    1. let fn = () => console.log('hi')
    2. fn // 函数自身
    3. let fn = () => console.log('hi')
    4. fn() // 函数调用

    函数的要素:
    1、调用时机

    1. let i = 0
    2. for(i = 0; i<6; i++){
    3. setTimeout(()=>{
    4. console.log(i)
    5. },0)
    6. }
    7. // 打印出 6 次 6

    当使用setTimeout()延迟函数时,需要先执行For循环,然后进行打印。当执行for循环后,此时的i=6,然后需要打印六次i的结果,此时打印出为6个6

    1. for(let i = 0; i<6; i++){
    2. setTimeout(()=>{
    3. console.log(i)
    4. },0)
    5. }
    6. // 打印出 0 , 1 ,2 ,3 ,4 ,5

    在JS中,当for 和 let在一起的时候,每次循环会多创建一次 “i”

    2、作用域

    1. function f1(){
    2. let a =1
    3. function f2(){
    4. let a =2
    5. consloe.log(a)
    6. }
    7. console.log(a)
    8. a=3
    9. f2()
    10. }
    11. f1()

    如果多个作用域有同名变量,那么查找同名变量的声明时,就向上取最近的作用域(就近原则)
    查找同名变量的过程与函数执行无关,但变量值与函数执行有关.

    在顶级作用域声明的变量是全局变量,window的属性为全局变量,其他都为局部变量。
    3、闭包
    如果函数用到外部变量,那么函数加这个变量 就叫做闭包
    4、形参

    1. let f3 = (x,y) => {return x+y}
    2. // x , y为形参
    3. f3(1,2) //1,2为实参

    5、返回值
    函数如果没写return ,返回值为undefined
    返回值为console.log(‘’)即为undefined
    6、调用栈
    7、函数提升(具名函数 无论放在哪里,它都会跑到第一行)
    8、arguments 和 this(除 箭头函数)

    1. function add(x,y){
    2. return x+y
    3. }
    4. add.call(undefined,1,2)// undefined作为第一个参数要作为this的值,也可以使用null

    立即执行函数

    1. let i = 0
    2. for(i = 0; i<6; i++){
    3. !(function(x) {
    4. setTimeout(() => {
    5. console.log(x)
    6. }, 0);
    7. })(i);
    8. }

    立即执行函数,[ !、~、()、+、- ]都行,但推荐使用” ! “