前端面试题~手写代码篇
深拷贝
function deepClone(obj) {
var result = Array.isArray(obj) ? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === 'object' && obj[key]!==null) {
result[key] = deepClone(obj[key]);
} else {
result[key] = obj[key];
}
}
}
return result;
}
function deepClone(arr){
return JSON.parse(JSON.stringify(arr))
}
数组乱序
// 取巧的一种算法,但是每个位置乱序的概率不同
function mixArr(arr){
return arr.sort(() => {
return Math.random() - 0.5;
})
}
// 著名的Fisher–Yates shuffle 洗牌算法
function shuffle(arr){
let m = arr.length;
while(m > 1){
let index = parseInt(Math.random() * m--);
[arr[index],arr[m]] = [arr[m],arr[index]];
}
return arr;
}
数组去重
ES6 set 方法
function removeDup(arr){
var result = [];
var hashMap = {};
for(var i = 0; i < arr.length; i++){
var temp = arr[i]
if(!hashMap[temp]){
hashMap[temp] = true
result.push(temp)
}
}
return result;
}
Array.from(new Set(arr))
[...new Set(arr)]
手写call & apply & bind
call、apply、bind是ES5中能改变this指向的方法。一般都会问一下这三个方法的区别。call和apply的传参不同,call接收逗号分隔的参数,apply接收数组(如何记不清这两个方法的区别的话,可以记apply接收array,都是a开头的,这样比较好记),调用都会立即执行。而bind调用完返回的是一个函数,需要再次调用才会执行。
接下来就会引申到能实现一个call/apply吗?或者能用apply实现一个bind吗?
Function.prototype.myCall = function(context){
if(typeof this != 'function'){
throw new TypeError('this is not a function')
}
context.fn = this;
var arr = [];
for(var i = 1; i< arguments.length; i++){
arr.push('argument[' + i + ']')
}
var result = eval('context.fn(' +arr+ ')');
delete context.fn;
return result;
}
Function.prototype.myApply = function(context,arr){
if(typeof this != 'function'){
throw new TypeError('this is not a function')
}
context.fn = this;
var result= [];
if(!arr){
result = context.fn()
}else{
var args = [];
for(var i = 1; i< arr.length; i++){
args.push('arr[' + i + ']')
}
result = eval('context.fn(' +args+ ')');
}
delete context.fn;
return result;
}
Function.prototype.myBind = function(context){
if(typeof this != 'function'){
throw new TypeError('this is not a function')
}
var self = this;
var args = Array.prototype.slice.call(arguments,1);
var F = function(){};
F.prototype = this.prototype;
var bound = function(){
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof F ? this: context, args.concat(bindArgs))
};
bound.prototype = new F();
return bound;
}