前端手写面试题

this指向题目

let length = 10;
  function fn() {
    return this
  }
  var obj1 = {
    length: 5,
    test1: function () {
      return fn();
    },
    test3: function () {
      return this
    },
    test4: function () {
      setTimeout(function () {
        console.log(this)
      }, 500)
    },
    test5() {
      return {
        fn: () => {
          return this
        }
      }
    },
    test6() {
      setTimeout(() => {
        console.log(this)
      }, 500)
    }
  };
  obj1.test2 = fn;
  var obj2 = {
    length: 99
  }

  console.log(obj1.test1.call());//window
  console.log(obj1.test1());//window
  console.log(obj1.test2.call());//window
  console.log(obj1.test2());//obj1
  console.log(obj1.test4());//undefined
  console.log(obj1.test5().fn());//obj1
  console.log(obj1.test6());//undefined


//题2
var s1 = {
  lll:'s1',
  t1: function(){ // 测试this指向调用者
      return this
  },
  t2: () => { // 测试箭头函数,this并未指向调用者
      return this
  },
  t3: { // 测试对象中的对象
    tt1: function() {
        return this
    }
  },
  t4: { // 测试箭头函数以及非函数调用this并未指向调用者
    tt1: () => {
         return this
    }
  },
  t5: function(){ // 测试函数调用时箭头函数的this的指向,其指向了上一层对象的调用者
      return {
          tt1: () => {
            return this
          }
      }
  },
  t6: function(){
    return {
      tt2: nnn
    }
  },
  t7: function(){
    return nnn
  }
}
function nnn(){
  return this
}
// const nnn = () => {
//   return this
// }
console.log(s1.t1()); // s1对象 // 此处的调用者为 s1 所以打印对象为 s1
console.log(s1.t2()); // Window
console.log(s1.t3.tt1()); // s1.t3对象
console.log(s1.t4.tt1()); // Window
console.log(s1.t5().tt1()); // s1对象
console.log(s1.t6().tt2())//{tt2: ƒ}
console.log(s1.t7()())//window
复制代码

手写reduce

function reduceFn(a, f, init) {
  var i = 0,
    len = a.length,
    val;
  if (arguments.length > 2) {
    val = init;
  } else {
    while (i < len) {
      if (i in a) {
        val = a[i++];
        break;
      } else {
        i++;
      }
    }
  }
  while (i < len) {
    if (i in a) val = f.call(undefined, val, a[i], i, a);
    i++;
  }
  return val;
}
复制代码

手写eventBus

class eventBus {
  constructor(){
    this._event = this._event || new Object;
  }
}
eventBus.prototype.emit = function(type,...args){
  let e = this._event[type];
  console.log(e)
  if(Array.isArray(e)){
    for(let i=0;i<e.length;i++){
      e[i].call(this,...args)
    }
  }else{
    e.call(this,...args)
  }
}
eventBus.prototype.addListener = function(type,fn){
  e = this._event[type];
  if(e){
    this._event[type] = [...e,fn]
  }else{
    this._event[type] = [fn]
  }
}
let eventEmit = new eventBus()
eventEmit.addListener('arson', man => {
  console.log(`expel ${man}`);
});
eventEmit.addListener('arson', man => {
  console.log(`save ${man}`);
});

eventEmit.addListener('arson', man => {
  console.log(`kill ${man}`);
});

触发事件
eventEmit.emit('arson','test')
复制代码

手写call、apply、bind

Function.prototype._call = function (base, ...args) {
  base = base || window;
  base.fn = this;
  var result = base.fn(...args);
  delete base.fn;
  return result;
};
Function.prototype._apply = function (base, args) {
  base = base || window;
  base.fn = this;
  var result = base.fn(...args);
  delete base.fn;
  return result;
};
Function.prototype._bind = function (base, ...args1) {
  base = base || window;
  base.fn = this;
  return function (args2) {
    var result = base.fn(...args1, args2);
    delete base.fn;
    return result;
  };
};
复制代码

手写new

function _new(base, ...args) {
  let obj = {};
  obj.__proto__ = base.prototype;
  let res = base.apply(obj, args);
  return typeof base === "object" ? res : obj;
}
复制代码

简单深拷贝

function deepClone(list){
  if(list === null){
    return null
  }
  let arr = Array.isArray(list) ? [] : {};
  for(let i in list){
    if(list[i] && typeof list[i] === 'object'){
      arr[i] = deepClone(list[i])
    }else{
      arr[i] = list[i]
    }
  }
  return arr
}
复制代码

sleep

const sleep = (time) => {
  return new Promise((resolve) => {
    setTimeout(() => resolve(), time);
  });
};
sleep(1000).then(() => {
  console.log("sleep");
});
复制代码

手写promise相关

function _Promise(executor) {
  this.status = "pedding";
  this.value = null;
  this.reason = null;
  const resolve = (value) => {
    this.value = value;
    this.status = "resolved";
  };
  const reject = (reason) => {
    this.reason = reason;
    this.status = "rejected";
  };
  try {
    executor(resolve, reject);
  } catch (e) {
    reject(e);
  }
}
_Promise.prototype.then = function (resolve, reject) {
  setTimeout(() => {
    if (this.status === "resolved") {
      resolve(this.value);
    } else {
      reject(this.reason);
    }
  }, 0);
};

//promise.all
_Promise.prototype.all = function (arr) {
  return new Promise((resolve, reject) => {
    let count = 0,
      final = [];
    arr.forEach((ele, i) => {
      Promise.resolve(ele).then(
        (result) => {
          final[i] = result;
          if (++count === arr.length) {
            resolve(final);
          }
        },
        (reason) => {
          reject(reson);
        }
      );
    });
  });
};
复制代码

常见排序

function sortFn(arr){//冒泡
   for(let i=0;i<arr.length-1;i++){
     for(let j=0;j<arr.length-i-1;j++){
      if(arr[j]>arr[j+1]){
        let temp = arr[j];
        arr[j] = arr[j+1]
        arr[j+1] = temp
      }
     }
   }
   return arr
}
function sortFn(arr){//选择
  for(let i=0;i<arr.length-1;i++){
    let min = i;
    for(let j=i+1;j<arr.length;j++){
      if(arr[j]<arr[min]){
        min = j
      }
    }
    if(min !== i){
      let temp = arr[i]
      arr[i] = arr[min]
      arr[min] = temp
    }
  }
  return arr
}
function sortFn(arr){//插入
  for(let i=1;i<arr.length;i++){
    let j = i
    while(j>0&&arr[j-1]>arr[j]){
      let temp = arr[j-1]
      arr[j-1] = arr[j]
      arr[j] = temp
      j--
    }
  }
  return arr
}
function sortFn(arr) {
  //希尔排序
  let gap = Math.floor(arr.length / 2);
  while(gap>0){
    for(let i=gap;i<arr.length;i++){
      let j = i,temp = arr[j];
      while(j-gap>-1 && arr[j-gap] > temp){
        arr[j] = arr[j-gap]
        j = j - gap
      }
      arr[j] = temp
    }
    gap = Math.floor(gap / 2);
  }
  return arr;
}
function quickSort (arr) {//快排
    if (arr.length <= 1) return arr
    var arr1 = [], arr2 = []
    for (var i = 1; i < arr.length; i++) {
        if (arr[i] < arr[0]) {
            arr1.push(arr[i])
        } else {
            arr2.push(arr[i])
        }
    }
    arr1 = quickSort(arr1)
    arr2 = quickSort(arr2)
    arr1.push(arr[0])
    return arr1.concat(arr2)
}
function quickSort(arr,left,right){//快排优化版(首先排好左边)
    left = left || 0;
    right = right || arr.length-1;
    if(left<right){
        let index = getIndex(arr,left,right)//获取中间
        quickSort(arr,left,index-1)
        quickSort(arr,index+1,right)
    }
    return arr
}
function getIndex(arr,left,right){
    let index = left + 1;
    for(let i=index;i<=right;i++){
        if(arr[i]<arr[left]){
            swap(arr,index,i)
            index++
        }
    }
    swap(arr,left,index-1)
    return index-1
}
function swap(arr,index,i){
    let temp = arr[index]
    arr[index] = arr[i]
    arr[i] = temp
}
console.log(quickSort([1,3,99,2,66]))
复制代码

哈希路由原理

function Router() {
        this.routes = Object.create(null);
        this.view = null
    }
    Router.prototype.init = function (view) {
        this.view = view;
        this.refresh()
        window.addEventListener('hashchange', this.refresh.bind(this), false)
    }
    Router.prototype.refresh = function () {
        let path = window.location.hash, fn = this.routes[path];
        if (fn) {
            this.view.innerHTML = fn()
        }
        console.log(this.view, this.routes)
    }
    Router.prototype.route = function (path, callback) {
        this.routes[path] = () => this.view.innerHTML = callback() || '';

    }
    var testRoute = new Router();
    testRoute.init(document.getElementById('root'))
    testRoute.route('#/blue', function () {
        return '#/blue'
    })
    testRoute.route('#/green', function () {
        return '#/green'
    })
复制代码

手写map

function myMap(arr,fn,base){
    base = base || undefined
    let res=[]
    for(let i=0;i<arr.length;i++){
        res[i] = fn.call(base,arr[i],i)
    }
    return res
}
console.log(myMap([2,3,1,22],(item,...rest)=>{return item}))
复制代码

其他

function Foo() {
  Foo.a = function () {
    console.log(1);
  };
  this.a = function () {
    console.log(2,343434);
  };
}
Foo.prototype.a = function () {
  console.log(4);
};

Foo.a = 3;
var foo = new Foo()
console.log(foo.a,Foo.a);
foo.a()

复制代码
  1. 内联样式,如: style="...",权值为1000
  2. ID选择器,如:#content,权值为0100
  3. 类,伪类、属性选择器,如.content,权值为0010
  4. 类型选择器、伪元素选择器,如div p ::after,权值为0001
  5. 通配符、子选择器、相邻选择器等。如* > +,权值为0000
  6. 继承的样式没有权值

css3 为了区分两者,已经明确规定了伪类用一个冒号来表示,而伪元素则用两个冒号来表示

formData类型参数不需要设置contentType

分类:
前端
标签: