饥人谷技术博客

函数与作用域

2017-03-23  本文已影响0人  66dong66

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

函数声明会提前,即可以在函数声明之前调用函数。而函数表达式只会将变量先提升,此时的变量是undefined,所以不能在函数表达式前调用函数。

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

在一个作用域下,var 声明的变量和function 声明的函数会前置。
变量的声明前置,var声明的变量按顺序提升到js最前,赋值为undefined
函数的声明前置,function声明的函数和变量一样前置,且都按照顺序提升。

3. arguments 是什么

argument是类数组对象,每个函数中都存在argument对象,argument并不是一个真正的数组,所以不具备除length属性之外的属性,arguments对象包含了函数运行时的所有参数,arguments[0]就是第一个参数,arguments[1]就是第二个参数,以此类推。这个对象只有在函数体内部,才可以使用。

var f = function(one) {
     console.log(arguments[0]);
     console.log(arguments[1]);
     console.log(arguments[2]);
  }
f(1, 2, 3)
// 1
// 2
// 3

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

重载是很多面向对象语言实现多态的手段之一,在静态语言中确定一个函数的手段是靠方法签名——函数名+参数列表,也就是说相同名字的函数参数个数不同或者顺序不同都被认为是不同的函数,称为函数重载。
在JavaScript中没有函数重载的概念,函数通过名字确定唯一性,参数不同也被认为是相同的函数,后面的覆盖前面的,但可以在函数体针对不同的参数调用执行相应的逻辑。

function printPeopleInfo (name, age, sex){
  if(name){
    console.log(name);
  }
  if(age){
    console.log(age);
  }
  if(sex){
    console.log(sex);
  }
}
 printPeopleInfo('gzd', 22);   //gzd 22
 printPeopleInfo('gzd', 22, 'male');  //gzd 22 male

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

立即执行函数表达式,首先它是一个表达式,而不是一个声明函数。其次,因为是表达式,所以可以用(), +, !, -等运算符来触发。

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

函数会立即执行,并且可以隔离作用域,立即执行函数内的任何赋值都不会影响这个函数外的变量和函数。

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

function fn(n){
     if(n === 1){
     return 1;
   }
   return n*fn(n-1);  //递归调用后还未结束:再乘以n,所以它不是尾调用
}

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: undefined
//sex: undefined
//["男"]
//name valley

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

function sumOfSquares(){
  var sum = 0;
  for(var i =0; i < arguments.length; i++){
    sum += arguments[i] * arguments[i];
  }
  return sum
}
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);

变量提升后代码为:
var a;
console.log(a); //a此时还没赋值,所以输出 undefined
a = 1;
console.log(b); //变量b没有声明过,所以会报错 Uncaught ReferenceError: b is not defined

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

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

变量提升后代码为:
function sayName(name){
  console.log('hello ', name);
}
var sayAge;

sayName('world');
sayAge(10); //函数表达式,声明必须在调用前

sayAge = function(age){
  console.log(age);
};

  输出:
// hello world
// Uncaught TypeError: sayAge is not a function

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

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

//声明提升后为
var x
function foo() {
  console.log(x)
}
function bar(){
  var x
  x = 30
  foo()
}
x = 10
bar()

作用域伪代码:
globalContext = {
  AO: {
      x:10,
      foo:function,
      bar:function
  }
  scope:null
}

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

fooContext = {
    AO:{}
    scope:globalContext.AO
}

barContext = {
    AO:{
       x:30 
   }
    scope:globalContext.AO
}

bar()开始执行,声明局部变量x=30,
foo()开始执行,执行console.log(x),发现 fooContext中没有x,
到scope:globalContext.AO中找x
发现:globalContext.AO中x为10
所以输出10

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

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

//声明提升后为
var x
function bar(){
    var x
    function foo(){
        console.log(x);
    }
    x = 30;
    foo();
}
x = 10;
bar();

作用域伪代码:
globalContext = {
    AO:{
        x:10;
        bar:function
    }  
    scope:null
}
bar.[[scope]] = globalContent.AO

barContent = {
  AO:{
    x:30
    foo:function  
  }
  scope:globalContent.AO
}
foo.[[scope]] = barContent.AO

fooContent = {
    AO:{}
    scope:barContent.AO
} 

bar() 执行,声明局部变量 x = 30;
foo() 执行,发现fooContext.AO中没有 x
根据scope:barContext.AO去找
发现scope:barContext.AO中x为30
所以输出30

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

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

//声明提升后
var x;
function bar(){
  var x
  x = 30;
  (function (){
    console.log(x)
  })()
}
x = 10;
bar()

作用域链伪代码:
globalContext = {
  AO:{
    x:10
    bar:function
  }
  scope:null
}
bar.[[scope]] = globalContext.AO

barContext = {
  AO:{
    x:30
    (anomyous):function
  }
  scope:globalContext.AO
}
(anomyous).[[scope]] = barContext.AO

(anomyous)Context = {
  AO:{}
  scope:barContext.AO
}

bar()执行声明局部变量x = 30
执行立即执行函数,立即执行函数中没有x
所以去他的scope:barContext.AO中找,发现x=30
所以输出30

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)


//声明提升
var a

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

function fn3(){
  console.log(a)
  a = 200
}

a = 1;
fn()
console.log(a)


作用域链伪代码:
globalContext = {
  AO: {
        a:1 => 200
        fn:function
        fn3:function
    },
    Scope: null
}
fn.[[scope]] = globalContext.AO
fn3.[[scope]] = globalContext.AO

fnContext = {
    AO: {
        a:undefined => 5 => 6 => 20
        fn2:function
    },
fn2.[[scope]] = fnContext.AO
}

fn3Context = {
    AO: {},
    Scope:globalContext.AO
}
fn2Context = {
AO: {}
Scope: fnContext.AO
}

结果是:undefined 5 1 6 20 200
上一篇下一篇

猜你喜欢

热点阅读