函数与作用域

2017-06-27  本文已影响12人  好好顽

1. 函数声明和函数表达式有什么区别
在ECMAScript中,创建函数的最常用的两个方法是函数表达式和函数声明,两者期间的区别是有点晕,因为ECMA规范只明确了一点:函数声明必须带有标示符(Identifier)(就是大家常说的函数名称),而函数表达式则可以省略这个标示符:

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

3. arguments 是什么
arguments 是一个类似数组的对象, 对应于传递给函数的参数。
arguments对象不是一个 Array
。它类似于数组,但除了 长度之外没有任何数组属性。例如,它没有 pop 方法。但是它可以被转换为一个真正的数组:
let args = Array.prototype.slice.call(arguments); let args = [].slice.call(arguments);
你还可以使用 Array.from()
方法或 spread 运算符将 arguments 转换为真正的数组:
let args = Array.from(arguments);let args = [...arguments];

4. 函数的"重载"怎样实现
用 arguments 对象判断传递给函数的参数个数,即可模拟函数重载:

function doAdd() {
  if(arguments.length == 1) {
    alert(arguments[0] + 5);
  } else if(arguments.length == 2) {
    alert(arguments[0] + arguments[1]);
  }
}

doAdd(10);  //输出 "15"
doAdd(40, 20);  //输出 "60"

当只有一个参数时,doAdd() 函数给参数加 5。如果有两个参数,则会把两个参数相加,返回它们的和。所以,doAdd(10) 输出的是 "15",而 doAdd(40, 20) 输出的是 "60"。
虽然不如重载那么好,不过已足以避开 ECMAScript 的这种限制。
5. 立即执行函数表达式是什么?有什么作用
立即执行函数表达式(Immediately-Invoked Function Expression),简称IIFE。表示定义函数之后,立即调用该函数。

(function(){
  var a  = 1;
})()

其他写法:

(function fn1() {});
[function fn2() {}];
1, function fn3() {};

作用:隔离作用域。
6. 求n!,用递归来实现

function factorial(num)
{
    // n不能小于0
    if (num < 0) {
        return -1;
    }
    // n=0时,阶乘结果是1
    else if (num == 0) {
        return 1;
    }
    // 否则,再次调用此递归过程
    else {
        return (num * factorial(num - 1));
    }
}

var result = factorial(8);
document.write(result);

// Output: 40320

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, '男');
    /* 输出:name:饥人谷 age:2 sex:男 ["饥人谷",2,"男"] name valley */
    getInfo('小谷', 3);
    /* 输出:name:小谷 age:3 sex:undefined ["小谷",3] name valley */
    getInfo('男');
    /* 输出:name:男 age:undefiend sex:undefined ["男"] name valley */

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

   function sumOfSquares(){
      var result = 0
      for (var i = 0; i < arguments.length; i++) {
        result = result + arguments[i] * arguments[i]
      }
      console.log(result)
   }
   var result = sumOfSquares(2,3,4)
   var result2 = sumOfSquares(1,3)
   console.log(result)  //29
   console.log(result2)  //10

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

    console.log(a);
    var a = 1;
    console.log(b);
    /* 输出:undefined 报错:b is not defined 原因:变量提升,没有b变量的声明*/

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

    sayName('world');//输出:hello world 函数声明前置
    sayAge(10);//报错:sayAge is not a function 函数表达式不前置
    function sayName(name){
        console.log('hello ', name);
    }
    var sayAge = function(age){
        console.log(age);
    };

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

输出结果  x:10
var x = 10
bar() 
function foo() {
  console.log(x)
}
function bar(){
  var x = 30
  foo()
}
//输出10

 1.第一步:执行上下文

  globalContext{
    AO:{
     x=10;
     foo:function();
     bar:function();
   },
    Scope:null
  }

  foo.[[scope]]=globalContext.AO
  bar.[[scope]]=globalContext.AO

 2.第二步:调用bar()

  barContext={
    AO:{
     x:30
     foo:function
    },
    Scope:bar.[[scope]]//globalContext.AO
  }

   bar()  //结果 x:30

 3.第三步:调用foo()

  fooContext={
    AO:{}
    Scope:foo.[[scope]]=globalContext.AO
   }
    foo()  //结果 x:10


   */

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

//  输出结果 x:30
var x = 10;
bar() 
function bar(){
  var x = 30;
  function foo(){
    console.log(x) 
  }
  foo();
}   
 /*
  输出结果 30
  第一步:执行上下文
  globalContext{
    AO:{
     x:10
     bar:function
    }
    Scope:null
  }
  bar.[[scope]]=globalContext.AO

  第二步:调用bar()

   barContext={
     AO:{
      x:30
      foo:function
     }
     Scope:bar.[[scope]]=globalContext.AO
   }

  bar()  //结果 x:30

  第三步:调用foo()

  fooContext={
    A0:{ }
    Scope:foo.[[scope]]=barContext.AO
  }

  foo() //结果 x:30

//  bar(){
//  foo()
//  }

*/

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


 //  输出结果  x:30
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

   第二步:调用bar()

   barContext={
     AO:{
       x=30
       :function
     }
     Scope:bar.[[scope]]=globalContext.AO
   }

   第三步:立即执行function ()

   functionContext={
     AO:{  }
     Scope:function.[[scope]]//barContext.AO
   }

*/

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

// 输出结果 a:undefined 5 1 6  20 200
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)

/*
   //第一步:执行上下文
   globalContext:{
     AO:{
       a:1
       fn:function
       fn3:function
     } 
     Scope:null
   }

    fn.[[scope]]=globalContext.A0
    fn3.[[scope]]=globalContext.AO

   //调用 fn()
   fnContext:{
     AO:{
       a:6
       fn3:function
       fn2:function
     }
    Scope:null
   }
    fn3[[scope]]=fnContext.AO
    fn2[[scope]]=fnContext.AO

   //调用 fn2()
   fn2Context:{ 
     AO:{  
    }
     Scope:fn2.[[scope]]=fnContext.AO
   }

   //调用 fn3()
   fn3Context:{
     AO:{
     } 
     Scope:fn3.[[scope]]=globalContext.AO
   }
 */
上一篇 下一篇

猜你喜欢

热点阅读