前端面试题(四)

  • 数组去重方法

方法一:
1、先创建一个空数组,用来保存最终结果
2、循环原数组中的每一个元素
3、再对每个元素进行第二次循环,判断是否有与之相同的元素,如果没有把这个元素放到新数组中
4、返回这个新数组


var arr = [];
var arr1 = [1,3,4,6,7,2,5,3,4,0]
for (var i = 0;i<arr1.length;i++){
  for(var j = i+1;j<arr1.length;j++){
    if(arr1[i] === arr1[j]){
      ++i;
    }
  }
  arr.push(arr1[i]);
}
console.log(arr.sort());
方法二:
/*
* 新建一新数组,遍历传入数组,值不在新数组就push进该新数组中
* IE8以下不支持数组的indexOf方法
* */
function uniq(array){
    var temp = []; //一个新的临时数组
    for(var i = 0; i < array.length; i++){//indexOf() 方法可返回数组中某个指定的元素位置。
        if(temp.indexOf(array[i]) == -1){//如果在数组中没找到指定元素则返回 -1
            temp.push(array[i]);
        }
    }
    return temp;
}

var aa = [1,2,2,4,9,6,7,5,2,3,5,6,5];
console.log(uniq(aa));
  • JavaScript原型,原型链

 每个对象都会在其内部初始化一个属性,就是prototype(原型),当我们访问一个对象的属性时,
 如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,
 于是就这样一直找下去,也就是我们平时所说的原型链的概念。
 关系:instance.constructor.prototype = instance.__proto__
  •  获取页面中所有的checkbox

<div>
      <input type="radio" value="wangwu">
      <input type="checkbox" value="wangwu">
      <input type="checkbox" value="wangwu">
      <input type="checkbox" value="wangwu">
      <input type="radio" value="wangwu">
</div>

var domList = document.getElementsByTagName("input");
var checkBoxList = [];
var len = domList.length;
for(var i = len-1;i>=0;i--){
  if(domList[i].type == "checkbox"){
    checkBoxList.push(domList[i]);
  }
}
console.log(checkBoxList)
  • JavaScript的事件流模型?(DOM事件流)

事件冒泡:事件开始由最具体的元素接受,然后逐级向上传播
事件捕捉:事件由最不具体的节点先接受,然后逐级向下,一直到最具体的

DOM事件流包含三个阶段:
1、事件捕捉
2、目标阶段
3、事件冒泡
  • 谈谈This对象的理解

this总是指向函数的直接调用者(而非间接调用者);
如果有new关键字,this指向new出来的那个对象;
在事件中,this指向触发这个事件的对象,特殊的是,IE中的attachEvent中的this总是指向全局对象Window;
  • JavaScript实现数组倒排和降序排列

数组倒排:

方法一:
var arr = [3,6,2,4,2,3,5];
console.log(arr.reverse());

方法二:
var arr = [3,6,2,4,2,3,5]
function Rerevse(arr){
  var result = [];
  for (var i = arr.length-1;i>=0;i--){
    result.push(arr[i]);
  }
  return result;
}
arr1 = Rerevse(arr);
console.log(arr1);
数组降序排列:
function bubbleSort(arr) {
    var len = arr.length;
    for (var i = 0; i < len; i++) {
        for (var j = 0; j < len - 1 - i; j++) {
            if (arr[j] < arr[j+1]) {        //相邻元素两两对比
                var temp = arr[j+1];        //元素交换
                arr[j+1] = arr[j];
                arr[j] = temp;
            }
        }
    }
    return arr;
}
arrges = [3,6,8,3,9,0,1,1];
console.log(bubbleSort(arrges));
  • JavaScript排序方法有哪些?

冒泡排序法:
解析:

    1.比较相邻的两个元素,如果前一个比后一个大,则交换位置。

  2.第一轮的时候最后一个元素应该是最大的一个。

   3.按照步骤一的方法进行相邻两个元素的比较,这个时候由于最后一个元素已经是最大的了,所以最后一个元素不用比较。

function bubbleSort(arr) {
    var len = arr.length;
    for (var i = 0; i < len; i++) {
        for (var j = 0; j < len - 1 - i; j++) {
            if (arr[j] > arr[j+1]) {        //相邻元素两两对比
                var temp = arr[j+1];        //元素交换
                arr[j+1] = arr[j];
                arr[j] = temp;
            }
        }
    }
    return arr;
}
arrges = [3,6,8,3,9,0,1,1];
console.log(bubbleSort(arrges));
注:作为最简单的排序算法之一,冒泡排序给我的感觉就像Abandon在单词书里出现的感觉一样,每次都在第一页第一位,
所以最熟悉。。。冒泡排序还有一种优化算法,就是立一个flag,当在一趟序列遍历中元素没有发生交换,则证明该序列已经有序。
但这种改进对于提升性能来说并没有什么太大作用。。。
选择排序法:
解析:

 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

以此类推,直到所有元素均排序完毕。
function selectionSort(arr) {
    var len = arr.length;
    var minIndex, temp;
    for (var i = 0; i < len - 1; i++) {
        minIndex = i;
        for (var j = i + 1; j < len; j++) {
            if (arr[j] < arr[minIndex]) {     //寻找最小的数
                minIndex = j;                 //将最小数的索引保存
            }
        }
        temp = arr[i];
        arr[i] = arr[minIndex];
        arr[minIndex] = temp;
    }
    return arr;
}
arr = [5,8,2,4,6,0,1,9,3];
console.log(selectionSort(arr));
注:在时间复杂度上表现最稳定的排序算法之一,因为无论什么数据进去都是O(n²)的时间复杂度。。。
所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。
快速排序:
解析:
快速排序是对冒泡排序的一种改进,第一趟排序时将数据分成两部分,一部分比另一部分的所有数据都要小。然后递归调用,在两边都实行快速排序。
function quickSort(arr, left, right) {
    var len = arr.length,
        partitionIndex,
        left = typeof left != 'number' ? 0 : left,
        right = typeof right != 'number' ? len - 1 : right;

    if (left < right) {
        partitionIndex = partition(arr, left, right);
        quickSort(arr, left, partitionIndex-1);
        quickSort(arr, partitionIndex+1, right);
    }
    return arr;
}

function partition(arr, left ,right) {     //分区操作
    var pivot = left,                      //设定基准值(pivot)
        index = pivot + 1;
    for (var i = index; i <= right; i++) {
        if (arr[i] < arr[pivot]) {
            swap(arr, i, index);
            index++;
        }        
    }
    swap(arr, pivot, index - 1);
    return index-1;
}

function swap(arr, i, j) {
    var temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}
arr = [5,8,2,4,6,0,1,9,3,88];
console.log(quickSort(arr));

注:快速排序的内循环比大多数排序算法都要短小,这意味着它无论是在理论上还是在实际中都要更快。
它的主要缺点是非常脆弱,在实现时要非常小心才能避免低劣的性能。
插入排序:
解析:
 (1) 从第一个元素开始,该元素可以认为已经被排序
 (2) 取出下一个元素,在已经排序的元素序列中从后向前扫描
 (3) 如果该元素(已排序)大于新元素,将该元素移到下一位置
 (4) 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
 (5) 将新元素插入到下一位置中
 (6) 重复步骤2
function insertionSort(arr) {
    var len = arr.length;
    var preIndex, current;
    for (var i = 1; i < len; i++) {
        preIndex = i - 1;
        current = arr[i];
        while(preIndex >= 0 && arr[preIndex] > current) {
            arr[preIndex+1] = arr[preIndex];
            preIndex--;
        }
        arr[preIndex+1] = current;
    }
    return arr;
}
arr = [5,8,2,55,6,0,1,9,3,88]
console.log(insertionSort(arr));

注:插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据。
算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。
希尔排序:
解析:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序

function shellSort(arr) {
    var len = arr.length,
        temp,
        gap = 1;
    while(gap < len/3) {          //动态定义间隔序列
        gap =gap*3+1;
    }
    for (gap; gap> 0; gap = Math.floor(gap/3)) {
        for (var i = gap; i < len; i++) {
            temp = arr[i];
            for (var j = i-gap; j >= 0 && arr[j]> temp; j-=gap) {
                arr[j+gap] = arr[j];
            }
            arr[j+gap] = temp;
        }
    }
    return arr;
}
arr = [5,8,2,55,6,0,1,9,33,88];
console.log(shellSort(arr));

注:希尔排序是插入排序的一种更高效率的实现。它与插入排序的不同之处在于,它会优先比较距离较远的元素。
希尔排序的核心在于间隔序列的设定。既可以提前设定好间隔序列,也可以动态的定义间隔序列。
归并排序:
解析:归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
function mergeSort(arr) {  //采用自上而下的递归方法
    var len = arr.length;
    if(len < 2) {
        return arr;
    }
    var middle = Math.floor(len / 2),
        left = arr.slice(0, middle),
        right = arr.slice(middle);
    return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right)
{
    var result = [];

    while (left.length>0 && right.length>0) {
        if (left[0] <= right[0]) {
            result.push(left.shift());
        } else {
            result.push(right.shift());
        }
    }

    while (left.length)
        result.push(left.shift());

    while (right.length)
        result.push(right.shift());

    return result;
}
arr = [5,8,21,55,6,0,1,9,33,88];
console.log(mergeSort(arr));

注:JavaScript没有对递归进行优化。运用递归函数不仅没有运行速度上的优势,还可能造成程序运行失败。因此不建议使用递归。

和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(n log n)的时间复杂度。代价是需要额外的内存空间。
原文地址:https://www.cnblogs.com/strong-FE/p/10875705.html