飞道的博客

javascript面试必备知识(5)手撕js面试常见题型

407人阅读  评论(0)

js面试必备知识,关注作者查看系列js知识体系

导语:这一章来直接手撕web前端js面试常见题!

1,手写深拷贝函数

function deepClone(obj ={}) {
  if (typeof obj !== 'object' || obj == {}) {
    return obj
  }

  let result
  if (obj instanceof Array) {
    result = []
  } else {
    result = {}
  }

  for (let key in obj) {
    if (obj.hasOwmproperty(key)) {
      result[key] = deepClone(obj[key])
    }
  }

  return result
}

2,利用apply手写一个bind函数,bind函数返回什么东西?

bind函数返回的是一个函数,需要手动去执行。

//给function的显式原型添加一个bind1函数
Function.prototype.bind1 = function () {
  const args = Array.prototype.slice.call(arguments)		//转变成数组

  const that = args.shift()		//将第一项的this拿出来

  const self = this			//获取调用这个bind1的函数
  //返回一个函数
  return function () {
      return self.apply(that, args)
  }
}
function fun1(a, b) {
  console.log('this', this)
  console.log(a, b)
  return 'fun1'
}

const fun2 = fun1.bind1({x: 100}, 10, 20)		//劫持
const res = fun2()		//手动执行
console.log(res)

3,settimeout和setinterval区别,怎么让settimeout执行完再进行一个操作?

setTimeout和setInterval都属于JS中的定时器,可以规定延迟时间再执行某个操作,不同的是setTimeout在规定时间后执行完某个操作就停止了,而setInterval则可以一直循环下去。

// 封装成一个函数(settimeout后后续操作),参数分别是执行的次数,需要settimeout的函数,延迟几秒
function settimeoutdo(num,fn,delay){		
  var counter = 0;
  var d = jQuery.Deferred();

  var doIncrease = function() {
    if(counter < num){
        counter++;
        setTimeout(fn, delay);			//执行需要settimeout的函数
        setTimeout(doIncrease, delay);
    } else {
      d.resolve();
    }
  };
  doIncrease();
  return d.promise();
};

settimeoutdo(1,() => {console.log('123')},1000).then(function() {
  console.log(456);
});

4,手写简单的jQuery,需要考虑插件和扩展性。


class jQuery {
  constructor(selector) {
    const result = document.querySelectorAll(selector);
    const length = result.length;
    for (let i = 0; i < length; i++) {
      this[i] = result[i];
    }
    this.length = length;
    this.selector = selector;
  }
  get(index) {
    return this[index];
  }
  each(fn) {
    for (let i = 0; i < this.length; i++) {
      const elem = this[i];
      fn(elem);
    }
  }
  on(type, fn) {
    return this.each((elem) => {
      elem.addEventListener(type, fn, false);
    });
  }
}
// const $p = new jQuery('p')
// $p.get(1)
// $p.each((elem) => console.log(elem.nodeName))
// $p.on('click', () => alert('clicked'))

// 插件
jQuery.prototype.dialog = function (info) {
  alert(info);
};
// const $p = new jQuery('p')
// $p.dialog('dialog')

// "造轮子"
class myJQuery extends jQuery {
  constructor(selector) {
    super(selector);
  }
  // 扩展自己的方法
  addClass(className) {
    this.each((elem) => elem.classList.add(className));
  }
  style(data) {
    this.each((elem) => elem.classList.add(style));
  }
}
// const $p = new myJQuery('p')
// $p.addClass('test')

5,数组去重。


//n方时间复杂度
function newarr(arr){
  for (let i = 0; i < arr.length; i++){
    for (let j = i+1; j < arr.length; j++){
      if (arr[i] == arr[j]) { 
        arr.splice(j,1);      //如果arr[i]等于arr[j],splice方法删除arr[j]
        j--;
      }
    }
  }
  return arr;
}

var arr = [3,4,5,4,2,5,6,8,2,3,1];
console.log(newarr(arr))


//	n时间复杂度,但是占用了新的内存
function newarr(arr){ 
  var newarr = []; 
  for(var i = 0; i < arr.length; i++){ 
      if (newarr.indexOf(arr[i]) == -1){ 
          newarr.push(arr[i])
      }; 
  } 
  return newarr; 
}

var arr = [3,4,5,4,2,5,6,8,2,3,1];
console.log(newarr(arr))


//用set对象的特性给数组去重
let a = [3,4,5,4,2,5,6,8,2,3,1];
let b = new Set(a);
b = [...b];
console.log(b)

6,splice函数和slice函数的区别

splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目
ps:该方法会改变原始数组。

例子:arr.splice(1,1) //删除从第二个元素开始的一个元素。

slice() 方法可提取字符串或者数组的某个部分,并以新的字符串或者数组返回被提取的部分
ps:该方法不会改变原始字符串或者数组,而且还会产生一个新的字符串或者数组。

例子:newstr = str.slice(1,10) //提取从第二个元素到10个元素到newstr,共9个元素。

7,一分钟解决瀑布流布局

我总结在另外一篇博文里面了,请赐教!!
一分钟解决瀑布流布局,小白也能看懂

感谢阅读,持续更新中。。。


转载:https://blog.csdn.net/gitchatxiaomi/article/details/108036594
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场