美文网首页
JavaScript关于函数

JavaScript关于函数

作者: 不是鱿鱼 | 来源:发表于2016-07-12 12:08 被阅读53次

    问答

    函数声明和函数表达式有什么区别 (*)

    函数声明形式:

    function sayHello(){
      console.log("Hello, World! ");
    }
    
    

    函数表达式形式:

    var sayHello = function(){
      console.log("Hello, World! ");
    };
    
    

    在声明一个变量的时候,javascript解释器会将变量声明的语句提前,函数声明形式会发生函数声明前置,所以代码如果放在使用之后也可以生效,而函数表达式形式只发生了变量声明前置,如果在定义之前使用,函数名目前还只是一个变量名,不能用()进行执行,会抛出错误。

    什么是变量的声明前置?什么是函数的声明前置 (**)

    var a = 1;
    //实际上相当于:
    var a; //这句声明会提前到所有语句之前执行
    a=1;
    

    所以,

    console.log(b); 
    var b = 1;//console.log 并不会报错,而是返回变量声明之后的值undefined。
    

    arguments 是什么 (*)

    arguments 是一个可以接收所有函数传递参数的类似数组,在函数里可以直接取用。当函数的参数不确定数量的时候可以使用arguments对形参进行数组的方式操作,可以实现类似重载。

    函数的重载怎样实现 (**)

    function fn(){ 
      var sum = 0; 
      for(x in arguments ){
        sum=arguments[x]+sum;
      };
      console.log(sum);
    }
    //无论多少参数都可实现累加运算
    

    立即执行函数表达式是什么?有什么作用 (***)

    (function() {
      c =1 ;
      console.log(c)
    })();
    
    

    立即执行函数可以将写在函数体内的语句直接执行。区别于普通语句,立即执行函数内的变量不会干扰函数体外,形成一个类似区块的空间。

    什么是函数的作用域链 (****)

    函数对象其中一个内部属性是[[Scope]],由ECMA-262标准第三版定义,该内部属性包含了函数被创建的作用域中对象的集合,这个集合被称为函数的作用域链,它决定了哪些数据能被函数访问。
    在函数执行过程中,每遇到一个变量,都会经历一次标识符解析过程以决定从哪里获取和存储数据。该过程从作用域链头部,也就是从活动对象开始搜索,查找同名的标识符,如果找到了就使用这个标识符对应的变量,如果没找到继续搜索作用域链中的下一个对象,如果搜索完所有对象都未找到,则认为该标识符未定义。函数执行过程中,每个标识符都要经历这样的搜索过程。


    --JavaScript 开发进阶:理解 JavaScript 作用域和作用域链]

    简单来说,函数作用域链用于查找函数内部变量的位置。在执行过程中,按照作用域链表的顺序依次进行查找。在函数每执行一次,这个表进行动态创建。所以,在实际使用中应当尽量减少全局变量的使用,避免with语句使用,如果一个跨作用域的对象被引用了一次以上,则先把它存储到局部变量里再使用。


    代码

    1. 以下代码输出什么? (难度**)

    • 可以看出arguments 是参数的数组,可以对其进行修改,改变参数。
    • 当参数缺省的时候,定义为 undefined。
    • 参数是具有顺序的,第一个参数传递为第一个形参。
    1. 写一个函数,返回参数的平方和?如 (难度**)

    function sumOfSquares(){
      var sum = 0;
      for(var x in arguments){
        sum += arguments[x]*arguments[x];
      }
      console.log(sum);
    }
    
    sumOfSquares(2,3,4);   // 29
    sumOfSquares(1,3);   // 10
    
    1. 如下代码的输出?为什么 (难度*)

    console.log(a);//返回 undefined
    var a = 1;
    console.log(b);//报错 提示未定义
    

    因为声明前置,实际上在这段代码执行前就已经执行了var a;,所以在console.log(a)的时候不发生错误,返回undefined。

    4.如下代码的输出?为什么 (难度*)

    • 由于函数声明前置,sayName可以正常执行
    • sayAge用了函数表达式形式,在赋值之前都不可以使用。

    5.如下代码的输出?为什么 (难度**)

    function fn(){}
    var fn = 3;
    console.log(fn);//3
    

    结果比较直观,实际上将上面的语句颠倒也会输出相同的结果:

    var fn = 3;
    function fn(){}
    console.log(fn);//3
    
    • 还是因为声明前置的原因,可以将声明都放到开头,再来理解:
    var fn;
    function fn(){}
    
    fn = 3;
    console.log(fn);//3
    
    

    这就是上面那段代码实际执行的样子,这也就不难理解了。
    需要注意的是,声明前置,变量的声明要比函数的声明要更早执行。

      function fn(){}
      var fn;  
      console.log(fn);
    
    //function fn(){}
    

    6.如下代码的输出?为什么 (难度***)

    • 在函数内部定义的函数,也会发生声明前置。上图中即使传入了参数10,但与函数内部函数重名,被覆盖掉了。此时console.log(fn2),打印出的就是fn2函数本身。此后fn2被重新赋值2,打印出3。

    7.如下代码的输出?为什么 (难度***)

    var fn = 1;
    function fn(fn){
       console.log(fn);
    }
    console.log(fn(fn)); 
    
    //Uncaught TypeError: fn is not a function(…)
    

    实际执行过程,由于声明前置:

    var fn;
    function fn(fn){
       console.log(fn);
    }
    
    fn = 1;
    console.log(fn(fn)); 
    

    fn被重新赋值为1,自然无法执行,报错。

    8.如下代码的输出?为什么 (难度**)

        //作用域
        console.log(j);//undefined
        console.log(i);//undefined
        for(var i=0; i<10; i++){
            var j = 100;
        }
        console.log(i);//10
        console.log(j);//100
    
    • 需要注意的是,for是属于运算符,不属于函数,所以在其内部定义的变量和当前属于同一个作用域。在JS中只有函数内部使用var定义,才具备另一个作用域性质。

    9.如下代码的输出?为什么 (难度****)

    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;
        }
    }
    

    改写代码:

    var i;
    var fn;
    function fn(){
        var i;
        function fn2(){
            i = 100;
        }
    
        console.log(i);//undefined
        i = 99;
        fn2();
        console.log(i);//100
        
    }
    
    fn(); 
    //undefined
    //100
    i = 10;
    fn = 20;
    console.log(i);//10
    

    10.如下代码的输出?为什么 (难度*****)

    • 立即执行函数的内部定义的函数名、变量不会影响到函数外面。所以在其内部执行的say(),并没有覆盖函数外的say = 0; 在最后打印出来还是0 。
    • 函数内部有一个嵌套结构。使用嵌套时,函数名可以在function后定义。不需要的时候可以不加。
    • return的执行,伴随函数的退出,不再继续往下执行。

    本教程版权归属于 张宇 及 饥人谷 所有,转载请说明来源~

    相关文章

      网友评论

          本文标题:JavaScript关于函数

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