面试题目

Posted by Liu lin on January 3, 2019

this

  • 填空 ``` <!DOCTYPE html>
this指向

<!DOCTYPE html>

this指向

<!DOCTYPE html>

this

以上三段代码分别输出什么?

### 原生DOM操作

- 完成以下dom节点的操作,要求:使用原生JS
  • #0
  • #1
  • #2
  • #3
    • #4
  • ...
  • #99998
  • #99999
  • #100000

为 <ul> 添加一个类 bar; 删除第 10 个 <li>; 在第 500 个 <li> 后面增加一个 <li> , 其文字内容为 ; 点击任意 <li> 弹窗显示其为当前列表中的第几项。


答案:

1) var list = document.getElementById(‘list’).getAttribute(‘class’); list = list.concat(‘bar’); document.getElementById(‘list’).setAttribute(‘class’,list) 2) var ul = document.getElementById(‘list’); var li = document.getElementsByTagName(‘li’); ui.removeChild(list[9]) 3) var ul = document.getElementById(‘list’); var li = document.createElement(‘li’); var lis = ducument.getElementsByTagName(‘li’); li.innerText= “"; ul.insertBefore(li,lis[500]) 4) 主要的两种实现方式,可要求使用两种方式实现:闭包,事件委托; 闭包: var ul = ducument.getElementsByTagName('ul')[0]; var lis = ul.getElementsByTagName('li'); function foo(){ for (var i = 0; i< lis.length; i++){ lis[i].onclick = (function(i){ return function(){ alert(i) } })(i) } }

foo();

事件委托: var ul = document.getElementById(‘list’); var lis = ul.getElementsByTagName(‘li’); ul.addEventListener(‘click’, function(e){ var e = e || window.event; var target = e.target || e.srcElement; for (var i=0; i< li.length; i++){ if(li[i] == target){ alert(i) } } })

### 算法

- 

### 

- 函数节流和防抖

节流: function throttle(fn, delay) { delay = delay || 50 let statTime = 0 return function () { statTime === 0 && fn.apply(this, arguments) let currentTime = new Date() if (currentTime - statTime > delay) { fn.apply(this, arguments) statTime = currentTime } } }

防抖: function debounce(fn, delay) { delay = delay || 50 let timer = null return function () { let self = this clearTimeout(timer) timer = setTimeout(fn.bind(self, arguments), delay); } }


- 原生Bind实现

Function.prototype._bind = function (context) { let self = this let args_1 = [].prototype.slice.call(arguments, 1) return function () { let args_2 = [].prototype.slice.call(arguments) let args = args_1.concat(args_2) return self.apply(context, args) } }

- 下面是一个一个动画版冒泡排序,请补充完整相应的代码

(function (global, undefined) {

/**
 * 构造函数
 * @param {构造参数} opt 
 */
function MySort(opt) {

    this.def = opt;
    this._initDom();

}


/**
 * 初始化dom(计算排序item的宽高,自适应容器)
 */
MySort.prototype._initDom = function () {

    //获取容器
    let container = document.getElementById(this.def.container);
    //获取数据
    let arr = this.def.arr;
    //获取数组最大值
    let max = Math.max.apply(null, arr);
    //容器宽度
    let cWidth = container.offsetWidth;
    //容器高度
    let cHeight = container.offsetHeight - 50;
    //计算item宽度
    let count = arr.length;
    let itemWidth = (cWidth - this.def.sep * (count + 1)) / count;
    //填充dom
    let html = '';
    arr.forEach((element, index) => {

        //计算left
        let left = index * itemWidth + (index + 1) * this.def.sep;
        //计算高度
        let height = element / max * cHeight;

        html += `<div class="item normalItem" style="left:${left}px; width:${itemWidth}px; height:${height}px;">${element}</div>`;

    });
    container.innerHTML = html;

}


/**
 * 交换两个item的dom位置
 * @param {左侧item} tempItem1 
 * @param {右侧item} tempItem2 
 */
MySort.prototype._changePosition = function (tempItem1, tempItem2) {

    tempItem1.parentNode.removeChild(tempItem2);
    tempItem1.parentNode.insertBefore(tempItem2, tempItem1);

}


/**
 * 交换两个item的逻辑位置实现动画
 * @param {排序数组} resArr 
 * @param {item列表} itemList 
 * @param {内侧循环index} j 
 */
MySort.prototype._changeItem = function (resArr, itemList, j) {

    [resArr[j], resArr[j + 1]] = [resArr[j + 1], resArr[j]];
    let tempLeft = itemList[j].style.left;
    itemList[j].style.left = itemList[j + 1].style.left;
    itemList[j + 1].style.left = tempLeft;

}


/**
 * 给当前活跃的item添加样式
 * @param {item列表} itemList 
 * @param {内侧循环index} j 
 */
MySort.prototype._activeItem = function (itemList, j) {

    itemList[j].classList.add('activeItem');
    itemList[j + 1].classList.add('activeItem');
    if (j > 0) {
        itemList[j - 1].classList.remove('activeItem');
    }

}


/**
 * 给已完成排序的item添加样式
 * @param {item列表} itemList 
 * @param {外侧循环index} i 
 * @param {内侧循环index} j 
 * @param {完成标示} complete 
 */
MySort.prototype._completeItem = function (itemList, i, j, complete) {

    itemList[j + 1].classList.add('completeItem');
    itemList[j].classList.remove('activeItem');
    //如果完成把剩余item设置为complete
    if (complete) {
        for (j = 0; j < itemList.length - i - 1; j++) {
            itemList[j].classList.add('completeItem');
        }
    }

}

/**
 * 排序内部逻辑操作
 */
MySort.prototype._render = async function (itemList,resArr,i,j, complete) {

    this._activeItem(itemList, j);
    await sleep(this.def.speed);

    if (resArr[j + 1] < resArr[j]) {

        this._changeItem(resArr, itemList, j);
        await sleep(this.def.speed);
        this._changePosition(itemList[j], itemList[j + 1]);
        complete = false;

    }

    //最后一次比较
    if (j == resArr.length - i - 2) {
        this._completeItem(itemList, i, j, complete);
    }

    //回调
    this.def.getData(resArr);
    return complete;

}


/**
 * 开始动画
 */
MySort.prototype.start = async function () {

    let resArr = this.def.arr.slice();
    let len = resArr.length;
    let complete;
    let itemList = document.getElementById(this.def.container).childNodes;

    for (let i = 0; i < len - 1; i++) {
        complete = true;
        for (let j = 0; j < len - i - 1; j++) {
            //交换逻辑操作
           complete = await this._render(itemList,resArr,i,j,complete);
        }
        if (complete) {
            break;
        }
    }

}


/**
 * 线程睡眠
 * @param {睡眠时间} time 
 */
var sleep = function (time) {

    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve();
        }, time);
    })

};


global.MySort = MySort;

})(window);

html如下:

<!DOCTYPE html>

冒泡排序动画demo1
- reduce实现数组去重

const distinct = arr => arr.sort().reduce( (init, current) => {

if (init.length === 0 || init[init.length - 1] !== current) {
    init.push( current );
}
return init; }, []);

- 两数之和:给定一个整数数组和一个目标值,找到数组中和为目标值的两个数.

/**

  • @param {number[]} nums
  • @param {number} target
  • @return {number[]} */ var twoSum = function(nums, target) {

    var map = new Map(); var number = [];

    for(var i = 0; i < nums.length; i ++) {

     if(map.has(target - nums[i])) {
        number.push(i, map.get(target - nums[i]));
         break;
     }
     map.set(nums[i], i);  }  return number; };
    

```