1.前言

对于一个web前端来说,面试的时候,难免会遇到javascript的面试题。就我自己而言。有几道面试题,有些是我面试遇到的,有些是在网上看到的,但是都印象深刻。今天就来简单分析一下我遇到的,印象深刻的一些面试题!主要目的希望能让小伙伴学到一些东西,如过以后遇到类似的情况,就记得不要掉坑了!

2.预解析

预解析:在当前作用域下,js运行之前,会把带有var和function关键字的事先声明,但不会赋值(个人见解)

对预解析印象深刻,并不是因为难,而是要细心,稍微一粗心,答案就写错了!我遇到预解析的题目不止一道,有两道我现在还能记住,我说下!

2-1.预解析1

alert(a)
a();
var a=3;
function a(){
    alert(10)
}   
alert(a)
a=6;
a();  

------------分割线------------------

alert(a)
a();
var a=3;
var a=function(){
    alert(10)
}   
alert(a)
a=6;
a(); 

看到这个代码,当时答错了。后来请教了朋友,然后自己再理解下,就理顺了!
考点其实就两个,第一变量声明提前,第二函数声明优先于变量声明!
下面我简单分析一下,
第一部分运行结果:
1.函数声明优先于变量声明,所以,刚开始,a就是function a(){alert(10)} ,就会看到这个函数。
2.a(),执行函数,就是出现alert(10)
3.执行了var a=3; 所以alert(a)就是显示3
4.由于a不是一个函数了,所以往下在执行到a()的时候, 报错。
第二部分运行结果:
1.underfind
2.报错
在之前说过,预解析是把带有varfunction关键字的事先声明,但不会赋值。所以一开始是underfind,然后报错是因为执行到a()的时候,a并不是一个函数。

//函数表达式,和变量声明同等
var a=function(){
    alert(10)
} 
//函数声明,优于变量声明    
function a(){
    alert(10)
} 

2-2.预解析和作用域

var a=0;
function aa(){
    alert(a)
    a=3
}
//结果是什么都没发生,因为要执行aa函数才会执行alert(0)

------------分割线1------------------

var a=0;
function aa(){
    alert(a)
    var a=3
}
aa();
//underfind  在aa函数里面,有var a=3,那么在aa作用域里面,就是把a这个变量声明提前,但是不会赋值,所以是underfind

------------分割线2------------------

var a=0;
function aa(a){
    alert(a)
    var a=3
}
aa(5)
alert(a)
//5,0   在函数体内,参数a的优先级高于变量a

------------分割线3------------------

var a=0;
function aa(a){
    alert(a)
    a=3
}
aa(5)
alert(a)
//5,0   在函数体内,执行alert(a)和a=3,修改的的并不是全局变量a,而是参数a

------------分割线4------------------

var a=0;
function aa(a){
    alert(a)
    var a=3
    alert(a)
}
aa(5)
//5,3
//这个我也有点不理解,请教网上的说法,有两个答案(小伙伴如果知道怎么理解,欢迎在评论上指点)
//1.参数优先级高于变量声明,所以 变量n的声明其实被忽略了,此时相当于
//var a=0;
//function aa(a){
//  var a=5;
//    alert(a)
//    a=3
//    alert(a)
//}
//aa(5)

//2.形参和局部变量优先级一样,此时相当于
//var a=0;
//function aa(a){
//  var a;    先声明
//  a=5      由于形参和变量名称一样,覆盖了!
//    alert(a)
//    a=3
//    alert(a)
//}
//aa(5)

------------分割线5------------------

var a=0;
function aa(a){
    alert(a)
    a=3
    alert(a)
}
aa()
alert(a)
//underfind  3  0 
//首先,参数优先级高于全局变量,由于没传参数,所以是underfind
//a=3,实际上修改的时形参a的值,并不是全局变量a,往下alert(a)也是形参a
//最后的alert(a),你懂的

3.递归

3-1.费波纳茨数组

这个不多说了,很简单,但是很经典。就是当前项等于前两项的和

var arr=[];
for(var i=0;i<10;i++ ){
    i<=1?arr.push(1):arr.push(arr[i-1]+arr[i-2]);
}
console.log(arr)

3-2.数据排列

比如 123454321 23456765432
这个怎么做呢?当时我的做法的分两步写,先展示前面,再展示后面
代码是

//01234543210
//先展示前面的   01234
//n:开始的数字    m:结束的数字
function num1(n,m){
    for(var i=n;i<m;i++){
        //再展示后面的 543210
        console.log(i);
        if(i===m-1){
            num2(n,m)
        }
    }
}
function num2(n,m){
    for(var i=m;i>=n;i--){
        console.log(i)
    }
}
test(2,5)  //2345432

这样代码太多了,后来研究了这种

function num(n,m){
    console.log(n);
    if(n<m){
        test(n+1,m);
        console.log(n);
    }
}
num(2,5)  //2345432

解释如下

1.首先执行num(2,5),就是
console.log(2); ->  test(3,5);  ->  console.log(2);      
//执行test(3,5);  就是是相当于   console.log(3); -> test(4,5); -> console.log(3); 下面以此类推
console.log(2); -> console.log(3); -> test(4,5); -> console.log(3); ->  console.log(2);  

然后就是

console.log(2); -> console.log(3); -> console.log(4); -> test(5,5); -> console.log(4); -> console.log(3); ->  console.log(2);

最后就是

console.log(2); -> console.log(3); -> console.log(4); -> console.log(5); -> console.log(4); -> console.log(3); ->  console.log(2);

4.其它

4-1

function foo1()
{
 return {
     bar: "hello"
 };
}
 
function foo2()
{
 return
 {
     bar: "hello"
 };
}
var a=foo1();
var b=foo2();
console.log(a) //Object {bar: "hello"}
console.log(b) //underfind
//仔细看就知道了

4-2

网上看到的题目,我自己改造下 80%应聘者都不及格的JS面试题

for (var i = 0; i < 5; i++) {
  console.log(i);
}
console.log(i);
//这个大家应该很快就知道了,012345



for (var i = 0; i < 5; i++) {
 setTimeout(function() {
  console.log(i);
 }, 1000);
}
console.log(i);
//这个大家就要小心一点了,答案是5    55555
//在setTimeout执行之前,for循环早就执行完了,i的值早已经是5了,所以一开始是执行,最后面的console.log(i);
//在for循环的时候一下子自定义5个setTimeout,大概一秒后,就是输出55555



for (var i = 0; i < 5; i++) {
 (function(j) { // j = i
  setTimeout(function() {
   console.log(j);
  }, 1000);
 })(i);
}
console.log(i); 
//这里的解析和上面基本一样,只是用闭包来记录每一次循环的i,
//所以答案是5     01234



var output = function (i) {
 setTimeout(function() {
  console.log(i);
 }, 1000);
};
 
for (var i = 0; i < 5; i++) {
 output(i); // 这里传过去的 i 值被复制了
}
console.log(i);

//这里的解析和上面基本一样,把i当参数传进output,记录每一次循环的i,
//所以答案是5     01234



for (let i = 0; i < 5; i++) {
 setTimeout(function() {
  console.log(i);
 }, 1000);
}
console.log(i);
//结果是  报错   01234 
//注意i是用let定义的,不是var

5.小结

首先,要说一个就是这些是我自己遇到的题目里面,印象比较深刻的一些题目,并不一定是常见的题目。
然后,这篇文章可以说是我的一个笔记,记录着我遇到过的题目。我发这样的面试题文章给小伙伴看,目的不是为了让小伙伴们记住题目和答案,或者是应付面试,这样没有意义,也不现实!我的目的是为了让大家可以学习一下,通过题目来知道一些原理和运行的机制,或者是知道一些可能的‘陷阱’。
另外,我遇到过的实际的操作题也很多,比如数组去重,打乱数组,统计数组各个元素出现的次数, 字符串各个字符的出现次数,获取地址链接的各个参数等等。这些题目不仅在面试题出现的比较多,在实际项目开发也会经常用到,小伙伴可以自己学习。当然我自己也有封装过一些函数,就是实现上面说的那些操作的函数,这个我近期也会写文章,记录我封装过哪些函数,封装过哪些常用的功能,到时候再分享。有什么需要改正的,或者好的建议,也欢迎指出!

-------------------------华丽的分割线--------------------
想了解更多,关注关注我的微信公众号:守候书阁

clipboard.png

你可能感兴趣的文章

28 条评论
许嵩Vae · 2017年07月10日

4-1也是醉了,论随手格式化代码的重要性!!!

+5 回复

猪吃鱼 · 2017年07月10日

面试题中还有var关键字,呵呵了

+2 回复

1

那应该有啥
要不养条鱼

开飞机的贝塔 · 2017年07月10日
0

@开飞机的贝塔 let

Zigzag · 2017年07月11日
shelly0129 · 2017年07月14日

自己写了一个3-2的
function num(n,m){

var len=(m-n)*2+1
for(var i=0;i<len;i++){
   n<m?(console.log(n++)):(console.log(m--))
}

}
num(2,5)

+2 回复

2

厉害,我学到了!

守候 作者 · 2017年07月16日
金蛋 · 2017年07月29日

被4-1埂了,尼玛第二个直接return后续直接不执行了,出题人真牛逼。这题也能出……

+2 回复

瘾_瘾 · 2017年08月07日

undefined不是underfind

+2 回复

依韵_宵音 · 2017年07月12日

我觉得2-1的第一个解释的有点问题

alert(a)
a();
var a=3;
function a(){
    alert(10)
}   
alert(a)
a=6;
a(); 

存在提示的有两个 functionvar function 更优先一点,因此实际上是:

// function a(){alert(10)} 提升到最前 ,var a=3;实际上是 var a; a=3; var a; 会前置 所以:
function a(){
    alert(10)
} 
var a;
alert(a)
a();
a=3;  
alert(a)
a=6;
a();  

+1 回复

1

原文中的 3.执行了var a=3; 所以alert(a)就是显示3 这里我觉得有问题

依韵_宵音 · 2017年07月12日
1

我的个人理解是
1.var a=function(){}和var a=3,这两个的优先级应该是一样的。函数声明,function a(){}优先级才会更高。
2.2-1中 ‘3.执行了var a=3; 所以alert(a)就是显示3’,可能当时解释得不够清楚,我的意思是,代码执行到了这里,然后a就是3,并不是一个函数了。所以后面的alert就是显示3。你说的也对,var a确实会被提前声明,但是不会赋值,所以a那个时候还是一个函数,执行到下面才被赋值(a=3)

守候 作者 · 2017年07月12日
1

@守候你 1 赞同的 就是这样。 我的意思是说 你的 3.执行了var a=3; 所以alert(a)就是显示3 这句里面只执行的应该是 a=3 , var a 是在 alert(a);a();之前就已经执行的。

依韵_宵音 · 2017年07月12日
莫名小晟 · 2017年07月19日

看到4-1愣了一秒,尼玛换行梗,出题人你出来我们聊聊

+1 回复

以乐之名 · 2017年09月05日

3-2 我自己的解决

var numFunc = function (n,m) {
  let arr = [m]
  for(let i = m - 1; i >= n; i--){
    arr.push(i);
    arr.unshift(i)
  }
  return arr.join()
}

numFunc(2, 5)
// 利用数组的操作方法
// push 数组尾部插入 pop数组尾部移除
// unshift 数组头部插入 shift数组头部移除

+1 回复

1

不错,学到了,这个也是比较好理解

守候 作者 · 2017年09月05日
行胜 · 2017年07月10日

4-1有点不懂

回复

0

foo1是返回了一个对象,foo2没有返回任何东西。因为foo2
return
//注意看,这里换行了,执行到return的时候就出去了,并没有返回对象
{
。。。
}

守候 作者 · 2017年07月10日
1

这个,真的是,醉了。我说我实现出来怎么一直两个都是Object。我把代码整理对齐了一下,结果就不是你的结果了。欲哭无泪啊。。。。。

Huooo · 2017年07月12日
呆萌小二郎zmh · 2017年07月10日

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

alert(10)

}
alert(a)
a=6;
a();
我在浏览器上试了,结果是先弹出6,然后报错a不是个函数,第一个并不是undefined

回复

0

你应该是浏览器测试我上面代码的之前,就已经有a这个变量了,并且赋值了!你试下把浏览器刷新了,然后再输入上面的代码就知道了!

守候 作者 · 2017年07月10日
0

@守候你 恩恩,试了下,刚我还在纳闷,怎么出6了,undefined是对的

呆萌小二郎zmh · 2017年07月10日
Zigzag · 2017年07月11日

3-1考查的不仅仅只是这个,查查memorize会有更好的答案。

回复

navk · 2017年07月12日

3-2一旦数据稍微大点,程序就慢的不行,硬件不好就要卡死。

回复

huguangju · 2017年07月19日

2-1.预解析1 的代码作如下转换就好理解了:

var a;
a = function() {
    alert(10)
}
alert(a)
a();
a=3;
alert(a)
a=6;
a();

------------分割线------------------

var a;
alert(a)
a();
a=3;
a=function(){
    alert(10)
}
alert(a)
a=6;
a(); 

回复

1

多谢提醒,确实是,这样的写法,比解释更好!

守候 作者 · 2017年07月19日
背靠南窗尿东墙 · 2017年07月20日

4-1这样出题真的很没有意思。。。

回复

navk · 2017年08月13日

明显就是随处乱搬过来的

回复

载入中...
Planets
守候 守候

14.1k 声望

发布于专栏

守候书阁

一个前端开发者,记录开发的点滴经历

484 人关注