// 函数申明的几个形式// 规范的函数申明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属性的值}