前端面试官常问JavaScript编程题。

167 阅读2分钟

直接上干货:

1.数组排序。

sort() 方法以字母顺序对数组进行排序:

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();

使用相同技巧对数组进行降序排序:

var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return b - a});

2.数组元素的去重

利用ES6当中的Set去重(ES6中最常用)

function unique (arr) {
  return Array.from(new Set(arr))
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
 //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]

利用for嵌套for,然后splice去重

function unique(arr){            
        for(var i=0; i<arr.length; i++){
            for(var j=i+1; j<arr.length; j++){
                if(arr[i]==arr[j]){         //第一个等同于第二个,splice方法删除第二个
                    arr.splice(j,1);
                    j--;
                }
            }
        }
return arr;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
    //[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}]     //NaN和{}没有去重,两个null直接消失了

更多数组去重:segmentfault.com/a/119000001…

3.用递归的方法求数组的求和

递归求和:

var arr = [1,2,3];
function sum(arr) {
  if(arr.length == 0){
    return 0;
  } else if (arr.length == 1){
    return arr[0];
  } else {
    return arr[0] + sum(arr.slice(1));
  }
}
console.log(sum(arr));//6

for循环求和

var arr = [1,2,3];
function sum(arr) {
  var s = 0;
  for (var i = 0;i<arr.length;i++) {
    s += arr[i];
  }
  return s;
}
console.log(sum(arr));//6

4.深拷贝、浅拷贝

深复制和浅复制只针对像 Object, Array 这样的复杂对象的。简单来说,浅复制只复制一层对象的属性,而深复制则递归复制了所有层级. 浅复制:

var obj = { a:1, arr: [2,3] };
var shallowObj = shallowCopy(obj);
 
function shallowCopy(src) {
  var dst = {};
  for (var prop in src) {
    if (src.hasOwnProperty(prop)) {
      dst[prop] = src[prop];
    }
  }
  return dst;
}

因为浅复制只会将对象的各个属性进行依次复制,并不会进行递归复制,而 JavaScript 存储对象都是存地址的,所以浅复制会导致 obj.arr 和 shallowObj.arr 指向同一块内存地址。

shallowObj.arr[1] = 5;
obj.arr[1]   // = 5

而深复制则不同,它不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深复制的方法递归复制到新对象上。

需要注意的是,如果对象比较大,层级也比较多,深复制会带来性能上的问题。在遇到需要采用深复制的场景时,可以考虑有没有其他替代的方案。在实际的应用场景中,也是浅复制更为常用。

5.做一个10秒的倒计时

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<script type="text/javascript">
    function daojishi()
    {
        var starttime=document.getElementById("id2").innerText;
        if(starttime==0)
        {
            return ;
        }
        setTimeout("daojishi()",1000);
        starttime--;
        document.getElementById("id2").innerText=starttime;
    }
</script>
 
 
<body>
<h5 id="id2">10</h5>
<button id="id1" onclick="daojishi()">开始倒计时</button>
 
</body>
</html>

6.setTimeout()和setInterval()的使用以及区别

setTimeout()方法

这个方法所有浏览器都支持,setTimeout( ) 是属于 window 的 method, 但我们都是略去 window 这顶层物件名称, 这是用来设定一个时间, 时间到了, 就会执行一个指定的 method。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <script>
        var x = 0;
        function countSecond()
        {
            x = x+1;
            document.haorooms.haoroomsinput.value = x;
            setTimeout("countSecond()", 1000)
        }
    </script>
</head>
<html>
<body>
 
<form name="haorooms">
    <input type="text" name="haoroomsinput" value="0" size=4 >
</form>
 
<script>
    countSecond();
</script>
 
</body>
</html>

setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。setInterval() 方法会不停地调用函数,直到 

clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
 
</body>
<script>
    function test(){
        this.name = "setInternal";
        this.waitMes = function(){
            var that = this;
            setInterval(function(){
                alert(that.name);
            },3000);
        }
    }
    var te = new test();
    te.waitMes();
</script>
</html>

通过上面可以看出,setTimeout和setinterval的最主要区别是:

    1)setTimeout只运行一次,也就是说设定的时间到后就触发运行指定代码,运行完后即结束。如果运行的代码中再次运行同样的setTimeout命令,则可循环运行。(即:要循环运行,需函数自身再次调用 setTimeout());而 setinterval是循环运行的,即每到设定时间间隔就触发指定代码。这是真正的定时器。

    2)setinterval使用简单,而setTimeout则比较灵活,可以随时退出循环,而且可以设置为按不固定的时间间隔来运行,比如第一次1秒,第二次2秒,第三次3秒。