美文网首页
函数与作用域

函数与作用域

作者: 湖衣 | 来源:发表于2017-04-06 15:26 被阅读0次

    声明前置和作用域也是JS 部分面试常考点

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

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

     function sayHello(){
       console.log('hello')
     }
     //函数调用
     sayHello()```
    声明不必放到调用的前面,声明的是一个函数,用时就是调用,该声明位置可放在后面。函数声明最重要的特征就是函数声明提升,意思是在执行代码之前就会读取函数声明。
    
    函数表达式:用函数表达式定义的函数在使用之前必须先赋值。
     ```var sayHello = function(){
       console.log('hello');
     }
     sayHello()```
    声明必须放到调用的前面,声明的是一个变量,必须声明过后才能使用。
    
    
    ####2.什么是变量的声明前置?什么是函数的声明前置
    - 变量的声明前置:JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,然后给他初始值undefined,然后才逐句执行程序,这就叫做“变量提升”,也即“变量的声明前置”。在一个作用域块中,所有的变量都被放在块的开始出声明,但是变量的赋值不会提升。
    
    - 函数的声明前置:在一个作用域下,同var 声明的变量一样,function 声明的函数也会前置。函数的声明前置优先级高于变量的声明前置。
    
    ```console.log(a); 
    var a = 3;
    console.log(a); 
    sayHello();
    function sayHello(){
     console.log('hello');
    }```
    执行时语句顺序如下:
    ```var a
    function sayHello(){}
    console.log(a);//undefined
    a=3
    console.log(a); //3
    sayHello();```
    
    ####3.arguments 是什么
    arguments 是一个类似数组的对象, 对应于传递给函数的参数。在函数内部,可以使用arguments对象获取到该函数的所有传入参数。arguments 对象仅在函数内部有效,在函数外部调用 arguments 对象会出现一个错误。
    严格模式下,
    1. arguments 不能通过程序语法被绑定(be bound)或赋值。
    2.函数的 arguments 对象会保存函数被调用时的原始参数。arguments[i] 的值不会随与之相应的参数的值的改变而变化,同名参数的值也不会随与之相应的 arguments[i] 的值的改变而变化。
    3.不再支持 arguments.callee。arguments.callee 是一个不可删除属性,而且赋值和读取时都会抛出异常。
    
    ``` function printPersonInfo(name, age, sex){
       console.log(name);
       console.log(age);
       console.log(sex);
     }
    可以写为
    function printPersonInfo(){
       console.log(arguments[0]);
       console.log(arguments[1]);
       console.log(arguments[2]);
     }```
    
    ####4.函数的"重载"怎样实现
    在 JS 中没有重载,同名函数会覆盖。 但可以在函数体针对不同的参数调用执行相应的逻辑。
    ```function printPeopleInfo(name, age, sex){
       if(name){
         console.log(name);
       }
       if(age){
         console.log(age);
       }
       if(sex){
         console.log(sex);
       }
     }
     printPeopleInfo('Byron', 26);
     printPeopleInfo('Byron', 26, 'male');```
    
    ####5.立即执行函数表达式是什么?有什么作用
    立即执行函数通常有下面几种写法:
    ```(function fn0() {})();
    (function fn1() {} ()); 
    // 在数组初始化器内只能是表达式
    [function fn2() {}];
    // 逗号也只能操作表达式
    1, function fn3() {};```
    
    在Javascript中,一对圆括号“()”是一种运算符,跟在函数名之后,表示调用该函数。比如,print()就表示调用print函数。
    作用:
    一是不必为函数命名,避免了污染全局变量;
    二是隔离作用域,IIFE内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量。
    
    ####6.求n!,用递归来实现
    ```function fn1(i){
     if(i===1){
       return 1;
     }
     return i*fn1(i-1);
    }```
    
    ####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('男');```
    输出:
    name:饥人谷  age:2  sex:男  ['饥人谷',2,'sex']  name valley
    name:小谷  age:3  sex:undefined   ['小谷',3]  name valley
    name:男  age:undefined   sex:undefined    ['男']  name valley
    
    ####8. 写一个函数,返回参数的平方和?
    ```function sumOfSquare() {
       var result = 0;
       for(var i=0; i<arguments.length; i++){
         result+=arguments[i]*arguments[i];
       }
       return result;
    }
    var result = sumOfSquares(2,3,4)
    var result2 = sumOfSquares(1,3)
    console.log(result)  //29
    console.log(result)  //10```
    
    ####9. 如下代码的输出?为什么
       ```console.log(a);
       var a = 1;
       console.log(b);```
    输出:
    undefined /*因为变量声明前置,var a,console.log(a)*/
    b is not defined报错 /*因为变量b没有声明*/
    
    ####10. 如下代码的输出?为什么
       ```sayName('world');
       sayAge(10);
       function sayName(name){
           console.log('hello ', name);
       }
       var sayAge = function(age){
           console.log(age);
       };```
    输出:
    hello world /*函数声明可以放在后面*/
    sayAge is not a 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:null
    }
    foo.[[scope]] = globalContext.AO
    bar.[[scope]] = globalContext.AO
    barContext{
     AO:{
       x:30
     },
       Scope:bar.[[scope]] //globalContext.AO
    }
    fooContext{
     AO:{    
     },
       Scope:foo.[[scope]] // globalContext.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:null
    }
    foo.[[scope]] = barContext.AO
    bar.[[scope]] = globalContext.AO
    barContext{
     AO:{
       x:30
       foo:function
     },
       Scope:bar.[[scope]] //globalContext.AO
    }
    fooContext{
     AO:{    
     },
       Scope:foo.[[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:null
    }
    bar.[[scope]] = globalContext.AO
    barContext{
     AO:{
       x:30
     }
     Scope:bar.[[scope]]
    }```
    
    
    ####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:null
    }
    fn.[[scope]] = globalContext.AO
    fn2.[[scope]] = fnContext.AO
    fn3.[[scope]] = globalContext.AO
    fnContext{
     AO:{
       a:20
       fn2:function
     },
       Scope:fn.[[scope]] //globalContext.AO
    }
    fn2Context{
     AO:{ 
     },
       Scope:fn2.[[scope]] // fnContext.AO  
    }
    fn3Context{
     AO:{ 
     },
       Scope:fn3.[[scope]] // globalContext.AO  
    }```

    相关文章

      网友评论

          本文标题:函数与作用域

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