十道前端面试题

102 阅读2分钟

1、为数组去重

方法一:双层for循环

思路:双层循环,外层循环元素,内层循环时进行比较,如果有相同的值则跳过,不相同则用push进新数组,然后返回新数组,因为它的时间复杂度是O(n^2),如果数组长度很大,效率会很低

Array.prototype.removeDuplicate=function(){
	var arr=this,result=[],i,j,len=arr.length;
	for(i=0;i<len;i++){
        for(j=i+1;j<len;j++){
            if(arr[i]===arr[j]){
            j=++i
            }
        }
	  result.push(arr[i])
	}
	return result
}

方法二:Array.filter() 加 indexOf/includes

思路:利用indexOf检测元素在数组中第一次出现的位置是否和元素现在的位置相等,如果不等则说明该元素是重复元素

function distinct(a, b) {
    let arr = a.concat(b);
    return arr.filter((item, index)=> {
        return arr.includes(item)
    })
}

方法三:ES6 中的 Set 去重

思路: ES6 提供了新的数据结构 Set,Set 结构的一个特性就是成员值都是唯一的,没有重复的值。

function distinct(array) {
   return Array.from(new Set(array));
}

2、将一个setTimeout转为Promise

function sleep(ms){
	return new Promise((resolve,reject)=>{
	if(ms>1000)reject(new Error('延迟时间过长'))
	setTimeout(()=>resolve(),ms)
	})
}

3、求出所有参数中偶数之和,参数不定

function sumEven(){
	var len=arguments.length;
	if(len==0){
		return 0
	}
	var sum=0;
	for(var i=0;i<len;i++){
		if(arguments[i]%2==0){
			sum+=arguments[i]
		}
		return sum
	}
}

4、实现一个自动生成ID函数,每次调用ID值加1

function getID(){
	var n=0
	return function(){
		return n++;
	}
}

5、添加合适的css属性,使div.inner可以相对div.outer垂直居中,其中div.inner的高度不定(写出三种)

1、弹性盒模型
    display:flex;
    justify-content:center;
    align-items:center;

2、父级
    display:flex;
子元素:
    margin:auto

3、定位
父元素
    position:relative
子元素
     position: absolute;
     top: 50%;
     left: 50%;
     transform: translate(-50%, -50%);

6、为了遍历对象添加迭代器,使之可以使用for...of遍历

function addIterator(obj){
       if(Object.prototype.toString.call(obj) !== "[object Object]"){
         return //非对象,不处理
    }
    if(obj[Symbol.iterator]){
    return //避免重复添加
    }
const it = Object.create(Object.getPrototypeOf(obj), {
        [Symbol.iterator]:  {
                enumerable: false,
                writable: false,
                configurable: true,
                value: function() {
                    const _this = this
                    //也可使用: keys = Object.getOwnPropertyNames(this)
                    const keys = Object.keys(this)
                    let index = 0
                    return {
                        next(){
                            return {
                                value: _this[keys[index++]],
                                done: index>keys.length
                            }
                        }
                    }
        }
	}
})
Object.setPrototypeOf(obj, it)
}

7、遍历一棵树

function flatTree(tree){
	for(var i in tree){
		this.expandedKeys.push(tree[i].label)
		if(tree[i].children){
			this.setName(tree[i].children)
		}
	}
}

8、实现一个重复执行的函数,返回的函数每次执行后可以重复执行fn函数times次,每次时间间隔wait毫秒

function repeat(fn, times, wait) {
  return () => {
    for (let i = 1; i <= times; i++) {
      setTimeout(fn, i * wait)
    }
  }
}

9、实现一个JS函数柯里化

柯里化的定义:接收一部分参数,返回一个函数接收剩余参数,接收足够参数后,执行原函数。

有两种思路:

  • 通过函数的 length 属性,获取函数的形参个数,形参的个数就是所需的参数个数
  • 在调用柯里化工具函数时,手动指定所需的参数个数

通用版

function curry(fn, args) {
    var length = fn.length;
    var args = args || [];
    return function(){
        newArgs = args.concat(Array.prototype.slice.call(arguments));
        if (newArgs.length < length) {
            return curry.call(this,fn,newArgs);
        }else{
            return fn.apply(this,newArgs);
        }
    }
}

ES6写法

const curry = (fn, arr = []) => (...args) => (
  arg => arg.length === fn.length
    ? fn(...arg)
    : curry(fn, arg)
)([...arr, ...args])

10、实现一个双向绑定

defineProperty 版本

// 数据
const data = {
  text: 'default'
};
const input = document.getElementById('input');
const span = document.getElementById('span');
// 数据劫持
Object.defineProperty(data, 'text', {
  // 数据变化 --> 修改视图
  set(newVal) {
    input.value = newVal;
    span.innerHTML = newVal;
  }
});
// 视图更改 --> 数据变化
input.addEventListener('keyup', function(e) {
  data.text = e.target.value;
});

proxy 版本

// 数据
const data = {
  text: 'default'
};
const input = document.getElementById('input');
const span = document.getElementById('span');
// 数据劫持
const handler = {
  set(target, key, value) {
    target[key] = value;
    // 数据变化 --> 修改视图
    input.value = value;
    span.innerHTML = value;
    return value;
  }
};
const proxy = new Proxy(data, handler);

// 视图更改 --> 数据变化
input.addEventListener('keyup', function(e) {
  proxy.text = e.target.value;
});