// 函数申明的几个形式// 规范的函数申明function func1 () {    console.log(123);};// 函数的表达式let func2 = function() {    console.log(456);}// 构造函数与函数表达式let func3 = new Function(console.log(789));// 对象中的办法let obj = {    name:'xuwen',    fun4() {        console.log('aaa');    }}// 函数晋升{    // 函数与变量一样  在执行前就晋升  并且把整个函数晋升    // 在es6之前   变量的能够反复申明  就会呈现函数与变量重名的状况  这是不对的   在es6中   申明过的名称不可反复 不论是函数名还是变量名    func4();    function func4 () {        console.log('func4');    };}{    // 经典函数  递归函数    // 经典实例  阶乘    function factorial(num){        if(num > 0) {            if(num == 1){                return 1;            }            return num * factorial(--num);        }else{            console.error(参数谬误);        }    }    console.log(factorial(10));  // 3628800    // 应用递归求和    function sum(...args) {        return args.length == 0 ? 0 : args.pop() + sum(...args);   // pop()返回值为删除的元素  即数组的尾元素    }    console.log(sum(1,2,3,4,5,6));  // 21}{    // this 指向    // this遵循谁调用就指向谁    如果没有特地指出就是指向全局环境   在浏览器中指向window  在node环境在指向以后模块{}    console.log(this);    //  {}    const obj = {        name:'xuwen',        say(){            console.log(this.name);        },        run(){            console.log([...this.name].map(function(item) {                return item + `-${this.name}`;            }));        },        run1(){            console.log([...this.name].map(item =>  item + `-${this.name}`));        }    };    obj.say();     // xuwen    阐明指向申明的对象    obj.run();  //  因为以后模块并没有name属性  索引该属性为undefined    // [    //     'x-undefined',    //     'u-undefined',    //     'w-undefined',    //     'e-undefined',    //     'n-undefined'    //   ]    //  如果应用应用箭头函数 this则指向父级的上下文环境    obj.run1();   // [ 'x-xuwen', 'u-xuwen', 'w-xuwen', 'e-xuwen', 'n-xuwen' ]    // 有时候咱们须要特地把this指向特定的元素    通过扭转this指向扭转元素的属性   比方  数组指向伪数组从而达到伪数组具备数组的办法    //   call  apply  bind  这三个办法就是干这个事的    // call 与 apply 次要区别为参数不一样   call  从第二个参数开始 独自传参  不限参数  不限类型   而apply第二个参数为数组      const s1 = new Set([1,2,3]);    [].push.call(s1,4,6);    console.log(s1);  // Set { 1, 2, 3, '0': 4, '1': 6, length: 2 }    [].push.apply(s1,[7,8]);    console.log(s1);   // Set { 1, 2, 3, '0': 4, '1': 6, '2': 7, '3': 8, length: 4 }    // bind 传参相似call   但 bind 是不会立刻执行的  返回一个扭转了this指向的函数    let s2 = [].push.bind(s1,9);    console.log(s2());   // 5   返回length属性的值}