函数声明 VS. 函数表达式
2017-08-12 14:14
176 查看
昨晚室友扔我一道前端JS面试题,我仔细看了一下,给出了答案,果不其然,有两个地方答错了,这里就记录一下。
做第二个的时候,我的思路为:getName()这肯定是要调全局的getName函数,这时候要纠结一下了,我们有一个getName函数表达式,还有一个getName函数声明,那到底该调用哪个呢?这时候我的脑海里出现了一句话“在JavaScript中函数是一等公民”,so,我把getName函数表达式中的getName当作一个变量,getName函数声明中的getName当作函数,所以结果理所当然的认为是5。
我的思路从一开始就不对,拿到这道题,首先应该想一下考的知识点是什么?很明显,这就是考察变量提升(Hoisting)。就拿上面代码的后两行来说,先定义的getName函数表达式(1),然后是getName函数声明(2),首先要明确,
这里补充一下,在JavaScript中,变量进入一个作用域可以通过下面四种方式:
语言自定义变量:所有的作用域中都存在this和arguments这两个默认变量
函数形参:函数的形参存在于函数作用域中
函数声明:funciton foo(){}
变量定义:var foo
可以这样理解:在开始执行作用域中的代码时,
给当前
给当前作用域对象添加属性名为函数的形参,属性值为函数的实参的属性。
把作用域中的函数声明提前,也就是给作用域对象添加一个属性名为函数名,属性值为函数声明的属性。
把作用域中的变量定义提前,相当于给作用于对象添加一个属性名为变量名,属性值为undefined的属性。
上面这一段仅仅是我个人的理解,网上有篇博文描写的很准确
当进入执行上下文(代码执行之前)时,VO(变量对象)里已经包含了下列属性:
函数的所有形参(如果我们是在函数执行上下文中)
所有函数声明(FunctionDeclaration, FD)
所有变量声明(var, VariableDeclaration)
我觉得有个例子能用来考察是否真正理解了变量提升
结果输出:1
答案是看情况:
同样是一个 x 标识
如果在进行函数 function x() {}; 声明的同时,只声明 var x; 而不对 x 进行赋值操作,那么此时函数声明优先级更高,函数声明会覆盖掉变量声明
如果在进行函数 function x() {}; 声明的同时,不仅声明 var x; 而且同时还对 x 进行赋值操作,即 var x = 1;,那么此时,变量声明会被 保存 ,不会被覆盖。变量声明的优先级更高, 会覆盖掉函数声明。只有当函数声明及对函数的操作出现在变量声明之前时,函数声明才不会被覆盖。
看完代码上面的解释,相信以上三段代码大家都能得出正确的输出结果。
回到之前的面试题,第三个和第二个是同一个考点。这里就不再赘述了。
最后说一下开始的JS面试题的结果:2411233
Javascript作用域和变量提升https://segmentfault.com/a/1190000003114255
js闭包http://www.cnblogs.com/zhjjNo1/archive/2011/02/12/1951905.html
题目
function Foo(){ getName = function(){alert(1)}; return this; } Foo.getName = function(){alert(2)}; Foo.prototype.getName = function(){alert(3)}; var getName = function(){alert(4)}; function getName(){alert(5)}; //请写出一下输出结果 Foo.getName() getName() Foo().getName() getName() new Foo.getName() new Foo().getName() new new Foo().getName()
解析
这里先说一下我做错的两项:二和三。做第二个的时候,我的思路为:getName()这肯定是要调全局的getName函数,这时候要纠结一下了,我们有一个getName函数表达式,还有一个getName函数声明,那到底该调用哪个呢?这时候我的脑海里出现了一句话“在JavaScript中函数是一等公民”,so,我把getName函数表达式中的getName当作一个变量,getName函数声明中的getName当作函数,所以结果理所当然的认为是5。
我的思路从一开始就不对,拿到这道题,首先应该想一下考的知识点是什么?很明显,这就是考察变量提升(Hoisting)。就拿上面代码的后两行来说,先定义的getName函数表达式(1),然后是getName函数声明(2),首先要明确,
JS中,函数声明和函数表达式都是用来定义函数的。所以前面我的理解都错了(函数表达式的左操作数是变量)。由于(1)和(2)都是定义了一个名为getName的函数,那调用时,到底执行的是哪个函数呢?这就要说到变量提升了。
变量提升
一切源于JS只有函数作用域和全局作用域。在一个作用域中的代码执行之前,函数声明(函数本身也是一种变量–foo = function(){},所以也存在变量提升的现象)和变量定义通常会被解释器移到所在作用域的最顶部。
这里补充一下,在JavaScript中,变量进入一个作用域可以通过下面四种方式:
语言自定义变量:所有的作用域中都存在this和arguments这两个默认变量
函数形参:函数的形参存在于函数作用域中
函数声明:funciton foo(){}
变量定义:var foo
可以这样理解:在开始执行作用域中的代码时,
给当前
作用域对象(我自己起的名字)添加一个arguments属性,属性值为调用该函数时,传递的参数列表。
给当前作用域对象添加属性名为函数的形参,属性值为函数的实参的属性。
把作用域中的函数声明提前,也就是给作用域对象添加一个属性名为函数名,属性值为函数声明的属性。
把作用域中的变量定义提前,相当于给作用于对象添加一个属性名为变量名,属性值为undefined的属性。
上面这一段仅仅是我个人的理解,网上有篇博文描写的很准确
当进入执行上下文(代码执行之前)时,VO(变量对象)里已经包含了下列属性:
函数的所有形参(如果我们是在函数执行上下文中)
— 由名称和对应值组成的一个变量对象的属性被创建;没有传递对应参数的话,那么由名称和undefined值组成的一种变量对象的属性也将被创建。
所有函数声明(FunctionDeclaration, FD)
— 由名称和对应值(函数对象(function-object))组成一个变量对象的属性被创建;如果变量对象已经存在相同名称的属性,则完全替换这个属性。
所有变量声明(var, VariableDeclaration)
— 由名称和对应值(undefined)组成一个变量对象的属性被创建;如果变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性。
我觉得有个例子能用来考察是否真正理解了变量提升
var a = 1; function b() { a = 10; return; function a() {} } b(); alert(a);
结果输出:1
变量和函数声明的函数名相同时,谁的优先级会更高
我是一个搬运工-–-答案是看情况:
同样是一个 x 标识
如果在进行函数 function x() {}; 声明的同时,只声明 var x; 而不对 x 进行赋值操作,那么此时函数声明优先级更高,函数声明会覆盖掉变量声明
如果在进行函数 function x() {}; 声明的同时,不仅声明 var x; 而且同时还对 x 进行赋值操作,即 var x = 1;,那么此时,变量声明会被 保存 ,不会被覆盖。变量声明的优先级更高, 会覆盖掉函数声明。只有当函数声明及对函数的操作出现在变量声明之前时,函数声明才不会被覆盖。
function a() {} console.log(a); //function a() {} var a; console.log(a); //function a() {}
function a() {} console.log(a); //function a() {} var a = 1; console.log(a); // 1
var a = 1; function a() {} console.log(a); // 1
看完代码上面的解释,相信以上三段代码大家都能得出正确的输出结果。
回到之前的面试题,第三个和第二个是同一个考点。这里就不再赘述了。
最后说一下开始的JS面试题的结果:2411233
参考文献
函数声明 VS 函数表达式https://changxiupeng.github.io/2016/10/29/%E5%87%BD%E6%95%B0%E5%A3%B0%E6%98%8E%E5%92%8C%E5%87%BD%E6%95%B0%E8%A1%A8%E8%BE%BE%E5%BC%8F/Javascript作用域和变量提升https://segmentfault.com/a/1190000003114255
js闭包http://www.cnblogs.com/zhjjNo1/archive/2011/02/12/1951905.html
相关文章推荐
- Javascript高级程序设计——函数声明与函数表达式的区别
- 函数声明,函数表达式,块级作用域小结
- 函数声明和函数表达式
- 函数声明和函数表达式区别
- 函数声明与函数表达式的区别
- 深入理解函数声明和函数表达式(转)
- JavaScript的函数声明与函数表达式的区别
- 函数声明和函数表达式
- 函数声明和函数表达式的理解
- 函数声明与函数表达式
- 函数声明和函数表达式
- 函数声明与函数表达式的区别
- 函数声明和函数表达式的(区别)应用场景注意事项
- 函数声明与函数表达式、变量提升
- 函数声明与函数表达式
- 函数声明与函数表达式的提升剖析
- 函数声明和函数表达式
- 函数声明与函数表达式
- 深入理解函数声明与函数表达式
- 函数声明与函数表达式