其实每个面试题 答案不是一种 这个很重要的 尤其大公司的面试题
每个方式的为什么属于最重要的。
1 如何找最接近定值的值。
// 方法01
function limit(arr, num){
var newArr = [];
arr.map(function(x){
// 对数组各个数值求差值
newArr.push(Math.abs(x - num));
});
// 求最小值的索引
var index = newArr.indexOf(Math.min.apply(null, newArr));
return arr[index];
}
// 方法二
function findNext(num,arr) {
return arr.sort((a,b)=>{ return Math.abs(a-num) - Math.abs(b-num) })[0]
}
2 如何写多外边框
总结 (outline和box-shadow (分为内外阴影))
方法1 传统的 嵌套多个div
方法2 使用outline
#outline {
width: 84px;
height: 84px;
border: 8px solid blue;
/*-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;*/
outline: 10px solid brown;
outline-offset: 0px;
/*border和outline之间的距离*/
margin: 20px;
/*因为outline不影响布局,使用margin给边框腾位置*/
}
优点:它跟边框类似,可以设置各种线型,比如虚线、实线。
缺点:outline不影响布局,需使用margin给边框腾位置。以防被其它元素覆盖。如果容器本身有圆角的话,描边并不能完全贴合圆角,效果图如下
方法3 使用box-shadow 外投影实现多重边框。
#boxShadow {
margin: 40px;
/*因为box-shadow不影响布局,使用margin给边框腾出位置*/
width: 84px;
height: 84px;
border: 8px solid blue;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
-webkit-box-shadow: 0 0 0 10px brown;
box-shadow: 0 0 0 10px brown;
/*参数分别为:水平偏移量、垂直偏移量、模糊距离、向外扩展距离和投影颜色*/
}
优点:多个圆角边框之间完全贴合;同时还可以接收一个列表,一次设置多个投影(即边框)。它的扩张效果是根据元素自己的形状来的,如果元素是矩形,它扩张开来就是一个更大的矩形;如果元素有圆角,它也会扩张出圆角。
缺点:CSS3属性,兼容性不好;box-shadow也不影响布局的,如果这个元素和其它元素的相对位置关系很重要,需要以外边距等方式来为这些多出来的 “边框” 腾出位置,以防被其它元素覆盖。
注意:使用内嵌投影(即box-shadow添加参数为inset,默认不设置时为外阴影)似乎是更好的选择。因为内嵌投影让投影出现在元素内部,设置内边距在元素的内部给多个边框腾位置,处理起来更容易一些
/*使用box-shadow一次性设置多个边框,并且使用内嵌投影*/
#moreboxShadow {
width: 120px;
height: 120px;
border: 8px solid blue;
/*注意:向外扩张的距离要每次累加;内嵌投影即添加参数为inset,该参数可选,当不设置时即为外投影*/
-webkit-box-shadow: inset 0 0 0 10px brown, inset 0 0 0 20px yellow, inset 0 0 0 30px green;
box-shadow: inset 0 0 0 10px brown, inset 0 0 0 20px yellow, inset 0 0 0 30px green;
padding: 30px;
/*设置内边距,为box-shadow添加的添加的边框疼位置,这样就不会影响元素之间的位置*/
3 eventEmiter的实现
class EventEmitter {
constructor(){
this.listeners = {};
}
on(type,cb){
if (this.listeners[type]){
this.listeners[type].push(cb);
} else {
this.listeners[type] = [cn];
}
}
emit(type,..arg) {
this.listeners[type]this.listeners[type].forEach(el=> el.apply(this,arg))
}
remove(type,cb){
this.listeners[type] && this.listeners[type].filter(el=> el !==cb)
}
}
4 深度克隆
const isType = (obj, type) => {
if (typeof obj !== 'object') return false;
const typeString = Object.prototype.toString.call(obj);
let flag;
switch (type) {
case 'Array':
flag = typeString === '[object Array]';
break;
case 'Date':
flag = typeString === '[object Date]';
break;
case 'RegExp':
flag = typeString === '[object RegExp]';
break;
default:
flag = false;
}
return flag;
};
/**
* deep clone
* @param {[type]} parent object 需要进行克隆的对象
* @return {[type]} 深克隆后的对象
*/
const clone = parent => {
// 维护两个储存循环引用的数组
const parents = [];
const children = [];
const _clone = parent => {
if (parent === null) return null;
if (typeof parent !== 'object') return parent;
let child, proto;
if (isType(parent, 'Array')) {
// 对数组做特殊处理
child = [];
} else if (isType(parent, 'RegExp')) {
// 对正则对象做特殊处理
child = new RegExp(parent.source, getRegExp(parent));
if (parent.lastIndex) child.lastIndex = parent.lastIndex;
} else if (isType(parent, 'Date')) {
// 对Date对象做特殊处理
child = new Date(parent.getTime());
} else {
// 处理对象原型
proto = Object.getPrototypeOf(parent);
// 利用Object.create切断原型链
child = Object.create(proto);
}
// 处理循环引用
const index = parents.indexOf(parent);
if (index != -1) {
// 如果父数组存在本对象,说明之前已经被引用过,直接返回此对象
return children[index];
}
parents.push(parent);
children.push(child);
for (let i in parent) {
// 递归
child[i] = _clone(parent[i]);
}
return child;
};
return _clone(parent);
};