美文网首页饥人谷技术博客
前端基础(问答12)

前端基础(问答12)

作者: 郑哲明 | 来源:发表于2016-07-10 22:29 被阅读27次

    keywords:函数声明、函数表达式、声明前置、argument、重载、作用域链


    • 函数声明和函数表达式有什么区别?

    函数声明:

    function functionName() {
        statement;
    }
    

    使用function关键字可以声明一个函数。

    函数表达式:

    var functionName = function() {
        statement;
    };
    

    将函数赋给一个变量,变量将会指向函数,下次使用直接调用变量即可。

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

    变量的声明前置:

    console.log(a);
    var a=1;
    //undefined
    
    /*实际上相当于:
    var a ;
    console.log(a);
    a=1;
    变量会提升到最前面;
    */
    

    函数的声明前置:

    fn();
    //"1"
    
    function fn() {
        console.log('1');
    }
    //实际上,和变量声明一样,函数声明会提升到最前面,但会在变量声明的后面。
    
    • arguments 是什么?

    在函数内部,你可以使用arguments对象获取到该函数的所有传入参数。类似于数组。

    function printPersonInfo(name, age, sex){
        console.log(name);
        console.log(age);
        console.log(sex);
        console.log(arguments);
    }
    
    • 函数的重载怎样实现?

    重载,即相同函数名的参数个数不同或顺序不同,被视为不同的函数。 在JS中没有函数重载的概念,函数的名称具有唯一性,参数不同或顺序不同也被认为是同一函数。

    function sum (a,b) {
        return a+b;
    }
    
    function sum (a,b,c){
        return a+b+c;
    }
    
    //如果重载,则这两个函数不同;
    

    但在JS中可以利用遍历arguments模仿重载的功能。例如求和:

    function sum() {
        var val = 0;
        for (var i=0;i<arguments.length;i++) {
            val += arguments[i];
        }
    }
    
    • 立即执行函数表达式是什么?有什么作用?

    立即执行函数表达式,简称IIFE,是指定义一个函数之后,立刻调用函数。常用的写法有两种:

    (function(){ /* code */ }());
    // 或者
    (function(){ /* code */ })();
    

    JavaScript引擎规定,如果function关键字出现在行首,一律解释成语句。因此,JavaScript引擎看到行首是function关键字之后,会认为这一段都是函数的定义。

    如果要立即执行函数,解决方法就是不要让function出现在行首,让引擎将其理解成一个表达式。

    通常只对匿名函数使用IIFE,主要的作用是:
    1、不必为函数命名,污染全局变量;
    2、在函数内部形成单独作用域,封装外部无法读取的私有变量;
    参考:
    详解JavaScript立即执行函数表达式
    JavaScript的立即执行函数

    • 什么是函数的作用域链?

    JavaScript的每个函数function都有自己的作用域,使用Active Object(简称AO)活动对象来保存,在相互嵌套的函数中形成了作用域链,如下图所示:

    作用域链

    作用域链就是从里到外的AO链。

    函数fn3中使用的变量,如在fn3作用域寻找不到,则往外层fn作用域寻找,以此类推,直到全局对象window。
    例如:

    var c = 5; 
    function t1(){ 
      var d = 6; 
      function t2(){ 
        var e = 7; 
        var d = 3;
     //如果在这里声明的var d = 3,
     //那么函数就不在向外寻找变量d,输出的值为15 
        console.log(c+d+e); 
      } 
      t2(); 
    } 
    t1();
    

    再如:

        var    a = 1
        function fn1() {
            console.log(a)
            var a = 5
            function fn2() {
                console.log(a)
                a = 20
                d = 10
            }
            a++
             fn2()
            console.log(a)
            console.log(d)
        }
        fn1()
        console.log(a)
        console.log(d)
        //undefined
        //6
        //20
        //10
        //1
        //10
    

    参考:
    JavaScript.the core
    深入理解JavaScript——作用域链

    代码

    • 以下代码输出什么?

    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('hunger', 28, '男');
    getInfo('hunger', 28);
    getInfo('男');
    
    //name: hunger
    //age: 28
    //sex: 男
    //['hunger', 28, '男']
    //name valley
    //name: hunger
    //age: 28
    //sex: undefined
    //['hunger', 28]
    //name valley
    //name: 男
    //age: undefined
    //sex: undefined
    //['hunger']
    //name valley
    
    • 写一个函数,返回参数的平方和?如

    function sumOfSquares(){
        var val = 0;
        for (var i=0,length=arguments.length; i<length;i++) {
            val += arguments[i]*arguments[i]
        }
        return console.log(val);
    }
    sumOfSquares(2,3,4);   // 29
    sumOfSquares(1,3);   // 10
    
    • 如下代码的输出?为什么

    console.log(a);           //变量声明前置
    var a = 1;
    console.log(b);         //b未定义
    //undefined
    //报错
    
    • 如下代码的输出?为什么

    sayName('world');                       //函数声明前置
    sayAge(10);                                  //函数表达式不能前置
    function sayName(name){
        console.log('hello ', name);
    }
    var sayAge = function(age){
        console.log(age);
    };
    //hello world
    //TypeError : sayAge is not a function
    
    • .如下代码的输出?为什么

    function fn(){}
    var fn = 3;       //变量声明前置,fn先是函数,后被赋予数值3;
    console.log(fn);
    
    //3
    
    • 如下代码的输出?为什么

    function fn(fn2){
       console.log(fn2);
       var fn2 = 3;          
       console.log(fn2);
       console.log(fn);
       function fn2(){
            console.log('fnnn2');
        }
     }
    fn(10);
    //function fn2()
    //3
    //function fn()
    
    //上述函数相当于:
    //function fn(fn2){
    //  var fn2;
    //  function fn2(){
    //      console.log('fnnn2');
    //  }
    //  console.log(fn2);
    //  fn = 3;
    //  console.log(fn2);
    //  console.log(fn);
    //}
    
    • 如下代码的输出?为什么

    var fn = 1;
    function fn(fn){
         console.log(fn);
    }
    console.log(fn(fn)); 
    //TypeError: fn is not a function
    
    //实际上,相当于:
    //var fn;
    //function fn(fn){
    //  console.log(fn);
    //}
    //fn = 1;
    //console.log(fn(fn));
    
    • 如下代码的输出?为什么

    //作用域
    console.log(j);
    console.log(i);
    for(var i=0; i<10; i++){    //i和j变量声明前置,i和j是全局变量
        var j = 100;
    }
    console.log(i);
    console.log(j);
    
    //undefined
    //undefined
    //10
    //100
    
    • 如下代码的输出?为什么

    fn();
    var i = 10;
    var fn = 20;
    console.log(i);
    function fn(){
        console.log(i);
        var i = 99;
        fn2();
        console.log(i);
        function fn2(){
            i = 100;
        }
    }
    
    //undefined
    //100
    //10
    
    // 实际上,相当于:
    // var i;              
    // var fn;
    // function fn(){
    //  var i;
    //  function fn2(){
    //      i = 100;         这里i是全局变量;
    //  }
    //  console.log(i);
    //  i = 99;
    //  fn2();
    //  console.log(i);
    // }
    // fn();
    // i = 10;
    // fn = 20;
    // console.log(i);
    
    • 如下代码的输出?为什么

    var say = 0;
    (function say(n){
        console.log(n);
        if(n<3) return;
        say(n-1);
    }( 10 ));
    console.log(say);
    
    // 10
    // 9
    // 8
    // 7
    // 6
    // 5
    // 4
    // 3
    // 2
    // 0
    
    //这里用到立即执行函数表达式(IIFE),say不断执行,直到遇到return跳出函数,
    //之后函数say被销毁,say成为0
    

    相关文章

      网友评论

        本文标题:前端基础(问答12)

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