美文网首页
函数与作用域(进阶3)

函数与作用域(进阶3)

作者: 饥人谷_js_chen | 来源:发表于2017-01-26 11:46 被阅读0次

    1. 函数声明和函数表达式有什么区别

    • 函数声明不必放在调用前面
    • 函数表达式必须放在调用前面

    2. 什么是变量的声明前置?什么是函数的声明前置

    • 在一个作用域下,var声明的变量和function声明的函数会前置
    • 不在函数作用域内,var声明的变量和function声明的函数都会前置到全局最顶部
    • 在函数作用域内,var声明的变量和function声明的函数则会前置到函数体的最顶部

    3. arguments 是什么

    arguments是函数所有参数的集合(数组),可以在函数内使用

    4. 函数的"重载"怎样实现

    js不支持重载,同名函数会覆盖,需要对参数进行非空或者类型的判断来模拟函数重载(可以用if条件判断语句来实现)

    5. 立即执行函数表达式是什么?有什么作用

    • 类似于下面的写法是立即执行函数表达式:
    (function(){
      //todo
    }())
    
    • 作用:隔离作用域

    6. 求n!,用递归来实现

    答:两种方法(其中尾递归优化用了ES6语法)
    尾调用优化:调用函数是最后一步操作,递归时只保留内层函数的调用帧

    • 没有尾调用优化的递归
    function fn(n){
      if(n===1){
        return 1;
      }
      return n*fn(n-1);//递归调用后还未结束:再乘以n,所以它不是尾调用
    }
    
    • 优化后的递归(尾递归优化)
    const fm = (n, flat)=>{
      if(n===1){
        return flat;
      }
      return fm(n-1,n*flat);//尾部递归调用后结束,释放外层函数的调用帧,只保留内层函数的调用帧
    };
    const fmm = (n)=>fm(n,1);
    
    • 打印结果
    var res1 = fn(10);
    let res2 = fmm(10);
    console.log(res1, res2);//3628800  3628800
    

    7. 以下代码输出什么?

          function getInfo(name, age, sex){
            console.log('name:',name);
            console.log('age:', age);
            console.log('sex:', sex);
            console.log(arguments);
            arguments[0] = 'valley';
            console.log('name', name);
        }
    
    getInfo('饥人谷', 2, '男');
    getInfo('小谷', 3);
    getInfo('男');
    

    答:

    • getInfo('饥人谷', 2, '男');
    "name":  "饥人谷"
    "age":  2
    "sex":  "男"
    [object Arguments]{0:"饥人谷", 1:2, 2:"男"}
    "name"  "valley"
    
    • getInfo('小谷', 3);
    "name":  "小谷"
    "age":  3
    "sex":  undefined
    [object Arguments]{0:"小谷", 1:3}
    "name"  "valley"
    
    • getInfo('男');
    "name":  "男"
    "age":  undefined
    "sex":  undefined
    [object Arguments]{0:"男"}
    "name"  "valley"
    

    8. 写一个函数,返回参数的平方和?

    function sumOfSquares(){
       }
       var result = sumOfSquares(2,3,4)
       var result2 = sumOfSquares(1,3)
       console.log(result)  //29
       console.log(result2)  //10
    

    三种方法:分别是for循环、for-in循环和Object.values(),代码如下:

     function sumOfSquares(){
       let res = 0;
    //  1. for 循环
    //    for(let i=0; i<arguments.lenght; i++){
    //      res += arguments[i] * arguments[i];
    //    }
    //  2. for-in循环
    //    for (let index in arguments) {
    //      res += arguments[index]*arguments[index];
    //    }
    //   3.ES8引入了Object.keys、Object.values和Object.entries,作为遍历一个对象的补充手段。  
      for(let value of Object.values(arguments)) {
        res += value*value;
      }
       return res;
     }
    

    9. 如下代码的输出?为什么

        console.log(a);
        var a = 1;
        console.log(b);
    

    输出:undefined 报错("error" "ReferenceError: b is not defined ...");
    - 因为var声明的变量会声明前置,即在console.log(a)之前就声明了a(但还没赋值),故输出undefined;
    - b没有声明,所以会报错

    10. 如下代码的输出?为什么

        sayName('world');
        sayAge(10);
        function sayName(name){
            console.log('hello ', name);
        }
        var sayAge = function(age){
            console.log(age);
        };
    

    输出: "hello " "world" 报错("error" "TypeError: sayAge is not a function")

    • function声明的函数无需写在调用前;
    • 但函数表达式必须先声明再调用.

    11. 如下代码输出什么? 写出作用域链查找过程伪代码

    var x = 10
    bar() 
    function foo() {
      console.log(x)
    }
    function bar(){
      var x = 30
      foo()
    }
    

    输出:10

    globalContext = {
      AO:{
        x:10,
        foo:function,
        bar:function,
      },
      scope:none;
    }
    foo['scope'] = globalContext.AO;
    bar['scope'] = globalContext.AO;
    barContext = {
      AO:{
        x:30,
      },
      scope:golbalContext.AO
    }
    fooContext = {
      AO:{},
      scope:golbalContext.AO
    }
    

    12. 如下代码输出什么? 写出作用域链查找过程伪代码

    var x = 10;
    bar() 
    function bar(){
      var x = 30;
      function foo(){
        console.log(x) 
      }
      foo();
    }   
    

    输出: 30,伪代码如下:

    globalContext = {
      AO:{
        x:10,
        bar:function,
      },
      scope:none,
    }
    bar['scope'] = globalContext.AO;
    barContext = {
      AO:{
        x:30,
        foo:function,
      },
      scope: globalContext.AO,
    }
    fooContext = {
      AO:{},
      scope:barContext.AO,
    }
    

    13. 以下代码输出什么? 写出作用域链的查找过程伪代码

    var x = 10;
    bar() 
    function bar(){
      var x = 30;
      (function (){
        console.log(x)
      })()
    }
    

    输出 30

    globalContext = {
      AO:{
        x:10,
        bar:function,
      },
      scope:none;
    }
    bar['scope'] = globalContext.AO;
    barContext = {
      AO:{
        x:30,
        foo:function,
      },
      scope:golbalContext.AO
    }
    foo['scope'] = barContext.AO;
    fooContext = {
      AO:{},
      scope:barContext.AO
    }
    

    14. 以下代码输出什么? 写出作用域链查找过程伪代码

    var a = 1;
    
    function fn(){
      console.log(a)
      var a = 5
      console.log(a)
      a++
      var a
      fn3()
      fn2()
      console.log(a)
    
      function fn2(){
        console.log(a)
        a = 20
      }
    }
    
    function fn3(){
      console.log(a)
      a = 200
    }
    
    fn()
    console.log(a)
    

    输出:undefined 5 1 6 20 200

    globalContext = {
      AO:{
        a:200,
        fn:function,
        fn3:function,
      },
      scope:none;
    }
    fn['scope'] = globalContext.AO;
    fn3['scope'] = globalContext.AO;
    fn3Context = {
      AO:{},
      scope:globalContext.AO,
    }
    fnContext = {
      AO:{
        a:20,
        fn2:function,
      },
      scope:globalContext.AO
    }
    fn2['scope'] = fnContext.AO;
    fn2Context = {
      AO:{},
      scope:fnContext.AO
    }
    

    相关文章

      网友评论

          本文标题:函数与作用域(进阶3)

          本文链接:https://www.haomeiwen.com/subject/xoyxittx.html