前端面试知识点梳理——js基础面试题

422 阅读3分钟

var 和 let const的区别

  • var是ES5语法,let、const是ES6语法;var有变量提升
  • var和let是变量,可修改;const是常亮,不可修改
  • let const有块级作用域,var没有
// 变量提升
var a = 100
console.log(a)   //100

console.log(b)   //undefind
var b =200
//相当于
var b
console.log(b)
b = 200

console.log(d)   // b没有声明定义
let d = 20

// 块级作用域
for(let i = 0; i<10;i++){
    let j = i + 1
}
console.log(i,j)  //报错

typeof返回哪些类型

  • undefined string number boolean symbol
  • object
  • function

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

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

手写深度比较 lodash.isEqual(递归方法)

// 实现如下效果
const obj1 = {a: 10, b: {x: 100, y:200 }}
const obj2 = {a: 10, b: {x: 100, y:200 }}
isEqual(obj1, obj2) === true

function isObject(obj){
    return typeof obj === 'object' && obj != null
}
function isEqual(obj1,obj2){
    // 
    if(!isObject(obj1) || !isObject(obj2)){
        return obj === 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 
}

split() 和 join()的区别

  • 两者是相反的过程,split()是将字符串以某个标识来分割为数组,join()是将数组以某个标识来拼接为字符串。
'1-2-3'.split('-')   //[1,2,3]
[1,2,3].join('-')    // '1-2-3'

数组的 pop push unshift shit 分别是什么

  • 功能是什么
  • 返回值是什么
  • 是否对原数组造成影响
const arr = [10, 20, 30, 40]
// pop
const popRes = arr.pop()
console.log(popRes,arr)           // 40, [10, 20, 30]
// shift
const shiftRes = arr.shift()      //返回数组第一项
console.log(shiftRes,arr)         // 10,[20, 30, 40]
// push
const pushRes = arr.push(50)      //返回length
console.log(pushRes,arr)          // 5,[10,20,30,40,50]
// unshift
const unshiftRes = arr.unshift(5) //返回length
console.log(unshiftRes,arr)       // 5,[5,10,20,30,40]

// concat
const concatRes = arr.concat([50, 60])
console.log(concatRes,arr)        // [10, 20, 30, 40, 50, 60],[10, 20, 30, 40]
// map
const mapRes = arr.may(num => num * 10)
console.log(mapRes,arr)           // [100, 200, 300, 400],[10, 20, 30, 40]
// filter
const filterRes = arr.filter(num => num > 25)
console.log(filterRes,arr)        // [30, 40],[10, 20, 30, 40]
// slice
arr.slice() //类似深拷贝

// 纯函数(concat、map、filter、slice)
// 1、不改变源数组(没有副作用)
// 2、返回一个数组
// 非纯函数(pop、push、shift、unshift、forEach、some、every、reduce、splice)

数组slice 和 splice的区别

  • 功能区别(slice - 切片,splice - 剪接)
  • 参数和返回值
const arr = [10, 20, 30, 40, 50]
// slice 纯函数
const arr1 = arr.slice()      // [10, 20, 30, 40, 50]
const arr2 = arr.slice(1,4)   // [20, 30, 40]
const arr3 = arr.slice(2)     // [ 30, 40, 50]
const arr4 = arr.slice(-2)    // [ 40, 50]
//splice 非纯函数
const spliceRes = arr.splice(1, 2, 'a', 'b', 'c')
console.log(spliceRes,arr)    // [20, 30], [10, "a", "b", "c", 40, 50]

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

const arr = [10,20,30].map(parseInt)
console.log(arr) // [10, NaN,NaN]
// 拆解
[10,20,30].map((item,index)=>{
    parseInt(item,index)
    //parseInt(10,0)  10
    //parseInt(20,1)  NaN
    //parseInt(30,2)  NaN
})

ajax请求get和post的区别

  • get 一般用于查询操作,post一般用于用户提交操作
  • get参数拼接在url上,post参数放在请求体内

闭包有何影响

  • 变量会常驻内存,得不到释放。闭包不要乱用

阻止默认行为和冒泡

  • event.stopPropagation()
  • event.preventDefault()

如何减少DOM操作

  • 缓存DOM查询结果
  • 多次DOM操作,合并到一次插入(createDocumentFragment())

解释jsonp原理,为何不是真正的ajax

  • JSONP是JSON with Padding的略称。它是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
  • ajax 是通过 XMLHttpRequest请求

document load 和 ready的 区别

  • load:全部资源加载完成之后执行
  • ready:dom渲染完成即可执行

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

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

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

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

手写字符串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
}
Math.max()
Math.min()

如何捕获JS程序中的异常

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

什么JSON

  • json是一种数据格式,本质是一段字符串
  • json里的key和val,必须用双引号括起来
  • json格式和js对象结构一致,对js语言更友好
  • window.JSON是一个全局对象:JSON.stringify JSON.parse

手写获取当前页面url参数

// 传统方式
function query(name){
    const search = location.search.substr(1)  //类似array.slice()
    const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`,'i')
    const res = search.match(reg)
    if(res ===null){
        return null
    }
    return res[2]
}
// URLSearchParams (ie不兼容)
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)
}
const res = flat([1,2,[3,4]])
console.log(res)               // [1,2,3,4]

Array.prototype.flat([depth])  //默认为1,Infinity 无限层

数组去重

// 传统方式
function unique(arr){
    const res = []
    arr.forEach(item=>{
        if(res.indexOf(item)< 0){
            res.push(item)
        }
    })
}
unique([1,2,3,3,4,5])    //[1,2,3,4,5]

// 使用Set (无序,不能重复)
function unique(arr){
    const set = new Set(arr)
    return [...set]
}

数组排序

Array.prototype.sort.call(arguments)