前端常见手写面试题(持续更新中)

前端面试题(附答案)持续更新中…… 关于前端面试的题,这里整理了一些干货,经常被问到的一些问题,出现频率比较高的问题,如有不足之处,请大家指出,持续更新…(ps一到三颗代表重要性,选择性了解,掌握,前端需要知道的知识)盒模型由内容(content)、内边距(padding)、边框(border)、外边距(margin)组成。盒模型分为IE盒模型和W3C标准盒模型。W3C标准盒模型又叫content-box,元素宽度/高度由border+padding+content组成。(属性width,height只包含内容content,... 阅读详情

实现简单路由

// hash路由
class Route{
  constructor(){
    // 路由存储对象
    this.routes = {}
    // 当前hash
    this.currentHash = ''
    // 绑定this,避免监听时this指向改变
    this.freshRoute = this.freshRoute.bind(this)
    // 监听
    window.addEventListener('load', this.freshRoute, false)
    window.addEventListener('hashchange', this.freshRoute, false)
  }
  // 存储
  storeRoute (path, cb) {
    this.routes[path] = cb || function () {}
  }
  // 更新
  freshRoute () {
    this.currentHash = location.hash.slice(1) || '/'
    this.routes[this.currentHash]()
  }
}

实现forEach方法

Array.prototype.myForEach = function(callback, context=window) {
  // this=>arr
  let self = this,  
      i = 0,
      len = self.length;

  for(;i<len;i++) {
    typeof callback == 'function' && callback.call(context,self[i], i)
   }
}

实现观察者模式

观察者模式(基于发布订阅模式) 有观察者,也有被观察者

观察者需要放到被观察者中,被观察者的状态变化需要通知观察者 我变化了 内部也是基于发布订阅模式,收集观察者,状态变化后要主动通知观察者

class Subject { // 被观察者 学生
  constructor(name) {
    this.state = 'happy'
    this.observers = []; // 存储所有的观察者
  }
  // 收集所有的观察者
  attach(o){ // Subject. prototype. attch
    this.observers.push(o)
  }
  // 更新被观察者 状态的方法
  setState(newState) {
    this.state = newState; // 更新状态
    // this 指被观察者 学生
    this.observers.forEach(o => o.update(this)) // 通知观察者 更新它们的状态
  }
}

class Observer{ // 观察者 父母和老师
  constructor(name) {
    this.name = name
  }
  update(student) {
    console.log('当前' + this.name + '被通知了', '当前学生的状态是' + student.state)
  }
}

let student = new Subject('学生'); 

let parent = new Observer('父母'); 
let teacher = new Observer('老师'); 

// 被观察者存储观察者的前提,需要先接纳观察者
student. attach(parent); 
student. attach(teacher); 
student. setState('被欺负了');

实现apply方法

思路: 利用this的上下文特性。apply其实就是改一下参数的问题

Function.prototype.myApply = function(context = window, args) {
  // this-->func  context--> obj  args--> 传递过来的参数

  // 在context上加一个唯一值不影响context上的属性
  let key = Symbol('key')
  context[key] = this; // context为调用的上下文,this此处为函数,将这个函数作为context的方法
  // let args = [...arguments].slice(1)   //第一个参数为obj所以删除,伪数组转为数组

  let result = context[key](...args); // 这里和call传参不一样

  // 清除定义的this 不删除会导致context属性越来越多
  delete context[key]; 

  // 返回结果
  return result;
}
// 使用
function f(a,b){
 console.log(a,b)
 console.log(this.name)
}
let obj={
 name:'张三'
}
f.myApply(obj,[1,2])  //arguments[1]

基于Generator函数实现async/await原理

核心:传递给我一个Generator函数,把函数中的内容基于Iterator迭代器的特点一步步的执行

function readFile(file) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(file);
    }, 1000);
    })
};

function asyncFunc(generator) {
    const iterator = generator(); // 接下来要执行next
  // data为第一次执行之后的返回结果,用于传给第二次执行
  const next = (data) => {
        let { value, done } = iterator.next(data); // 第二次执行,并接收第一次的请求结果 data

    if (done) return; // 执行完毕(到第三次)直接返回
    // 第一次执行next时,yield返回的 promise实例 赋值给了 value
    value.then(data => {
      next(data); // 当第一次value 执行完毕且成功时,执行下一步(并把第一次的结果传递下一步)
    });
  }
  next();
};

asyncFunc(function* () {
    // 生成器函数:控制代码一步步执行 
  let data = yield readFile('a.js'); // 等这一步骤执行执行成功之后,再往下走,没执行完的时候,直接返回
  data = yield readFile(data + 'b.js');
  return data;
})

数组中的数据根据key去重

给定一个任意数组,实现一个通用函数,让数组中的数据根据 key 排重:

const dedup = (data, getKey = () => {} ) => {
  // todo
}
let data = [
  { id: 1, v: 1 },
  { id: 2, v: 2 },
  { id: 1, v: 1 },
];

// 以 id 作为排重 key,执行函数得到结果
// data = [
//   { id: 1, v: 1 },
//   { id: 2, v: 2 },
// ];

实现

const dedup = (data, getKey = () => { }) => {
    const dateMap = data.reduce((pre, cur) => {
        const key = getKey(cur)
        if (!pre[key]) {
            pre[key] = cur
        }
        return pre
    }, {})
    return Object.values(dateMap)
}

使用

let data = [
    { id: 1, v: 1 },
    { id: 2, v: 2 },
    { id: 1, v: 1 },
];
console.log(dedup(data, (item) => item.id))

// 以 id 作为排重 key,执行函数得到结果
// data = [
//   { id: 1, v: 1 },
//   { id: 2, v: 2 },
// ];

实现map方法

  • 回调函数的参数有哪些,返回值如何处理
  • 不修改原来的数组
Array.prototype.myMap = function(callback, context){
  // 转换类数组
  var arr = Array.prototype.slice.call(this),//由于是ES5所以就不用...展开符了
      mappedArr = [], 
      i = 0;

  for (; i < arr.length; i++ ){
    // 把当前值、索引、当前数组返回去。调用的时候传到函数参数中 [1,2,3,4].map((curr,index,arr))
    mappedArr.push(callback.call(context, arr[i], i, this));
  }
  return mappedArr;
}

实现redux-thunk

redux-thunk 可以利用 redux 中间件让 redux 支持异步的 action

// 如果 action 是个函数,就调用这个函数
// 如果 action 不是函数,就传给下一个中间件
// 发现 action 是函数就调用
const thunk = ({ dispatch, getState }) => (next) => (action) => {
  if (typeof action === 'function') {
    return action(dispatch, getState);
  }

  return next(action);
};
export default thunk

原生实现

function ajax() {
  let xhr = new XMLHttpRequest() //实例化,以调用方法
  xhr.open('get', 'https://www.google.com')  //参数2,url。参数三:异步
  xhr.onreadystatechange = () => {  //每当 readyState 属性改变时,就会调用该函数。
    if (xhr.readyState === 4) {  //XMLHttpRequest 代理当前所处状态。
      if (xhr.status >= 200 && xhr.status < 300) {  //200-300请求成功
        let string = request.responseText
        //JSON.parse() 方法用来解析JSON字符串,构造由字符串描述的JavaScript值或对象
        let object = JSON.parse(string)
      }
    }
  }
  request.send() //用于实际发出 HTTP 请求。不带参数为GET请求
}

参考:前端手写面试题详细解答

实现模板字符串解析功能

let template = '我是{{name}},年龄{{age}},性别{{sex}}';
let data = {
  name: '姓名',
  age: 18
}
render(template, data); // 我是姓名,年龄18,性别undefined
function render(template, data) {
  const reg = /\{\{(\w+)\}\}/; // 模板字符串正则
  if (reg.test(template)) { // 判断模板里是否有模板字符串
    const name = reg.exec(template)[1]; // 查找当前模板里第一个模板字符串的字段
    template = template.replace(reg, data[name]); // 将第一个模板字符串渲染
    return render(template, data); // 递归的渲染并返回渲染后的结构
  }
  return template; // 如果模板没有模板字符串直接返回
}

实现filter方法

Array.prototype.myFilter=function(callback, context=window){

  let len = this.length
      newArr = [],
      i=0

  for(; i < len; i++){
    if(callback.apply(context, [this[i], i , this])){
      newArr.push(this[i]);
    }
  }
  return newArr;
}

实现new的过程

new操作符做了这些事:

  • 创建一个全新的对象
  • 这个对象的__proto__要指向构造函数的原型prototype
  • 执行构造函数,使用 call/apply 改变 this 的指向
  • 返回值为object类型则作为new方法的返回值返回,否则返回上述全新对象
function myNew(fn, ...args) {
  // 基于原型链 创建一个新对象
  let newObj = Object.create(fn.prototype);
  // 添加属性到新对象上 并获取obj函数的结果
  let res = fn.apply(newObj, args); // 改变this指向

  // 如果执行结果有返回值并且是一个对象, 返回执行的结果, 否则, 返回新创建的对象
  return typeof res === 'object' ? res: newObj;
}
// 用法
function Person(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.say = function() {
  console.log(this.age);
};
let p1 = myNew(Person, "poety", 18);
console.log(p1.name);
console.log(p1);
p1.say();

实现every方法

Array.prototype.myEvery=function(callback, context = window){
    var len=this.length,
        flag=true,
        i = 0;

    for(;i < len; i++){
      if(!callback.apply(context,[this[i], i , this])){
        flag=false;
        break;
      } 
    }
    return flag;
  }


  // var obj = {num: 1}
  // var aa=arr.myEvery(function(v,index,arr){
  //     return v.num>=12;
  // },obj)
  // console.log(aa)

实现findIndex方法

var users = [
  {id: 1, name: '张三'},
  {id: 2, name: '张三'},
  {id: 3, name: '张三'},
  {id: 4, name: '张三'}
]

Array.prototype.myFindIndex = function (callback) {
  // var callback = function (item, index) { return item.id === 4 }
  for (var i = 0; i < this.length; i++) {
    if (callback(this[i], i)) {
      // 这里返回
      return i
    }
  }
}

var ret = users.myFind(function (item, index) {
  return item.id === 2
})

console.log(ret)

实现发布订阅模式

简介:

发布订阅者模式,一种对象间一对多的依赖关系,但一个对象的状态发生改变时,所依赖它的对象都将得到状态改变的通知。

主要的作用(优点):

  1. 广泛应用于异步编程中(替代了传递回调函数)
  2. 对象之间松散耦合的编写代码

缺点:

  • 创建订阅者本身要消耗一定的时间和内存
  • 多个发布者和订阅者嵌套一起的时候,程序难以跟踪维护

实现的思路:

  • 创建一个对象(缓存列表)
  • on方法用来把回调函数fn都加到缓存列表中
  • emit 根据key值去执行对应缓存列表中的函数
  • off方法可以根据key值取消订阅
class EventEmiter {
  constructor() {
    // 事件对象,存放订阅的名字和事件
    this._events = {}
  }
  // 订阅事件的方法
  on(eventName,callback) {
    if(!this._events) {
      this._events = {}
    }
    // 合并之前订阅的cb
    this._events[eventName] = [...(this._events[eventName] || []),callback]
  }
  // 触发事件的方法
  emit(eventName, ...args) {
    if(!this._events[eventName]) {
      return
    }
    // 遍历执行所有订阅的事件
    this._events[eventName].forEach(fn=>fn(...args))
  }
  off(eventName,cb) {
    if(!this._events[eventName]) {
      return
    }
    // 删除订阅的事件
    this._events[eventName] = this._events[eventName].filter(fn=>fn != cb && fn.l != cb)
  }
  // 绑定一次 触发后将绑定的移除掉 再次触发掉
  once(eventName,callback) {
    const one = (...args)=>{
      // 等callback执行完毕在删除
      callback(args)
      this.off(eventName,one)
    }
    one.l = callback // 自定义属性
    this.on(eventName,one)
  }
}

测试用例

let event = new EventEmiter()

let login1 = function(...args) {
  console.log('login success1', args)
}
let login2 = function(...args) {
  console.log('login success2', args)
}
// event.on('login',login1)
event.once('login',login2)
event.off('login',login1) // 解除订阅
event.emit('login', 1,2,3,4,5)
event.emit('login', 6,7,8,9)
event.emit('login', 10,11,12)  

发布订阅者模式和观察者模式的区别?

  • 发布/订阅模式是观察者模式的一种变形,两者区别在于,发布/订阅模式在观察者模式的基础上,在目标和观察者之间增加一个调度中心。
  • 观察者模式是由具体目标调度,比如当事件触发,Subject 就会去调用观察者的方法,所以观察者模式的订阅者与发布者之间是存在依赖的。
  • 发布/订阅模式由统一调度中心调用,因此发布者和订阅者不需要知道对方的存在。

实现reduce方法

  • 初始值不传怎么处理
  • 回调函数的参数有哪些,返回值如何处理。
Array.prototype.myReduce = function(fn, initialValue) {
  var arr = Array.prototype.slice.call(this);
  var res, startIndex;

  res = initialValue ? initialValue : arr[0]; // 不传默认取数组第一项
  startIndex = initialValue ? 0 : 1;

  for(var i = startIndex; i < arr.length; i++) {
    // 把初始值、当前值、索引、当前数组返回去。调用的时候传到函数参数中 [1,2,3,4].reduce((initVal,curr,index,arr))
    res = fn.call(null, res, arr[i], i, this); 
  }
  return res;
}

实现Array.of方法

Array.of()方法用于将一组值,转换为数组

  • 这个方法的主要目的,是弥补数组构造函数Array()的不足。因为参数个数的不同,会导致Array()的行为有差异。
  • Array.of()基本上可以用来替代Array()new Array(),并且不存在由于参数不同而导致的重载。它的行为非常统一
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1

实现

function ArrayOf(){
  return [].slice.call(arguments);
}

实现一个compose函数

组合多个函数,从右到左,比如:compose(f, g, h) 最终得到这个结果 (...args) => f(g(h(...args))).

题目描述:实现一个 compose 函数

// 用法如下:
function fn1(x) {
  return x + 1;
}
function fn2(x) {
  return x + 2;
}
function fn3(x) {
  return x + 3;
}
function fn4(x) {
  return x + 4;
}
const a = compose(fn1, fn2, fn3, fn4);
console.log(a(1)); // 1+4+3+2+1=11

实现代码如下

function compose(...funcs) {
  if (!funcs.length) return (v) => v;

  if (funcs.length === 1) {
    return funcs[0]
  }

  return funcs.reduce((a, b) => {
    return (...args) => a(b(...args)))
  }
}

compose创建了一个从右向左执行的数据流。如果要实现从左到右的数据流,可以直接更改compose的部分代码即可实现

  • 更换Api接口:把reduce改为reduceRight
  • 交互包裹位置:把a(b(...args))改为b(a(...args))

数组去重方法汇总

首先:我知道多少种去重方式

1. 双层 for 循环

function distinct(arr) {
    for (let i=0, len=arr.length; i<len; i++) {
        for (let j=i+1; j<len; j++) {
            if (arr[i] == arr[j]) {
                arr.splice(j, 1);
                // splice 会改变数组长度,所以要将数组长度 len 和下标 j 减一
                len--;
                j--;
            }
        }
    }
    return arr;
}

思想: 双重 for 循环是比较笨拙的方法,它实现的原理很简单:先定义一个包含原始数组第一个元素的数组,然后遍历原始数组,将原始数组中的每个元素与新数组中的每个元素进行比对,如果不重复则添加到新数组中,最后返回新数组;因为它的时间复杂度是O(n^2),如果数组长度很大,效率会很低

2. Array.filter() 加 indexOf/includes

function distinct(a, b) {
    let arr = a.concat(b);
    return arr.filter((item, index)=> {
        //return arr.indexOf(item) === index
        return arr.includes(item)
    })
}

思想: 利用indexOf检测元素在数组中第一次出现的位置是否和元素现在的位置相等,如果不等则说明该元素是重复元素

3. ES6 中的 Set 去重

function distinct(array) {
   return Array.from(new Set(array));
}

思想: ES6 提供了新的数据结构 Set,Set 结构的一个特性就是成员值都是唯一的,没有重复的值。

4. reduce 实现对象数组去重复

var resources = [
    { name: "张三", age: "18" },
    { name: "张三", age: "19" },
    { name: "张三", age: "20" },
    { name: "李四", age: "19" },
    { name: "王五", age: "20" },
    { name: "赵六", age: "21" }
]
var temp = {};
resources = resources.reduce((prev, curv) => {
 // 如果临时对象中有这个名字,什么都不做
 if (temp[curv.name]) {

 }else {
    // 如果临时对象没有就把这个名字加进去,同时把当前的这个对象加入到prev中
    temp[curv.name] = true;
    prev.push(curv);
 }
 return prev
}, []);
console.log("结果", resources);

这种方法是利用高阶函数 reduce 进行去重, 这里只需要注意initialValue得放一个空数组[],不然没法push

实现bind方法

bind 的实现对比其他两个函数略微地复杂了一点,涉及到参数合并(类似函数柯里化),因为 bind 需要返回一个函数,需要判断一些边界问题,以下是 bind 的实现

  • bind 返回了一个函数,对于函数来说有两种方式调用,一种是直接调用,一种是通过 new 的方式,我们先来说直接调用的方式
  • 对于直接调用来说,这里选择了 apply 的方式实现,但是对于参数需要注意以下情况:因为 bind 可以实现类似这样的代码 f.bind(obj, 1)(2),所以我们需要将两边的参数拼接起来
  • 最后来说通过 new 的方式,对于 new 的情况来说,不会被任何方式改变 this,所以对于这种情况我们需要忽略传入的 this

简洁版本

  • 对于普通函数,绑定this指向
  • 对于构造函数,要保证原函数的原型对象上的属性不能丢失
Function.prototype.myBind = function(context = window, ...args) {
  // this表示调用bind的函数
  let self = this;

  //返回了一个函数,...innerArgs为实际调用时传入的参数
  let fBound = function(...innerArgs) { 
      //this instanceof fBound为true表示构造函数的情况。如new func.bind(obj)
      // 当作为构造函数时,this 指向实例,此时 this instanceof fBound 结果为 true,可以让实例获得来自绑定函数的值
      // 当作为普通函数时,this 指向 window,此时结果为 false,将绑定函数的 this 指向 context
      return self.apply(
        this instanceof fBound ? this : context, 
        args.concat(innerArgs)
      );
  }

  // 如果绑定的是构造函数,那么需要继承构造函数原型属性和方法:保证原函数的原型对象上的属性不丢失
  // 实现继承的方式: 使用Object.create
  fBound.prototype = Object.create(this.prototype);
  return fBound;
}
// 测试用例

function Person(name, age) {
  console.log('Person name:', name);
  console.log('Person age:', age);
  console.log('Person this:', this); // 构造函数this指向实例对象
}

// 构造函数原型的方法
Person.prototype.say = function() {
  console.log('person say');
}

// 普通函数
function normalFun(name, age) {
  console.log('普通函数 name:', name); 
  console.log('普通函数 age:', age); 
  console.log('普通函数 this:', this);  // 普通函数this指向绑定bind的第一个参数 也就是例子中的obj
}


var obj = {
  name: 'poetries',
  age: 18
}

// 先测试作为构造函数调用
var bindFun = Person.myBind(obj, 'poetry1') // undefined
var a = new bindFun(10) // Person name: poetry1、Person age: 10、Person this: fBound {}
a.say() // person say

// 再测试作为普通函数调用
var bindNormalFun = normalFun.myBind(obj, 'poetry2') // undefined
bindNormalFun(12) // 普通函数name: poetry2 普通函数 age: 12 普通函数 this: {name: 'poetries', age: 18}

注意: bind之后不能再次修改this的指向,bind多次后执行,函数this还是指向第一次bind的对象

前端_面试题持续更新中) 本文系统整理了前端开发常见面试题,涵盖HTML、CSS、Vue、路由和JavaScript五大模块。HTML部分详解了元素分类、H5新特性和存储方案;CSS部分包含新特性、样式隔离和布局定位;Vue部分重点剖析了MVVM原理、生命周期、组件通信和性能优化;路由部分对比了两种模式及传参方式;JavaScript部分区分了变量声明、异步请求和性能优化策略。全文采用问答形式,既包含基础概念解析,又提供实际应用场景,帮助开发者全面掌握前端核心知识体系,特别适合面试复习和技术查漏补缺。 阅读详情

相关推荐

最新前端面试题精编2020持续更新

文档描述 本文是关注微信小程序的开发和面试问题, 由基础到困难循序渐进, 适合面试和开发小程序。 并有热点框架(vue react node.js 全栈)前端资源以及后端视频资源和源码 并基于前端进阶和面试的需求 总结了常用插件和js算法 以及html/css 和js热点面试题 文档答案(更多面试题和答案) Vue面试题 生命周期函数面试题 1.什么是 vue 生命周期 2.vue...

MingL520的博客 9053

2022必会的前端手写面试题

面试题视频讲解(高效学习):进入学习 二、题目 1. 防抖节流 这也是一个经典题目了,首先要知道什么是防抖,什么是节流。 防抖: 在一段时间内,事件只会最后触发一次。 节流: 事件,按照一段时间的间隔来进行触发。 实在不懂的话,可以去这个大佬的Demo地址玩玩防抖节流DEMO // 防抖 function debounce(fn) { let timeout = null; return function () {

潇晨1998的博客 591

前端面试题总结(js、html、小程序、React、ES6、Vue、算法、全栈热门视频资源)持续更新

文档描述 本文是关注微信小程序的开发和面试问题, 由基础到困难循序渐进, 适合面试和开发小程序。 并有热点框架(vue react node.js 全栈)前端资源以及后端视频资源和源码 并基于前端进阶和面试的需求 总结了常用插件和js算法 以及html/css和js热点面试题 因为csdn不可以有外链 所以答案链接在评论区!!! Vue面试题 生命周期函数面试题 1.什么是...

MingL520的博客 8万+

前端面试常见手写代码题【详细篇】

前端面试中,经常会遇到防抖 、节流、函数柯里化、函数组合、instanceof 实现、实现new操作符的行为、深拷贝、继承实现:、手写Promise、数组中常见函数的实现等代码手写题,本文都已全部列举

前端探索者 3105

二叉树的遍历(JS版)

二叉树的遍历有深度优先和广度优先两种。前序、中序、后序遍历都属于深度优先遍历。层次遍历属于广度优先遍历,从上到下,从左到右或从右到左一层一层的遍历。 1、二叉树的深度优先遍历-递归 // 前/先序:根左右 var DLR = function(root, res) { if(!root) return ; res.push(root.val); root.lef...

chengzihy的专栏 1576

前端面试手写题目总结

【代码】面试手写题目总结。

qq_48896417的博客 1189

2024前端面试12个手写题,你确定会?

万丈高楼平地起,地基打的牢,才能永远立于不败之地。今天给大家带来的是10常见JavaScript 手写功能,重要的地方已添加注释。有的是借鉴别人的,有的是自己写的,如有不正确的地方,欢迎多多指正。

富朝阳的博客 1656

2024最新最全的前端面试题集锦(2024 持续更新...敬请关注)

工作以来,感觉自己接触到的东西还是挺多的,但是当我面试的时候,就会发现各种问题,很多知识点都是模棱两可,答得不全面。究其原因,还是没有吃透这些内容。所以我决定,用几个月的时间,将我们大前端的大部分精选面试题进行整理,将大部分知识点进行归纳总结,为自己也为其他小伙伴们提供一份面试学习参考。

XH_jing的博客 2万+

前端面试题汇总大全(含答案)-- 持续更新

汇总了一些前端常见面试题。 一、HTML 篇 1. 简述一下你对 HTML 语义化的理解? 用正确的标签做正确的事情。 html 语义化让页面的内容结构化,结构更清晰,便于对浏览器、搜索引擎解析;即使在没有样式 CSS 情况下也以一种文档格式显示,并且是容易阅读的; 搜索引擎的爬虫也依赖于 HTML 标记来确定上下文和各个关键字的权重,利于 SEO; 使阅读源代码的人对网站更容易将网站...

张兴华的博客 19万+

2022年最新前端面试题持续更新

2022年最新前端面试题 适合初/中级前端开发工程师

qq_45165744的博客 6万+

持续更新】汇总了一份前端领域必看面试题

前端天花板确实低,VP很少见?尽头小组长?撒一把米放键盘上?对于前端的梗很多,但是这都不重要!深耕自己的领域,你就是专家!

吴秋霖的博客 1万+

前端面试题库-面试前刷刷题,持续更新

写在前面 现在面试文章已很多,更不觉得新鲜,本文可能有点不同,正因为“多”也就才有了本文的输出。 相信很多前端小伙伴也包括我在内,面试前都要做一些准备,而做做面试题是最平常不过的事儿了,然而每次面试前都要现找面试题,而且答案也不是现成的,其实这样重复的事情在不知不觉中浪费你很多时间。 也就因为发现了这个问题,才有了把面试题进行整理的想法,希望能对一些人有所帮助,节省一点时间吧。 题目整理 这1个多...

zz_jesse的博客 4294

前端面试题持续更新中)

前端面试题 1.闭包 闭包就是能够读取其他函数内部变量的函数。 闭包的缺点:滥用闭包函数会造成内存泄露,因为闭包中引用到的包裹函数中定义的变量都 永远不会被释放,所以我们应该在必要的时候,及时释放这个闭包函数本 2.数据类型 基本数据类型:String,Boolean,number,Null,undefined,object, 字符串 布尔 数值 空值 未定义 对象 引用数据类型:Objec...

weixin_39940684的博客 1万+

中级前端常见面试题(附答案),持续更新

文章目录Q:JS有哪些数据类型?7种基本类型1种引用类型Q:ES6数据结构 Set / MapSetMapQ:call, apply, bind 用法和区别call() 和 apply()bind()Q:new 的执行过程1. 在内存中创建了一个实例对象(内容为空)2. 设置该实例对象的\__proto__属性指向构造函数的prototype原型对象3. 使用该实例对象stu1调用构造函数,改变构造函数中的this指向为实例对象stu14. 返回刚刚创建好的实例对象Q:JS常见的内存泄漏1. 意外的全局变量

TrumanGao的博客 1万+

京东前端二面高频手写面试题持续更新中)

判断对象是否存在循环引用 循环引用对象本来没有什么问题,但是序列化的时候就会发生问题,比如调用对该类对象进行序列化,就会报错: 下面方法可以用来判断一个对象中是否已存在循环引用: 查找有序二维数组的目标值: 二维数组斜向打印: 手写 Promise 实现Promise相关方法 实现Promise的resolve 传参为一个 , 则直接返回它。 传参为一个 对象,返回的 会跟随这个对象,采用它的最终状态作为自己的状态。 其他情况,直接返回以该值为成功状态的对象。 实现 Promise.rejec

helloworld1024fd的博客 412

一到三年经验前端面试题总结——看完这些月薪过万没问题(持续更新中)

前言: 目前大三,在准备秋招的路上,没有实习经验,以下是根据自己复习的资料和面试遇到的问题整理出来的,后面逐渐更新,复习用!!希望大家都能找到满意的工作 我自己的技术栈是vue加小程序,所以react这方面写的少 一、思想 1、说一下你是怎么学习前端的? 二、html css html5和css3阶段 说一下三栏布局,两边固定,中间自适应,五种 bfc 三、js JQuery js基本数据类型和基本数据类型的区别 js数据类型的检测和装换 relpace说一下用法 四、 ES6,7,8,9,10 什么

十九万里的博客 6219

前端面试题(持续更新中~)

CSS3 中伪元素after和before,盒模型概念,元素居中方法,防抖和节流,深拷贝和浅拷贝,forEach用什么方法结束,怎么结束for循环的一层,forin和forof,如果要取数组第100条数据,怎么取,数组哪些方法改变原数组哪些方法不改变原数组,SSR服务端渲染流程及SEO,服务端渲染框架,前端项目中环境变量怎么处理,怎么配置,axios有封装过吗,后台管理侧边栏权限管,简述TCP/IP,UDP,对于SEO怎么优化,后台管理登录流程,解决Git冲突

weixin_57844432的博客 1万+

2024前端常见面试题持续更新中)

function funOne(){ // 外部函数// 局部变量function funTwo(){ // 内部函数num++;return num;// 返回函数 funTwo宏任务包括:setTimeout setInterval Ajax DOM事件,宏任务是由宿主(浏览器、Node)发起的,宏任务,可以理解为每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行).进程的切换肯定是宏任务,因为需要花费大量的资源。

lakewind6的博客 1029
上一篇: 手写JS函数的call、apply、bind
下一篇: 怎样徒手写一个React
helloworld1024fd
博客等级 码龄4年 244粉丝 243原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值