2020面试系列-js手写代码
函数节流,防抖
节流
//函数节流
function throttle(handler, wait) {
let preTime = 0;
return function () {
let now = Date.now();
if (now - preTime >= wait) {
handler();
preTime = now;
}
};
}
var t = throttle(function () {
console.log(11);
}, 1000);
var oBtn1 = document.getElementById('btn1');
oBtn1.onclick = function(){
t();
}
防抖
//函数防抖
function debounce(handler, wait) {
let timer = null;
return function () {
if(timer){
clearTimeout(timer);
}
timer = setTimeout(
handler,1000
)
};
}
var t = debounce(function () {
console.log(11);
}, 1000);
document.onmousemove = function(){
t();
}
实现call,apply,bind
call
Function.prototype.mcall = function (context) {
//传参第一个参数转对象,不传参直接去window
let ctx = Object(context) || window;
let fn = "fn",
res = "";
while (ctx.hasOwnProperty(fn)) {
// 循环判断并重新赋值 ,防止上下文对象上本来就有同名方法
fn = fn + Math.random();
}
//把绑定函数作为上下文对象的方法
ctx[fn] = this;
//作为对象方法调用绑定函数,并把参数传入
if (arguments.length > 1) {
res = ctx[fn](...[...arguments].slice(1));
} else {
res = ctx[fn]();
}
delete ctx[fn];
//返回函数返回值
return res;
};
apply
Function.prototype.mapply = function (context, arr) {
let ctx = Object(context) || window;
let fn = "fn",
res = "";
while (ctx.hasOwnProperty(fn)) {
fn = fn + Math.random();
}
ctx[fn] = this;
if (arr) {
res = ctx[fn](...arr);
} else {
res = ctx[fn]();
}
delete ctx[fn];
return res;
};
bind
Function.prototype.mbind = function (context) {
context = context ? Object(context) : window;
//保存argumets
var mArguments = arguments,
self = this;
if (arguments.length > 1) {
return function () {
//借用apply
self.apply(context, [...mArguments].slice(1));
};
} else {
return function () {
self.apply(context);
};
}
};
实现数组实例方法
push
//push 从后面新增
Array.prototype.push = functon(){
for(var i =0;i<arguments.length;i++){
this[this.length-1] = arguments[i];
}
return this.length;
}
POP
//pop 从后面删除一个
Array.prototype.pop = function(){
var item = this[this.length-1];
if(this.length>0){
this.length = this.length - 1;
}
return item;
}
shift
//shift 从前面删除一项
Array.prototype.shift = function(){
var item = this[0];
for(var i = 1;i<this.length;i++){
this[i-1] = this[i];
}
this.length = this.length-1;
return item;
}
unshrft
//unshift 从前面增加n项
Array.ptototype.unshift = function(){
var l = arguments.length;
//把原数组向后移动
for(var i= 0;i<this.length;i++){
this[i+l] = this[i];
}
//赋值
for(var j = 0;j<arguments.length;j++{
this[j] = arguments[j];
}
return this.length;
}
filter
//fitler
Array.prototype.fitler = function(handler){
var newArr = [];
for(var i = 0;i<this.length;i++){
if(handler(this[i],i,this)){
newArr[newArr.length] = this[i];
}
}
return newArr;
}
数组去重
//普通去重
function unique(arr) {
var newArr = [];
arr.forEach((item, index, arr) => {
if (newArr[newArr.length] != item) {
newArr[newArr.length] = item;
}
});
return newArr;
}
//indexOf去重
function unique(arr) {
var newArr = [];
arr.forEach((item, inddex, arr) => {
if (newArr.indexOf(item) == -1) {
newArr.length = item;
}
});
return newArr;
}
//利用对象属性不能相同
function unique(arr) {
var obj = {},
newArr = [];
arr.forEach((item, index, arr) => {
if (!obj[item]) {
obj[arr[i]] = 1;
newArr.push(item);
}
});
return newArr;
}
//es6去重
function unique(arr) {
return Array.from(new Set(arr));
}
//扩展运算符
function unique(arr) {
return [...new Set(arr)];
}
排序算法
//冒泡排序
//相邻两元素之间两两比较,比较出大值进行赋值互换,再依次与相邻的元素比较,层层递进
//假设升序排序
function bubbleSort(arr) {
var l = arr.length;
for (var i = 0; i < l; i++) {
//比较轮数
for (var j = 0; j < l - i - 1; j++) {
//每一轮确定一个最大值,放最右边
var temp = arr[j];
if (arr[j] > arr[j + 1]) {
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
//选择排序
//先假设一个值为最大或者最小值
function selectSort(arr){
for(var i = 0;i<arr.length;i++){
var minIndex = i;
for(var j = i;j<arr.length;j++){
if(arr[j]>arr[j+1]){
minIndex=j+1;
var temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
//快速排序
//找基准,遍历数组,小于基准的放在left,大于基准的放在right,最后递归
function quickSAort(arr){
if(arr.length<=1>)return arr;
var temp = arr[0],left=[],right =[];
for(var i = 1;i<arr.length;i++){
if(arr[i]<temp){
left.push(arr[i])
}else{
right.push(arr[i])
}
}
return [].concat(quickSort(left),temp,quickSort(right));
}
深拷贝
//深拷贝黑科技
JSON.parse(JSON.stringify(obj));
//存在问题:无法拷贝原型上的属性和方法
//递归实现
function deepCopy(obj) {
var newobj = obj.constructor === Array ? [] : {};
if (typeof obj !== "object") {
return obj;
} else {
for (var i in obj) {
//判断对象的这条属性是否为对象,//若是对象进行嵌套调用,否则直接赋值
newobj[i] = typeof obj[i] === "object" ? deepCopy(obj[i]) : obj[i];
}
}
return newobj; //返回深度克隆后的对象
}
拉平多维数组
//简便方法
function flatArr(arr) {
return arr.join(",").split(",");
}
//递归实现
function flat(arr) {
let arr1 = [];
arr.forEach((val) => {
if (val instanceof Array) {
arr1 = arr1.concat(flat(val));
} else {
arr1.push(val);
}
});
return arr1;
}
setTimeout模拟定时器
function mInterval() {
//要执行的逻辑
console.log(1);
//每次逻辑执行完,才会向队列添加事件
setTimeout(mInterval, 1000);
}
mInterval();
手写promise
promise
//判断变量是否是函数
function isFunction(variable) {
return typeof variable === "function";
}
//promise构造函数
function MyPromise(handle) {
if (!isFunction(handle)) {
throw new Error("必须传入一个函数");
}
this.status = "pending"; //状态,默认等待状态
this.value = ""; //值
this.onResolveCallbacks = []; //存放成功回调的数组
this.onRejectCallbacks = []; //存放失败回调的数组
var that = this;
try {
handle(resolve, reject);
} catch (err) {
reject(err); //有报错,状态直接变为rejected
}
function resolve(val) {
if (that.status == "pending") {
that.status = "resolved";
that.value = val;
that.onResolveCallbacks.forEach((fn) => {
fn();
});
}
}
function reject(err) {
if (that.status == "pending") {
that.status = "rejected";
that.value = err;
that.onRejectCallbacks.forEach((fn) => {
fn();
});
}
}
}
promise.then
MyPromise.prototype.then = function (sucFun, faildFun) {
//可选参数
//如果没有传,只负责把值往后传
sucFun = isFunction(sucFun) ? sucFun : (value) => value;
faildFun = isFunction(faildFun) ? faildFun : (value) => value;
var that = this;
//先改变了状态
if (this.status === "resolved") {
sucFun(this.value);
}
if (this.status === "rejected") {
faildFun(this.value);
}
//先指定了回调函数,状态还没改变
if (this.status === "pending") {
//存住回调函数,在异步操作完成时调用
this.onResolveCallbacks.push(() => {
sucFun(this.value);
});
this.onRejectCallbacks.push(() => {
faildFun(this.value);
});
}
return this;
};
promise.all
Promise.allFun = (arr) => {
return new Promise((resolve, reject) => {
var resolveArr = [],
rejectArr = [];
for (var i = 0; i < arr.length; i++) {
if (!(arr[i] instanceof Promise)) {
arr[i] = Promise.resolve(arr[i]);
}
arr[i]
.then((res) => {
resolveArr.push(res);
if (resolveArr.length == arr.length) {
resolve(resolveArr);
}
})
.catch((err) => {
rejectArr.push(err);
reject(rejectArr);
});
}
});
};
promise.race
myPromise.race = function (arr) {
return new Promise(function (resolve, reject) {
for (var i in arr) {
arr[i].then(resolve, reject);
}
});
};
实现一个并发请求控制方法
async function sendRequest(list, max = 4) {
return new Promise((resolve, reject) => {
let index = 0; //
let count = 0; //上传成功个数
const start = () => {
while (max > 0 && index < list.length) {
//剩余位置-1
max--;
let chunk = list[index];
index++;
request().then((res) => {
max++; //释放暂用位置
count++; //上传成功数量+1
if (count == list.length) {
resolve("完成了");
} else {
start();
}
});
}
};
start();
});
}
function request() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(1);
resolve(1);
}, 2000);
});
}
var list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1];
sendRequest(list, 4)
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log("上传失败了");
});
实现new
function new() {
//创建空对象
let obj = {};
//获取构造函数
let Constructor = Array.prototype.shift.call(arguments);
//绑定原型关系
obj.__proto__ = Constructor.prototype;
// 执行构造函数,即绑定 this,并且为这个新对象添加属性
Constructor.apply(newObj, arguments);
//返回新对象
return obj;
}
Object.create
新创建一个对象,使用传入对象作为新对象的原型对象
Object.create = function (obj) {
//创建空构造函数F
function F() {}
//F的prottotype指向obj
F.prtotype = obj;
//返回F实例
return new F();
};
输出数据类型
function getType(param){ if(param){ return Object.prototype.toString.call(param).split(' ')[1].split(']')[0]; }else{<br> console.log('参数不能为空')<br> } }
斐波那契数列
//给定位置,输出对应的值
function fib(n){
if(n==1||n==2){
return 1;
}
return fib(n-1)+fib(n-2)
}
浙公网安备 33010602011771号