JavaScript基础面试
@ 姜波 | 星期二,七月 28 日,2020 年 | 4 分钟阅读 | 更新于 星期二,七月 28 日,2020 年

var和let、const的区别

  • var是ES5语法,let、const是ES6语法;var有变量提升
  • var和let是变量,可修改;const是常量,不可修改
  • let、const有块级作用域,var没有

typeof能判断哪些类型

  • underfined、string、number、boolean、symbol
  • object(typeof null === ‘object’)
  • function

列举强制类型转换和隐式类型转换

  • 强制:parseInt、parseFloat、toString等
  • 隐式:if、逻辑运算、==、+拼接字符串

手写深度比较,模拟lodash isEqual

function isObject(obj) {
  return typeof obj === 'object' && obj !== null
}
// 全相等
function isEqual(obj1, obj2) {
  if(isObject(obj1)||!isObject(obj2)) {
    // 值类型(一般不会是函数)
    return obj1 === obj2
  }
  if(obj1 === obj2) {
    return true
  }
  // 两个都是对象或数组,而且不相等
  // 1、先取出obj1和obj2的keys,比较个数
  const obj1Keys = Object.keys(obj1)
  const obj2Keys = Object.keys(obj2)
  if(obj1Keys.length !== obj2Keys.length) {
    return false
  }
  // 2、以obj1为基准,和obj2一次递归比较
  for(let key in obj1) {
    // 比较当前key的val--递归
    const res =isEqual(obj1[key], obj2[key])
    if(!res){
      return false
    }
  }
  // 3、全相等
  return true
}

数组的纯函数

  • concat
  • map
  • filter
  • slice

[10,20,30].map(parseInt)返回结果是什么

[10, 20, 30].map((num,index) => {
  return parseInt(num, index)
})

ajax请求get和post的区别

  • get一般用于查询操作,post一般用于提交操作
  • get参数拼接在url上,post放在请求体内(数据体积可更大)
  • 安全性:post易于防止CSRF

函数call和apply的区别

fn.call(this, p1, p2, p3)
fn.apply(this, arguments)

函数声明和函数表达式的区别

  • 函数声明function fn() {}
  • 函数表达式const fn = function() {}
  • 函数声明会在代码执行前预加载,而函数表达式不会

new Object()和Object.create()的区别

  • {}等同于new Object(),原型Object.prototype
  • Object.create(null)没有原型
  • Object.create({…})可指定原型

判断字符串以字母开头,后面字母数字下划线,长度6-30

const reg = /^[a-zA-Z]\w{5,29}$/

手写字符串trim方法,保证浏览器兼容性

String.prototype.trim = function() {
  return this.replace(/^\s+/,'').replace(/\s+$/,'')
}

如何获取多个数字中的最大值

function max() {
  const nums = Array.prototype.slice.call(arguments) // 变为数组
  let max = 0
  nums.forEach(n => {
    if(n>max){
      max = n
    }
  })
  return max
}

如何用JS实现继承

  • class继承
  • prototype继承

如何捕获JS程序中的异常

try{
  // todo
}catch(ex){
  console.error(ex) // 手动捕获catch
}finally{
  // todo
}

// 自动捕获
window.onerror = function(message, source, lineNum, colNum, error) {
  // 第一,对跨域的js,如CDN的,不会有详细的报错信息
  // 第二,对于压缩的js,还要配合sourceMap反查到未压缩代码的行、列
}

什么是JSON

  • json是一种数据格式,本质是一段字符串
  • json格式和JS对象结构一致,对JS语言更友好
  • window.JSON是一个全局对象:JSON.stringify、JSON.parse

获取当前页面url参数

// 传统方式
function query(name) {
  const search = location.search.substr(1) // 类似array.slice
  // search:'a=100&b=200&c=300'
  const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`,'i')
  const res = search.match(reg)
  if(res === null){
    return null
  }
  return res[2]
}

// URLSearchParams
function query(name) {
  const search = location.search
  const p = new URLSearchParams(search)
  return p.get(name)
}

手写数组flatern,考虑多层级

function flat(arr) {
  // 验证arr中,还有没有深层数组
  const isDeep = arr.some(item => item instanceof Array)
  if(!isDeep){
    return arr
  }
  const res = Array.prototype.concat.apply([],arr)
  return flat(res) // 递归
}

数组去重

// 传统方式
function unique(arr) {
  const res = []
  arr.forEach(item => {
    if(res.indexOf(item) < 0){
      res.push(item)
    }
  })
  return res
}

// 使用Set
function unique(arr) {
  const set = new Set(arr)
  return [...set]
}

手写深拷贝

function deepClone(obj = {}){
  if(typeof obj !== 'object' || obj == null){
    // obj是null,或者不是对象和数组,直接返回
    return obj
  }
  // 初始化返回结果
  let result
  if(obj instanceof Array){
    result = []
  }else{
    result = {}
  }
  
  for(let key in obj){
    // 保证key不是原型的属性
    if(obj.hasOwnProperty(key)){
      // 递归调用
      result[key] = deepClone(obj[key])
    }
  }
  
  // 返回结果
  return result
}

介绍RAF requestAnimationFrame

  • 想要动画流畅,更新频率要60帧/s,即16.67ms更新一次视图
  • setTimeout要手动控制频率,而RAF浏览器会自动控制
  • 后台标签或隐藏iframe中,RAF会暂停,而setTimeout依然执行

如何性能优化,从哪几个方面考虑

  • 原则:多使用内存、缓存,减少计算、减少网络请求
  • 方向:加载页面,页面渲染,页面操作流畅度

公众号

Image text

QQ

Image text

微信

Image text

微信打赏

Image text

社交链接