变量声明前置,立即执行函数,作用域链

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

函数声明和函数表达式都有声明前置的效果,但是:

  • 函数表达式的声明前置效果更像变量的声明前置效果,相当于只是一个变量名被前置了,而这个变量的值并没有被前置,不能在前面调用,会报错。


    变量声明前置,立即执行函数,作用域链_第1张图片
  • 函数声明则相当于整个函数都被前置了,可以在声明之前调用。


    变量声明前置,立即执行函数,作用域链_第2张图片

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

  • 什么是变量的声明前置?
    JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,然后给他初始值undefined,然后才逐句执行程序,这就叫做“变量提升”,也即“变量的声明前置”。


  • 什么是函数的声明前置?
    和变量的声明会前置一样,函数声明同样会前置,如果我们使用函数表达式那么规则和变量一样,如下图:



    如果我们使用函数声明的方式,那么即使函数写在最后也可以在前面语句调用,前提是函数声明部分已经被下载到本地。

3、arguments 是什么

是一个长的很像数组的对象,可以通过该对象获取到函数的所有传入参数。


变量声明前置,立即执行函数,作用域链_第3张图片

4、函数的重载怎样实现

在JavaScript中没有函数重载的概念,函数通过名字确定唯一性,参数不同也被认为是相同的函数,后面的覆盖前面的。函数调用没必要把所有参数都传入,只要你函数体内做好处理就行,但前提是传的参数永远被当做前几个。


变量声明前置,立即执行函数,作用域链_第4张图片

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

立即执行函数表达式有多种写法:(function(){})();, 或(function(){}()); ,或!function(){}();,或void function(){}(); , 如下图所示:

变量声明前置,立即执行函数,作用域链_第5张图片

作用: 创建一个独立的作用域。这个作用域里面的变量,外面访问不到(即避免变量污染)。
比如下面这个例子:不管单击哪个li,alert出来的总是6,而不是0、1、2、3、4、5。因为我们一定是在for循环结束后才单击的,而i是贯穿整个作用域的,所以,i总是6.

  • li1
  • li2
  • li3
  • li4
  • li5
  • li6

这里我们就可以用立即执行函数给每个li创造一个独立的作用域来解决这个问题。


变量声明前置,立即执行函数,作用域链_第6张图片

当然也有其他解决方法


变量声明前置,立即执行函数,作用域链_第7张图片

6、什么是函数的作用域链

JavaScript中所有的量都是存在于某一个作用域中的,在试图访问一个变量时JS引擎会从当前作用域开始向上查找直到Global全局作用域停止。
如下图:当alert(A)时, JS引擎沿着D的作用域, B的作用域, 全局作用域的顺序进行查找,这三个作用域组成的有序集合就成为作用域链。


变量声明前置,立即执行函数,作用域链_第8张图片

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('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;
["男"]
name:valley;

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

 function sumOfSquares(){
     var sum=0;
     for(var i=0; i

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

console.log(a);  //underfined,因为变量提升的缘故,初始值undefined
var a = 1;  
console.log(b);  //报错,因为b没有声明

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

sayName('world');     //输出hello world,因为使用函数声明声明的函数,相当于整个函数都被前置了,可以在声明之前就被调用
sayAge(10);  //会报错,因为使用表达式声明的函数,只是函数名被前置了,所以在声明之前调用会报错
function sayName(name){ 
    console.log('hello ', name); 
} 
var sayAge = function(age){ 
    console.log(age); 
};

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

function fn(){} 
var fn = 3; 
console.log(fn); //3,因为当在同一个作用域内定义了名字相同的变量和方法的话,无论其顺序如何,变量的赋值会覆盖方法的赋值

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

function fn(fn2){
    console.log(fn2); 
    var fn2 = 3; 
    console.log(fn2); 
    console.log(fn);
    function fn2(){
       console.log('fnnn2');
   } 
} 
fn(10); 

输出

 function fn2(){
       console.log('fnnn2');
   } 

3

function fn(fn2){ 
    console.log(fn2); 
    var fn2 = 3; 
    console.log(fn2);
     console.log(fn); 
    function fn2(){ 
        console.log('fnnn2'); 
  } 
}

因为,**当函数执行有命名冲突的时候,函数执行时载入顺序是变量、函数、参数 **,所以原代码等同于如下代码:

function fn(fn2){
    var fn2;  //变量声明前置
    function fn2(){   //函数声明前置
        console.log('fnnn2'); 
    }
     console.log(fn2);   //打印fn2()函数
     fn2 = 3;
     console.log(fn2);   //打印数字3
     console.log(fn);     //向上寻找,打印fn()函数
}
fn(10);

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

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

执行报错。代码等同于:

var fn;   //变量声明前置
function fn(fn){   //函数声明前置
    console.log(fn); 
}
fn=1;  //fn赋值为1
console.log(fn(fn));   //报错,因为此时的fn是数字1

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

 //作用域
console.log(j);   //undefined,变量声明前置导致
console.log(i);   //undefined,变量声明前置导致
for(var i=0; i<10; i++){ 
    var j = 100; 
} 
console.log(i);  //10,因为i=9时,j=100,然后再执行i++,i=10,此时不满足条件i<10,跳出循环。
console.log(j);  //100,j一直等于100.

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

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, fn;
function fn(){ 
    var i;
    function fn2(){
         i = 100; 
    } 
    console.log(i);   //undefined,因为此时fn2()函数没有被调用,所以i没有被赋值,打印undefined
    i = 99; 
    fn2();    //此处调用了fn2()函数,但是由于fn2()函数没有返回值,所以此处没有打印,但是i已经被赋值为100,并且是全局变量
    console.log(i);   //打印出i的值100
   
}
fn();
i=10;  //此处i被重新赋值为10
fn=20;
console.log(i); //打印重新赋值后的i值

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

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
括号内是一个立即执行函数,创建了一个独立的作用域,这个作用域里的变量,外面访问不到。第一次传入参数10,打印10,由于n=10不满足条件(n<3),于是执行函数say(n-1),打印9,接着是8,7......3,2,当n=2时,满足条件(n<3),于是跳出函数,执行console.log(say);,打印0。


© 本文归饥人谷和本人所有,如需转载请注明来源。

你可能感兴趣的:(变量声明前置,立即执行函数,作用域链)