2018春节后前端面试小记

写在前面

    唉,我仍是前端小渣渣一个。javascript

最近一次的面试:

是一家云服务产品公司,面试流程也比较简单,前端负责人拿了一块白板和记号笔,心想一会要手写代码了。。。。前端

不过这种面试方式仍是不错的。java

去以前觉得本身准备的差很少,其实准备的远远不够充足啊。react

关于自我介绍

一开始通常会让你进行一个简单的自我介绍,我就主要说了一下上家公司的工做经历,描述了一下我负责过的项目,每一个项目的业务功能,主要详细介绍每一个项目用到的技术。面试

虽然我说了不少,可是过后以为我在表达的时候,语言的条理性、逻辑性、准确性都不是很好,表达能力的强弱也是面试官比较看中的一部分,毕竟有可能之后和他共事交流工做内容,探讨技术等,因此,自我介绍这一块,以为也挺重要的,自我介绍表明了面试官对你的第一印象,即使你面试不少次了,也说过不少次了,这方面仍是应该好好梳理下本身的语言。redux


接下来考察js了,面试官慢慢的拿起了他的小白板,个人内心默默的有点小紧张。。。。数组

考察方式也比较中规中矩,按照js里的大类挨个考察。bash

  • 首先是函数方面

for (var i = 0; i < 5; i++) { 

 setTimeout(function() {  

  console.log(i);  

}, 1000); 

}复制代码

“咦?。。。,上一次的面试不是也碰到了这个?”闭包

而后我淡定的说出了答案:框架

setTimeout函数会延迟执行,那么等到执行console.log()的时候,i已经变成5了,因此最后会一次性打印出5个5;”

问:“那我要输出0~4呢?”

“怎么也有这个问题?是否是要问我有几种改法。。。”

我直接说var 改为let就能够了

for (let i = 0; i < 5; i++) { 

 setTimeout(function() {  

  console.log(i); 

  }, 1000);

 }复制代码

或者加个闭包:

for (var i = 0; i < 5; i++) { 

 (function(i) {

setTimeout(function() {  

  console.log(i); 

 }, 1000); 

 })(i)

}

复制代码

或者这样:

for(var i = 1;i < 5;i++){  

  var a = function(){  

      var j = i;    

    setTimeout(function(){  

          console.log(j);  

      },1000)  
  }  
  
a();

}复制代码

这也是用了闭包的方法,其实就至关于把var化成了let效果同样,这样i的值一开始不会被默认绑定,每执行一次循环的时候都会给i赋予新值。


问:“若是去掉function里的 i呢?”

“这样其实对内存没有保持引用, i 最后仍是5。”


因为相似的面试题频繁遇到,整理了一些相关的面试题:

好比这个:

for (var i = 0; i < 5; i++) { 

 setTimeout((function(i) { 

   console.log(i); 

 })(i), i * 1000);
}复制代码

延时函数的第一个参数变成了一个当即执行函数,在这里应该是一个undefined,等价于:

setTimeout( undefined, … );

当即函数会立马执行,因此是立马就输出0~4;

Promise考察:

setTimeout(function() { 

 console.log(1)}, 0);

new Promise(function executor(resolve) { 

 console.log(2);  

for( var i=0 ; i<10000 ; i++ ) { 

   i == 9999 && resolve(); 

 } 
 console.log(3);

}).then(function() {  

console.log(4);

});

console.log(5);复制代码

考察运行机制,首先Promise是异步的,Promise只有三中状态,pending、fulfilled(成功)、rejected(失败),后二者统称为resolve(已定型),一旦状态定下句就没法再改变。

第一个延时函数首先会设置一个定时,在定时结束后传递这个函数将它放到任务队列中去,所以一开始不会输出1;

Promise里的函数会按顺序执行,输出2 3 ,Promise里的then就是会异步执行,放到当前Promise任务队列的最后执行,而console.log(5)是按顺序执行的,因此先输出5,再输出4。Promise.then()里面的回调属于 microtask, 会在当前 Event Loop 的最后执行, 而 SetTimeout 内的回调属于 macrotask, 会在下一个 Event Loop 中执行

最后,才会输出1。

最后输出: 2 3 5 4 1

  • 对象考察

先来个最简单的

var obj = {
  a: "1"
};

var obj2 = obj;

obj2.a = "2";

console.log(obj.a);复制代码

“确定是输出 2 啊”

ojb2只是对obj实例的一个引用,到最后仍是修改的obj的值。


this指针

name = "name of window";  

    function show() {   

     var name = "name in function show()";  

      alert(this.name);   
 }  

  show();复制代码

这里定义了一个全局变量 name ,这个变量是属于 window 的,在 show 函数里也声明了一个name 变量。

this 的定义是指向调用当前函数的那个对象, show() 函数是在全局被调用的,因此this 应该指向的是当前 window对象。

再看下一个:

var myObj = {   

     name: " my Object",

        show: function() {    

        var name = "my Object in function";  
 
         alert(this.name);  
      },  
  };   
 myObj.show();复制代码

此次,调用 myObj.show() 的对象是 myObj, 因此就会输出  my Object

  • 数组Array

先来个排序吧:

var arr = [ 2, 4, 50, 20, 3 ];复制代码

冒泡排序:

var arr = [ 2, 4, 50, 20, 3 ];

for(var i = 0 ; i < arr.length-1; i ++){

    for(var j = 0; j < arr.length-i; j++ ){

        var ls;

        if(arr[j] > arr[j+1]){

            ls = arr[j];

            arr[j] = arr[j+1]

            arr[j+1] = ls

        }
    }
}

console.log(arr);复制代码

其实我要开始想到的是用sort() ,可是sort排出来的不是很稳定,他默认排序是根据字符串Unicode码点。

还问我sort有几个参数,第二个参数是什么?

我当时没想起来,后续整理出来吧!

可选参数是一个比较函数, compareFunction ,用来指定按某种顺序进行排列的函数。若是省略,元素按照转换为的字符串的各个字符的Unicode位点进行排序。

  • 若是 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 以前;
  • 若是 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变;
  • 若是 compareFunction(a, b) 大于 0 , b 会被排列到 a 以前。
  • compareFunction(a, b) 必须老是对相同的输入返回相同的比较结果,不然排序的结果将是不肯定的。

要比较数字而非字符串,比较函数能够简单的以 a 减 b,以下的函数将会将数组升序排列

function compareNumbers(a, b) {
  return a - b;
}复制代码

因此上边那个排序就能够简单的写成:

var arr = [ 2, 4, 50, 20, 3 ];arr.sort(function (a, b) {

    return a - b;
});

console.log(arr);复制代码

或者更简洁一点:

var arr = [ 2, 4, 50, 20, 3 ];

arr.sort((a, b) => a -b );

console.log(arr);复制代码

又给我改了一下,说怎么用sort 来排序一个对象?

var obj = [
  { name: 'a', value: 21 },
  { name: 'b', value: 37 },
  { name: 'c', value: 45 },
  { name: 'd', value: -12 },
  { name: 'e' }
];复制代码

应该是这样:

obj.sort(function (a, b) {

    return (a.value - b.value);

});复制代码

顺便贴上MDN的详解


零零碎碎的问了很多,其余的记不太清了,都是一些知识性的东西,不罗列了。

而后问了一些react、 redux相关的技术原理,生命周期、单向数据流、虚拟DOM等等。。。

这些我回答的还好,由于工做每天用这个,也比较熟悉,js基础类的一些题回答的不太好,我也知道我js基础不扎实,再者,面试题看少了,虽然这些基础的知识点在工做中用的很少,有的记不清楚的就google了,也不会影响开发进度,可是,即使react 用的再熟练,重中之重的js基础!才是最重要的,框架都是js写的。

反思一下,以前工做中碰到了一些不会的或者生疏不经常使用的技术,google出来答案后直接就用上了,也没有仔细的去研究其中的原理,知其然不知其因此然!

过后也没有总结出来,下次再碰到这个技术点,可能又要google了。。。


不说废话了!

整理一些网上看到的不错的面试题:(转载)

  1. 关于变量声明提高和函数声明提高

alert(a);

a();

var a=3;

function a(){

    alert(10)
}   

alert(a);

a=6;

a();
复制代码

果不其然,我本身看一遍的时候就分析错了。

关键的一点就是:var 声明的变量 和function生命的函数都会提早,只是提早到做用域开始的位置,但不会进行赋值操做;

1.函数声明优先于变量声明,因此,刚开始,a就是 function a(){alert(10)} ,就会看到这个函数。
2. a(),执行函数,就是出现 alert(10)
3.执行了 var a=3; 因此 alert(a)就是显示 3
4.因为 a不是一个函数了,因此往下在执行到 a()的时候, 报错。 

再来看:

alert(a);

a();

var a=3;

var a=function(){

    alert(10)
}   
alert(a);

a=6;

a();
复制代码

区别是,函数此次用var声明了,根据原理,他只是声明被提早,但a 没有被赋值为一个函数,

因此,一开始alert(a) 是undefined;

a() 报错;

相似的题目:

var a=0;

function aa(){

    alert(a);

    var a=3;
}

 aa();复制代码

在aa函数里面,有var a=3,那么在aa做用域里面,就是把a这个变量声明提早,可是不会赋值,因此是undefined

var a=0;

function aa(a){ 
 
    alert(a); 
 
    var a=3; 

};

aa(5);

alert(a);

//5,0   复制代码

在函数体内,参数a的优先级高于变量a ;

var a=0;

function aa(a){

    alert(a);

    a=3;

    alert(a);

}
aa();

alert(a);
复制代码

首先没有传参数进去,aa() undefined

a=3,实际上修改的是形参a的值,并非全局变量a,往下alert(a)也是形参a;

最后的alert(a); 是全局的a;


写在最后

不说了!。。。

我要去刷面试题,继续啃个人JavaScript 语言精粹了。

相关文章
相关标签/搜索