js 给一段代码,给出运行后的最终结果的一些综合情况、
秋招快到了,我们在准备笔试或者面试题的时候,经常会遇到一些题,给一段js代码,回答运行后的结果是什么,下面我来整理一下。
1、作用域问题
(1)全局作用域
值为0
这个函数运行时,外面alert(x)拿到的是全局作用域中x的值,第一个声明的var x=0;的值是全局作用域中的值,第二个在f函数中声明的var x=2的值是局部作用域的值,因为用var重新声明了一个变量,两个指向的是不同的作用域,因此alert(x)返回的是0
(2)局部作用域
如果我们把var x=2;中的var去掉,变成下面这样子
值为2
出现这种情况是因为,var x=0;声明的是全局作用域的值,f()函数也是全局作用域,然后f函数中的值。x会覆盖掉外部的值,因此就会导致得到的值是2
再来看一个例子
这个值为3,4,i is not defined
这个也是因为x,y有声明并且在全局作用域中,这时就能得到x,y的值,而i是在f函数中命名的,在外部的全局中就不能调用到。
如果将alert()语句放在f函数中,像下面这样
值为3,4,20
2、函数覆盖问题
值为1,1
这里f函数将x的值置为1,然后虽然两次调用f()函数,但是函数已经产生覆盖,第一个函数覆盖了第二个函数,因此两次调用都是1
如果将上面的匿名函数f注释掉,如下
值为2,2
这时,已经不发生函数覆盖,就一直是2,
如果将命名函数注释掉
值为1,1
像这样,也不发生函数覆盖,也是只调用f函数、
要解决函数覆盖的方法,就先写命名函数,再写匿名函数
值为2,1
这样的话,命名函数f()先调用,匿名函数f后调用
总结:以后写函数时,尽量写成匿名函数形式,var f = function(){}
3、变量和函数提升问题
1、函数未定义
变量未定义,直接是undefined
2、函数已定义
这里声明了变量,js解释器“前瞻性”查找所有变量定义,把它们“提升”到函数顶部,就出现undefined,第一个未定义就出现undefined,第二个定义了就出现1223
3、内部变量重复定义
这里使用了闭包函数,第一个name变量提升,就会出现undefined,本来可以访问到全局作用域的name,但是内部已经重新声明了,name变量提升,就会出现undefined。这里典型的使用了函数声明提前,函数体内的块级作用域覆盖住了外部name的全局作用域,然后由于函数声明提升,相当于在函数体内,先var name;然后console.log("Original name was"+name);然后name = "Underhill";console.log("New name is" + name);最后的值是一样的。
因此,建议所有变量的定义,都放在头部,并使用var a=XX,b=xxx这样定义。
4、函数直接调用
这里函数直接调用就没什么好说的
5、函数定义提升
函数定义提升仅仅作用域函数定义,而不作用于函数表达式
这里函数definitionHoisted(),已经提升,而函数定义不作用于函数表达式,因此就抛出TypeError
6、命名函数表达式
在这里,函数名字是funcName()是函数的一部分,不会得到提升,而varName()也找不到这个方法
7、闭包函数与全局函数
var result = f1();就调用了f1()函数,这时result即为f2,函数,result是全局变量
result() 调用完之后的值为999,这时就是调用了f2函数,并将值输出
nAdd(),调用完之后,这时nAdd()函数为全局函数,也是闭包函数,值为1000,
result(),这个调用f2函数,就输出1000.
8.闭包中的命名提升。
这里输出的值是999,因为1000传入进去,a的值被覆盖了,a变量命名提升,输出就是999;
9、函数覆盖问题
在js函数中,是没有函数重载的,以前学java的时候,当函数名是相同的,主要传递的类型或者参数不同就会出现重载,两个都可以用,但是在js中
主要出现两个同名的函数,就会出现函数覆盖,第二个add函数,覆盖第一个add函数,然后,由于函数声明提前,就会直接将函数覆盖。
那么什么是函数声明提前呢?
函数声明提前就是变量在变量声明之前就是已经可用,一般用在函数体内,在一个函数体内是块级作用域,一般函数,内部同名函数会覆盖外部同名函数,然后又由于函数声明提前,就可以有值。
That's all,Thank you!