• 崽崽   2014/7/22 19:14:00
  • 面试JavaScript时需要注意的一些细节
  • 关键字: 面试 UI 前台
  •  

    常常让我们阴沟里翻船的基础知识

    之前总结的都是一些知识面的,会就是会,不会也答不出来,但在JavaScript笔试过程中经常会遇到一些自己觉得明明很简单,但答案却让人莫名其妙的问题,更有一些题目都会让人目瞪口呆的问题,在笔试过程中出错的几乎都是这类问题。你肯定见过这样的题目

    1
    2
    var f = function g(){ return 23; };
    typeof g();//g is not defined

    或者这样的题目

    1
    2
    3
    4
    5
    6
    7
    8
    var foo = 1;
    function bar() {
        foo = 10;
        return;
        function foo() {}
    }
    bar();
    console.log(foo);//1

    很多类似的题目,让人头痛的很,答案和自己认为肯定的不一样(后续博客会有相关分析),吃过很多次亏后也尝试在网上找一些JavaScript Quiz来做,每次做的时候被虐的体无完肤,做完之后会觉得自己可以应付笔试了,但在下次笔试的时候又死在类似题目上,痛定思痛把常出错的JavaScript知识点梳理了一下后,正确率果真提高了不少,发现其实都是一些JavaScript基础的语法知识,如果我们在笔试的时候总在JavaScript坑洼沟洄里摔倒而不是知识面上,那么就有必要了解一下这些不起眼的基础知识了,所以正经介绍面试经历的博客我希望以基础知识开始。文中主要内容都是看了《JavaScript权威指南》后了解的,真心推荐找工作的同学耐住性子读读这本好书。

    让我们从JavaScript类型开始

    JavaScript数据类型很简单,有原始类型(primitive type,也就是大家口口相传的值类型)和对象类型(所谓的引用类型)两类
    原始类型

    number、string、boolean、null、undefined

    对象类型

    object、function、Date、Array等

    也许你认为很简单,但如果没系统学习过,简单的数据类型在笔试、面试中也是很凶险的,先了解一下这几个类型的特点

    • string

      在很多编程语言中string类型都是引用类型,JavaScript中的string却是基本类型,在JavaScript中字符串是一组由16位值组成的不可变的有序序列,每个字符通常来自Unicode字符集(《JavaScript权威指南》)。在JavaScript中所有基础类型都不可以修改,这句话对于number等类型好理解,1变不成2,但是string "abc"不是可以变成"abcd"吗?其实所有我们认为修改字符串的方法只是返回了一个新的字符串。

    • number

      和大多数编程语言不同,JavaScript的number类型不区分整数和浮点数,所有数字都适用浮点数表示。

    • bool

      这个比较简单,该类型就是true和false两个值

    • null

      null对程序员来说并不陌生,表示未定义(声明)过的变量

    • undefined

      null表示“空”了,undefined是什么东东?我们知道像Java这样的强类型语言中如果我们声明一个变量而不初始化,系统会根据变量类型为其赋值该类型的默认值,但在JavaScript中我们声明变量靠的是var关键字(甚至可以不写),变量的类型是由其value决定的,为其赋值为数组,那么变量就是数组类型,为其赋值数字,变量就是number,但是如果我们不初始化呢?总不能说变量是null吧,毕竟这个变量已经得到声明,这时候我们就把该变量认为是undefined类型变量,并为其赋值undefined类型唯一值——undefined(不是"undefined")

    包装对象

    我们经常见到一些这样的代码

    1
    2
    3
    var s='test';
    console.log(s.indexOf(e)); //1
    console.log(s.length); //4

    乍一看没什么奇怪的,但是不是说好的string是基本类型吗?基本类型的变量哪里来的方法和属性!暂且放过这个知识点,反正能这么用就是了,看个题

    1
    2
    3
    var s='test';
    s.len=4;
    console.log(s.len);//undefined

    坑爹!怎么不是4又变成undefined了?只要引用了字符串属性,JavaScript就会通过调用 new String(s) 来创建一个临时对象,我们使用的indexOf方法和length属性正是来源于这个临时对象,每次使用都创建一次,然后销毁。这个临时对象就是包装对象,不只是string,number和boolean类型同样有包装对象。知道了这些知识看看上面的题目为什么结果是undefined

    上面代码可以这样解析

    1
    2
    3
    4
    var s='test';//创建字符串类型变量
    s.len=4;//创建包装对象,为包装对象添加属性len
    //引用完毕,销毁包装对象
    console.log(s.len);//创建包装对象,查找其len属性,没有找到,返回undefined
    这下明白了吧

    类型转换

    在笔试题中经常会遇到一些难题解决最后却死在阴沟里的题目,类型转换就经常充当阴沟,看个例子

    1
    2
    var a=[0], b=a, b=[1];
    console.log(a+b);
    我们搞定了数组的问题,最后问题可以变为[0]+[1],一不小心就会写为1,但是这时候我们调用的是数组的toString方法,实际是'0'+'1'='01',这时候就可以看出类型转换知识的重要性了。

    JavaScript的取值类型非常灵活,会根据需要自动转换类型,比如 ``` 1+'234' ``` JavaScript会自动把1转换为期望的字符串"1",这种转换时非常明显的,我们看一些平时可能会弄错的默认转换

    转换为字符串转换为数字转换为布尔值
    undefined"undefined"NaNfalse
    null"null"0false
    true"true"1
    false"false"0
    ""0false
    "2.5"2.5true
    "string"NaNtrue
    0"0"false
    1"1"true
    NaN"NaN"false
    Infinity"Infinity"true
    [2]"2"2true

    显式的类型转换(调用构造函数或者parseInt()函数等)我们很轻松可以发现,但JavaScript很多操作符都能引发隐式的类型转换

    1
    2
    3
    4
    5
    6
    7
    8
    Number("3");//3
    String(false);//false
    Boolean([]);//true
    Object(3);//new Number(3)
    1+"234";//"1234"
    5+"";//String(5)
    +"5";//5,变成了数字 Number("5")
    "5"-0;//5,也是数字

    toString和valueOf

    在一些情况下我们会把对象转换为基本类型,对于转换为布尔值规则很简单,所有的对象都会转换为true,然而我们最常用的是把对象转换为字符串或数字,这就比较麻烦了

    对象转为字符串 对象转换为字符串过程大概是这样 1. 如果对象具有toString方法则调用该方法,如果方法返回的是一个基本类型(有坑爹的toString方法不返回string类型的),JavaScript把这个值转换为字符串返回 2. 如果对象没有toString方法,或者该方法返回的不是一个基本类型,那么就会调用valueOf方法,如果存在valueOf方法并且valueOf返回的是基本类型,那么将值转换为字符串输出 3. 再如果就只能报错了

    对象转为数字 对象转换为数字过程大概是这样 1. 如果对象有valueOf方法,并且方法返回基本类型,则把值转换为数字返回 2. 如果对象具有toString方法,且方法返回基本类型,则转换为数字返回 3. 否则就报错

    上面情况只是针对强制转换,也就是我们显示的调用String或者Number构造函数的时候的处理,在平常使用中,在”显示“相关操作中会优先调用toString方法,而在运算相关操作中会优先调用valueOf方法。

    看个题目

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var o = {
            x: 8,
            valueOf: function(){
                return this.x + 2;
            },
            toString: function(){
                return this.x;
            }
        };
    console.log(String(o));//"8"
    console.log(Number(o)); //10
    console.log(o+1);//11,运算相关
    alert(o);//"8",显现相关

    注意返回的一个是字符串,一个是数字,了解了上面基本知识,你是不是答对了

    判断数据类型

    我们可以使用typeof运算符来判断数据类型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    typeof undefined; //"undefined"
    typeof null; "object"
    typeof true; "boolean"
    typeof 0; //"number"
    typeof NaN; //"number"
    typeof "string"; //"string"
    typeof function(){}; //"function"
    typeof []; //"object"
    typeof new Date(); //"object"
    有几个看起来比较蹊跷需要我们注意

    1. typeof是运算符,不是方法,也就是说和加减号一样用,不考虑优先级问题,没必要给操作数加括号,当然加了也没事儿,说实话可读性还挺高

    2. typeof返回值都是小写字符串

    3. null的类型不是null,而是"object"

    4. NaN这个不是数字的类型也是"number"

    5. function明明也是对象,但是typeof却给了"function"类型

    6. 其它对象都返回"object",很没有识别性

    具体识别对象类型使用instanceof 操作符,这个记住一点儿就行,对于基本类型,instanceof 永远返回false

    1
    2
    1 instanceof Number; //false
    new Number(1) instanceof Number; //true

    最后

    本来就想写一些知识点来阐述一些面试题,越写内容越多,而且发现盘根错节,只好老老实实从最基础的谈起,有了这些基本知识接下来就能小步快跑了,接下来会更新一些“干货”内容,不再是干巴巴的理论知识,不过都得建立在前几篇基础上才行

    • JavaScript面试时候的坑洼沟洄——数据类型

    • JavaScript面试时候的坑洼沟洄——表达式与运算符

    • JavaScript面试时候的坑洼沟洄——逗号、冒号和括号

    • JavaScript面试时候的坑洼沟洄——预解析

    PS. 让人望而生畏的JavaScript认真总结下来无非这些毫不起眼的基础知识,地基打好了,JavaScript的坑洼沟洄就都能够应付自如了。另外一直在寻找Mac上比较好用的博客客户端,感觉都不如Windows live Writer,惊闻博客园支持Markdown语法了,赶紧试试,开始时有些费力,不过熟悉了几个简单的语法后真的好方便。建议没有用过的同学尝试一下