谈谈我遇到的前端的一些神奇面试题

感谢大家批注指正,我不想误导大家,我只是说我遇到过类似的题目,然后这里分析分析这些题目,并没有说我们平时要这样去写代码。js这门语言很灵活,有很多奇葩(坑),如果你不知道,哪天你无意间调到坑里去了你还不知道,有经验的人应该都踩过无数js的坑。

去面试的时候有一些公司会给出面试题叫你做,前端的话一般有输出结果的题,叫你写出题目的输出结果。我遇到过几次,可是每次都感觉自己迷迷糊糊的,现在看来还是自己基础不够好导致了的。闲来没事,总结总结,大神们,莫拍砖,我只是个前端小菜鸟。

先来看一组题目,如果你们全部答对,那直接看最底部的一题。

//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>
分类:产品 时间:2014-01-07 人气:4
本文关键词: 网页设计
分享到:

相关文章

iOS 开发

Android 开发

Python 开发

JAVA 开发

开发语言

PHP 开发

Ruby 开发

搜索

前端开发

数据库

开发工具

开放平台

Javascript 开发

.NET 开发

云计算

服务器

Copyright (C) codeweblog.com, All Rights Reserved.

CodeWeblog.com 版权所有 闽ICP备15018612号

processed in 0.031 (s). 10 q(s)