面试题总结

106 阅读11分钟
原由

最近要毕业了,在找工作,也面试了四五家公司,有一些题目能够很好的答出来,更多的题目都是知道有那么个东西,但是一细究,就发现知识点很空白了,借着这个机会,想给自己定个目标,适时总结,坚持总结。因为以前有很多时候都是这个知识点不会,然后弄了很久,会了,但是过了一个月左右,这个知识点就忘记了,再次去理解这个知识点又花了很多时间,做了很多无用功,在某篇文章中看到是因为自己没有适时总结记忆的缘故。关于平台的选取,本来想用博客园的,它的活跃量太低了,然后发现掘金这个平台也蛮不错的,一翻文章,发现都是大佬级别的人物,em......,那我这个小菜鸟也跟着在这里分享自己一些总结和经历吧,同时也希望可以交到一些志同道合的朋友 ~ ~

本地记录

这回是第一篇文章,算是初体验吧,不怎么会排版,将就一下 == , 因为面试了四五家公司,出题的方向都不一样,有的重视编程,有的重视基础,那我就一一做一个总结吧。

某焕 (笔试部分)

某焕

1、Array(3).join()输出的结果是什么?
2、++"51".split("")[0]输出的结果是什么?
3、apply和call是什么,有什么不一样?  (这个问题基本上是每个公司都问了==)
4、Vue中计算属性和方法的区别?分别说出它们的应用场景。
5、实现一个函数sum, 使得能实现如下功能:
sum(1, 2)  //3
sum(1, 2, null)   //3
sum(1, true, true, 2, false)   //5
sum("1", 2, 3, "A", "B", 6)   //11
sum(0.1, 0.2) //0.3 而不是0.30000000000000004
6、实现一个函数:随机生成10~100的数字,一共十个,并对其进行排序,
解答一波:
1、 当时直接写的不知道== ,现在也不知道。 我先运行一下---,主要是这个Array(3)给我整的有点懵......,
好了,现在解释一下: 答案是 ",," 
原因:Array(3) 其实就是 new Array(3),创建了一个数组,长度为3,但是数组项都为空, 即[ <3 empty slots> ],如求Array(3)[0]的值,则为undefined。然后调用数组的转换方法 join()。
该方法是作为toString()方法的一个补充,数组调用toString()方法会分别调用每一项的toString()方法,然后以分隔符逗号连接。使用join方法则可以使用其它字符连接了,
它若不指定参数也以逗号为分隔符,所以即为",,"
知识补充:
数组有两种创建方式 : ①  构造函数 ② 字面量形式
① 使用Array构造函数 , 如 let arr = new Array() ;其中,new可省略(== 这个是关键!,细节...);可传递参数
② 使用字面量表示法。 多个数组项以逗号分隔开。 如 let arr = [1, 2, 3, 4]
第二题:
这次被我猜对了,但是还是有疑惑,就是这个++和后边的执行顺序问题。
首先答案是 6;
然后分析一下:
em......现在知道了,++"51"这样子是不能执行的,会报错 Uncaught SyntaxError: Invalid left-hand side expression in prefix operation;
而且在js中,圆括号的优先级最高,其次就是(成员访问,函数调用,排名不分先后)了,++优先级在后边呢。例如 ++"51"*2 就会报一样的错误,因为 () > 成员访问和函数调用 > ++和-- > +-*/的
另外还有一个js中字符串的相关方法的问题,老是把字符串和数组的方法搞混 == ,难道真的是我错了吗~~
记录一下字符串的相关方法:
为啥老是不记得string的方法呢,原来是: 为了便于操作基本类型值,js提供了三个特殊的引用类型,Boolean、Number和String。这些类型和Object、Array,Date,RegExp,Function类似,但是又有特殊行为。 
实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据。(因为基本类型值不是对象,讲道理它们不该有方法)。
例如: 
var s1 = "some text";
var s2 = s1.substring(2);
s1本来是基本类型值,但是后来的代码却调用了substring()方法。
解析: 第一行确实是基本类型值,但是第二行却不是了,因为后台进行了一系列的处理。第二行中,对一个基本类型值进行了读取,所以后台就会自动完成一系列动作: 
① var s1 = new String(""some text)
② var s2 = s1.substring(2)
③ s1 = null
最后的最后,s2它也是基本值类型,一切都神不知鬼不觉。

那这三种基本包装类型和其它引用类型有啥区别呢?
!主要区别就是对象的生存期。
使用new操作符创建的引用类型的实例,在执行流离开当前作用域前都一直保存在内存中。。而自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁。


下面这个可以加深下理解: (很多都是书上的知识)
typeof "haha"    //string
typeof new String("haha")   // Object
。顺便在这里记录一下这个特殊的引用类型之一的String的一些相关方法: 
感觉有点多。但还是知道一下的好。
假设  let str = "aello world"
首先是 
①长度属性: str.length     //11
字符串是不可变的,它的长度赋其它值也没啥用,这点和数组不同。

然后是关于对字符串的解析和操作了
② 字符方法
访问其中特定字符的方法: charAt()、charCodeAt()
str.charAt(0)   //a
str.charCodeAt(0) //97  这个是访问字符的编码

也ES5中也定义了一个方法访问字符 str[0] ,通过方括号表示法来访问,和数组一样,这个方法和上边的str.charAt(0)作用一样

③ 字符串操作方法
如要要拼接字符串,concat()由此被设计,可以有一个或者多个参数。和数组的concat方法使用方式一样的 ==
var str = "hello"
var result = str.concat("xixi") //"helloxixi"
实践中 基本上是用 + (加号操作符),这个更直观也更方便。

如果是要基于字符串而创建新的字符串的话。有三个方法
slice()、substr()、substring()
都有两参数 ,第一个是开始位置,第二个则不同(可选参数): slice和substring都是f(?start,?end), substr是 f(?from,?length)。不选默认把后边的都选中
这里的参数正负值不同,处理的形式也不一样== 
负值用的少,那就不记了,等用到了再查吧。
1)假如是正数的话, slice和substring的效果是一摸一样的,都是从strart 到 end。 substr的话就是起始位置和长度。  用slice()和substring()在一般的情况下完全可以代替substr()了
这里就不讨论 substr了,它好像并没有进入到ECMA的标准。 (其实是怕自己搞混了)
2)负数的情况。
let str = "woshiniya"   //length为9
str.slice(-1)则相当于str.slice(-1 + length),就是str.slice(8)   // "a"
所以可以记忆 -1 就返回最后的一个数,-2就是最后两个数。
str.slice(1, -1) 则是相当于start为1, end为-1,-1就是最后的那个位置了,其实这里是str.slice(1,8),但是我们自己其实可以省略掉这一步思考,直接认为str.slice(1,-1)就是 从角标1的位置到最后一个元素为止。

至于substring的话,它是无视参数顺序的,会自动将小的放在前面,大的放在后边,不支持负数,它会将负数直接变为0。
str.substring(1, -1)  其实就是str.substring(1, 0),也就是str.substring(0, 1)   //w

另外,注意一下在数组中也有concat方法,在数组中有slice方法和splice方法,没有substr和substring方法不要搞混了。

③ 字符串位置方法
indexOf()和lastIndexOf()这两个,接收的参数形式为 f(?searchElement, ?fromIndex)。没找到则返回-1 ,找到了返回对应下标。

注意,这两个方法和数组的位置方法是一样的。
④ trim()方法 -- 删除空格
ES5 中定义了 trim()方法,它创建一个副本,删除前置和后置所有所有空格。
还有两个非标准的方法(谷歌,火狐,Safari等实现了):
trimLeft()   ----> 删除左边的空格
trimRight() ----> 删除右边的空格

⑤字符串大小写
有四个,toLowerCase()、toLocaleLowerCase()、toupperCase()、tolocaleUpperCase(),顾名思义,就不多说了。

⑥ 字符串的模式匹配方法。
涉及到正则表达式了,em...挖坑+1,下次填上 == 
......

⑦localCompare()方法
与操作字符串有关的最后一个方法
str1.localCompare(str2)   如果返回负数(一般是-1) ,则str1排在str2前面,以此类推返回0和正数。

⑧fromcharCode()方法
这是String构造函数本身的静态方法,所以,也能猜到它的用意了。
它接收一个或多个字符编码,然后将它们转换成一个字符串。 和实例方法charCodeAt()相反。

⑨ HTML方法
基本是没用过...略
第三题:
这个题也是知道的。会使用,原理代码能看懂。但是自己手写不了......
这里答的是  这两个方式是一样的,都是改变this的绑定,但是传入的第二个参数不一样,apply是以数组形式传递的,call是以逗号分隔的参数形式传递的。
后边其实有个其它公司的面试官问我能不能手写,这个后边再提吧。。挖坑+2
第四题:
这个问题遇到的也很多。
我答的是 computed属性是可以缓存数据,仅当数据变化的时候,Vue才会重新去计算。
而方法则是每次访问数据,Vue就会去调用方法,这样子对性能不好。在数据不怎么变的时候,要多用computed属性。
具体应用场景我还真想不出来。。

官方文档中说的是 计算属性是基于它们的响应式依赖进行缓存的,只有在相关相应式依赖发生变化时,才会重新求值。 
( 其实就是重新渲染的话,计算属性也会被调用,但是里面的代码不会被执行。)而方法则是: 每当触发重新渲染时,调用方法将总会再次执行函数。

有个疑问...什么情况下触发重新渲染呢,是怎么触发的呢。。不知道  --挖坑+3
第五题:这个函数的实现写倒是写了,是用的typeof,但是当时对于typeof各种结果都不能肯定。typeof null,typeof false,会输出个啥,都忘了。
先复习一下typeof各种吧。(明天再写,深夜有点晚了,睡觉去。)

第二天了... 接着写
typeof "number","boolean","string"  会输出各自对应的。
typeof null, "对象"  会输出 "object"。  //实例就是对象了
typeof undefined  会输出 "undefined"
typeod 函数   会输出  "function"  // 构造函数也是函数。
实现代码:
function sum(...rest){
    rest.forEach( (item,index,array)  => {
        if(typeof item === "object" || item === false || typeof item === "string"){
            array[index] = 0
        }
        if(item === true){
            array[index] = 1
        }
    })
    let result = rest.reduce(function(pre, cur, index, array){
        return (pre * 1000 + cur * 1000) / 1000   //因为小数不准确,所以先转换为整数,然后再用除法,这样子就不会丧失精度了。这个也只能在一定范围内适用。 
        //当时用的是  .toFixed(1)方法,这样子其实会四舍五入,损失精度。
        //另外如果要判断两数是否相等,可以用Number.epsilon值。 Math.abs(0.3-(0.1+0.2)) < Number.EPSILON
        
    })
    return result
}

第六题:
当时random方法都忘记了...
答案:
function createRandomData(){
    let arr = []
    for(let i = 0; i < 10; i++){
        let num = Math.ceil(Math.random() * 90 +10)
        arr.push(num)
    }
    arr.sort()
    return arr
}
//上边这样子其实生成0的概率基本为0......可以改一下
        let num = Math.round(Math.random() * 90) +10
        这样子的话,几率就差不多了。
//因为会生成100,所以传入一个比较函数也是必要的。下面就是改正后的答案:

function createRandomData(){
    let arr = []
    for(let i = 0; i < 10; i++){
        let num = Math.round(Math.random() * 90) +10
        arr.push(num)
    }
    arr.sort(function(item1, item2){
        if(item1 < item2) return -1
        else if(item1 == item2) return 0
        else return 1
    })
    return arr
}
写在最后

笔试后边还有两道算法题,没做了。 然后面试问了挺多项目上的问题--- 我确实不咋知道,让回家等通知。本来听着面试官语气感觉是有戏。 然后,就被拒了。应该是又有人来面试,然后被刷下去了。

第一篇文章,后边有很多是想到哪补充到哪----,花了好久的时间写这个,以至于我都忘记多少时间了 ==

后边接着写。