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)