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

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

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

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


  • 函数声明则相当于整个函数都被前置了,可以在声明之前调用。


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

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


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



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

3、arguments 是什么

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


4、函数的重载怎样实现

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


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

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


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

<ul>
    <li>li1</li>
    <li>li2</li>
    <li>li3</li>
    <li>li4</li>
    <li>li5</li>
    <li>li6</li>
</ul>
<script type="text/javascript">
     var liList=document.getElementsByTagName("li");
     for(var i=0; i<liList.length; i++){
         liList[i].onclick=function(){
             alert(i);
         }
      }
</script>

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



当然也有其他解决方法


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

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


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<arguments.length; i++){
        sum=sum+Math.pow(arguments[i],2);
     }
        console.log(sum);
 }
sumOfSquares(3,5);   //34
sumOfSquares(3,5,-2);  //38
sumOfSquares(3,5,-2,"hello");   //NaN

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。


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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容