[转]谈谈我遇到的前端的一些神奇面试题--变量提升,函数提升
2015-01-21 09:08
405 查看
感谢大家批注指正,我不想误导大家,我只是说我遇到过类似的题目,然后这里分析分析这些题目,并没有说我们平时要这样去写代码。js这门语言很灵活,有很多奇葩(坑),如果你不知道,哪天你无意间调到坑里去了你还不知道,有经验的人应该都踩过无数js的坑。
去面试的时候有一些公司会给出面试题叫你做,前端的话一般有输出结果的题,叫你写出题目的输出结果。我遇到过几次,可是每次都感觉自己迷迷糊糊的,现在看来还是自己基础不够好导致了的。闲来没事,总结总结,大神们,莫拍砖,我只是个前端小菜鸟。
先来看一组题目,如果你们全部答对,那直接看最底部的一题。
以上题目考的知识点相对单一,无非就是预编译和作用域,还没牵扯太多东西。
研究以上题目我总结几点
js对:var 后面的变量、函数参数、函数进行预编译
来看看一些测试例子
以上代码约等于
再看以下代码,script标签
感觉以上代码输出正在,第二个script标签里面的a 是string类型,是第一个script标签先预编译。第二个<script>标签里的a但会往上查找。
在看下面这个
第一个script标签里的a,undefined,直接输出啊,立马报错。因为在第一个script标签的时候没有发现a声明过,没声明直接使用就会报错。 第二个script标签里面的输出是我们预料之中的
得出一个结论:js的预编译,是从有顺序的,根据script标签的顺序从上到下执行的
第一个输出的是function a(){},为什么会是这样!! 我感觉是先预编译变量,先给a赋值undefined,后来预编译函数,函数a覆盖了之前的变量a的默认值; 然后代码顺序执行到a=1;,这个时候赋值表达式给a赋值为1,所以后面输出都是1。
上面一种情况比较好理解,下面这种情况比较容易让人混淆。
函数有两个参数a和b,内部有声明了啊。调用fn的时候传入了一个字符串。 看看内部的输出,显示输出:容易上当,再是输出10。这是为啥呢
预编译阶段会预编译,var后面的变量,函数参数、函数。调用fn的时候传入的参数a,b。 a和b会预编译赋值undefined,调用发你,传入'容易上当',a就被赋值为容易上当了。函数里面变量a的默认值就是参数a的值了,开始输出a,也就是参数a值。后来遇到赋值表达式a=10,此时a就变成10了。
看下面这段代码就想对简单了
fn里面有参数a,也有变量a,也有函数a,这种迷惑性更高。其实当你知道三者先后顺序之后就不迷惑了
经过测试,我发现:参数a会覆盖预编译变量a的默认值,如果有函数,函数会覆盖参数a的值,这个就是先后顺序而已。
函数形参声明--->函数声明---->变量声明
来看一个综合一点的,找找感觉
在看这个,也是一个容易坑人的题目
看起劲了,收不到了,再来一个
说了这么多,其实就是围绕着js预编译函数,var 声明的变量就是显示声明的,会有变量提示、函数参数,搞懂先后顺序,以后遇到类似的题目基本都是没问题。
还有很多很多关于输出结果的,基本围绕着js的预编译,作用域,函数上下文对象,以及这门语言的一些特性来展开的。多看看《Javascript语言精髓与编程实践》 《Javascript高级程序设计第三版》加强基础,题目万变不离其中,都是考那些知识点。
接受大家的批评,我是菜鸟,不想误人子弟。在一个作用域内变量的声明顺序,函数形参声明--->函数声明---->变量声明 声明是有先后顺序的。任何一种声明,如果在前面出现,都不会再次声明。
再来一个 高级的,很多人都见过,但是我估计第一次能够全部答对的人应该很少,即使答对,但是全部知道为什么的更少!
本文地址http://www.cnblogs.com/Bond/p/4218639.html
去面试的时候有一些公司会给出面试题叫你做,前端的话一般有输出结果的题,叫你写出题目的输出结果。我遇到过几次,可是每次都感觉自己迷迷糊糊的,现在看来还是自己基础不够好导致了的。闲来没事,总结总结,大神们,莫拍砖,我只是个前端小菜鸟。
先来看一组题目,如果你们全部答对,那直接看最底部的一题。
//1、------------------------------------------------------------------------------------- a() var a = c = function() { console.log(2) } a() function a() { console.log(1) } a(); (function(b) { b(), c() var b = c = function a() { console.log(3) } b() })(a) c() //2、------------------------------------------------------------------------------------- var A = function() {} A.prototype.n = 1; var b = new A() A.prototype = { n: 2, m: 3 } var c = new A() console.log(b.n, b.m, c.n, c.m) //3、------------------------------------------------------------------------------------- (function f() { function f() { return 1; } return f(); function f() { return 2; } })(); //4、------------------------------------------------------------------------------------- if (!(a in window)) { var a = 1; } console.log(a) //5、------------------------------------------------------------------------------------- function a() {} var a; console.log(typeof a) //6、------------------------------------------------------------------------------------- (function(b) { console.log(b) var b = c = 2 console.log(b) })(1) //7、------------------------------------------------------------------------------------- (function(b) { console.log(b) var b = c = 2 console.log(b) function b() {} console.log(b) })(1) //8、------------------------------------------------------------------------------------- var a = 10; function fn() { console.log(1) var a = 100; console.log(a) } fn(); //9、------------------------------------------------------------------------------------- var a = 1 function c(a, b) { console.log(a) a = 2 console.log(a) } c()
以上题目考的知识点相对单一,无非就是预编译和作用域,还没牵扯太多东西。
研究以上题目我总结几点
js对:var 后面的变量、函数参数、函数进行预编译
来看看一些测试例子
只是var声明的变量相关
var 声明的变量a,就是显示声明的, 被预解析,赋值为undefined,既是常说变量提升。你在一个作用域任何一个地方声明变量,都会被提升到作用域开始(接受意见意见加上)。console.log(a)//undefined var a=1; console.log(a)//1
以上代码约等于
var a = undefined console.log(a) //undefined a = 1; console.log(a) //1
再看以下代码,script标签
<script> console.log(typeof a)//undefined var a='littlebear'; console.log(a)//littlebear </script> <script> console.log(typeof a)//string var a=1; console.log(a)//1 </script>
感觉以上代码输出正在,第二个script标签里面的a 是string类型,是第一个script标签先预编译。第二个<script>标签里的a但会往上查找。
在看下面这个
<script> console.log(typeof a)//undefined console.log(a)//报错,遇到<script>标签对时,会先对这一块进行预解析,下面没预解析,所以找不到声明过的a,于是报错了 </script> <script> console.log(typeof a)//undefined var a=1; console.log(a)//1 </script>
第一个script标签里的a,undefined,直接输出啊,立马报错。因为在第一个script标签的时候没有发现a声明过,没声明直接使用就会报错。 第二个script标签里面的输出是我们预料之中的
得出一个结论:js的预编译,是从有顺序的,根据script标签的顺序从上到下执行的
var声明的变量和函数在一起的时候
<script> console.log(a)//function a(){} var a=1; console.log(a)//1 function a(){} console.log(a)//1 </script>
第一个输出的是function a(){},为什么会是这样!! 我感觉是先预编译变量,先给a赋值undefined,后来预编译函数,函数a覆盖了之前的变量a的默认值; 然后代码顺序执行到a=1;,这个时候赋值表达式给a赋值为1,所以后面输出都是1。
var 声明的变量和函数参数在一起的时候
<script> var a=10; function fn(a,b){ console.log(a)//undefined a会预编译,此时输出a,当前作用域能够找到a,值是undefined。 所以不会向外搜索,也就不会是外部的10 var a=10; console.log(a)//10 } fn(); </script>
上面一种情况比较好理解,下面这种情况比较容易让人混淆。
<script> function fn(a,b){ console.log(a)//容易上当 var a=10; console.log(a)//10 } fn('容易上当'); </script>
函数有两个参数a和b,内部有声明了啊。调用fn的时候传入了一个字符串。 看看内部的输出,显示输出:容易上当,再是输出10。这是为啥呢
预编译阶段会预编译,var后面的变量,函数参数、函数。调用fn的时候传入的参数a,b。 a和b会预编译赋值undefined,调用发你,传入'容易上当',a就被赋值为容易上当了。函数里面变量a的默认值就是参数a的值了,开始输出a,也就是参数a值。后来遇到赋值表达式a=10,此时a就变成10了。
看下面这段代码就想对简单了
<script> var a=10; function fn(a,b){ console.log(a)//undefined 这里不是10哟。 当前作用域能够找到a的 a=10; console.log(a)//10 } fn(); </script>
函数,函数参数,var声明的变量在一起的时候
<script> var a=10; function fn(a,b){ console.log(a)//function a(){} 这里输出function a(){}, 不是参数a的值,哈哈 var a=10; console.log(a)//10 function a(){} console.log(a)//10 } fn(15); </script>
fn里面有参数a,也有变量a,也有函数a,这种迷惑性更高。其实当你知道三者先后顺序之后就不迷惑了
经过测试,我发现:参数a会覆盖预编译变量a的默认值,如果有函数,函数会覆盖参数a的值,这个就是先后顺序而已。
函数形参声明--->函数声明---->变量声明
来看一个综合一点的,找找感觉
<script> a();//1 var a = c = function() { console.log(2) }; a();//2 function a() { console.log(1) } a();//2 (function(b) { b();//2 其实就是外部的a c();//2 c为什么是2? 也许有人以为这里会报错,其实不会。 原因就在于var b=c=xxx。 c相当于没有加var 不会预编译,这里c直接查找到外部作用域的c var b = c = function a() { console.log(3) } b()//3 })(a);//走到这里 a已经被赋值表达式重新赋值 c();//3 由于没加var 的原因 c已经被立即执行函数内部的赋值表达式改变了值 这里是3 </script>
return 和函数、var声明的变量在一起的时候
由于预编译,后面的a覆盖了前面的a,所以return a的值 其实就是预编译之后a的值,预编译之后a的值就是第二个a。<script> function fn(){ function a(){console.log(1)} return a; function a(){console.log(2)} } fn()();//2 </script>
在看这个,也是一个容易坑人的题目
<script> var a=10; function fn(){ //预编译a 赋值undefined,内部作用域存在a这个变量,所以这里 !a 就是 !undefined,就是true,进入函数a=20; //但是后面的a怎么就是20呢,js没有块级作用域!! 不要小看js各种细节,够折腾的 if (!a) { var a=20 } console.log(a)// 这里是20 , } fn() </script>
看起劲了,收不到了,再来一个
<script> //a in window ==>true 、 !true ===》false if (!(a in window)) { var a = 1; } console.log(a)// undefined </script>
说了这么多,其实就是围绕着js预编译函数,var 声明的变量就是显示声明的,会有变量提示、函数参数,搞懂先后顺序,以后遇到类似的题目基本都是没问题。
还有很多很多关于输出结果的,基本围绕着js的预编译,作用域,函数上下文对象,以及这门语言的一些特性来展开的。多看看《Javascript语言精髓与编程实践》 《Javascript高级程序设计第三版》加强基础,题目万变不离其中,都是考那些知识点。
接受大家的批评,我是菜鸟,不想误人子弟。在一个作用域内变量的声明顺序,函数形参声明--->函数声明---->变量声明 声明是有先后顺序的。任何一种声明,如果在前面出现,都不会再次声明。
再来一个 高级的,很多人都见过,但是我估计第一次能够全部答对的人应该很少,即使答对,但是全部知道为什么的更少!
<script> var a = 10; var foo = { a: 20, bar: function () { var a = 30; return this.a; } }; console.log( foo.bar(), // 1. (foo.bar)(), // 2. (foo.bar = foo.bar)(), // 3. (foo.bar, foo.bar)() // 4. ); </script>
本文地址http://www.cnblogs.com/Bond/p/4218639.html
相关文章推荐
- 谈谈我遇到的前端的一些神奇面试题
- 前端一道面试题,考察变量定义提升、this指针指向、运算符优先级、原型、继承、全局变量污染、对象属性及原型属性优先级
- 整理一些最近经常遇到的前端面试题
- JS变量提升问题(及一些作用域面试题)
- 前端面试题(变量提升)
- 前端经常遇到的一些面试题
- 我在面试过程中遇到一些面试题汇总
- 一到关于js函数的前端面试题引发的血案
- 谈谈关于个人提升的一些思考
- 前端开发学习三——Javascript基础,变量提升(hosting)
- 前端小技巧(持续更新,一些遇到问题的解决方案)
- 介绍一些PHP判断变量的函数
- 介绍一些PHP判断变量的函数
- 自己遇到的一些面试题总结(2)
- 一个讨论引发关于js中函数声明,函数表达式,形参与变量声明赋值引发的一些事(http://www.cnblogs.com/zhouyongtao/archive/2012/11/22/2783089)
- x264中open_file_yuv函数欣赏(顺便谈谈如何利用指针在被调函数中改变主调函数中变量的值)
- 曾经遇到的一个面试题,快速排序用链表实现,算法和以前的相似,需要注意一些细节处理
- 谈谈关于个人提升的一些思考
- 自己遇到的一些面试题总结 (1)
- 阿里巴巴前端面试parseInt()函数的面试题