var和let const的区别
- var是ES5语法,let const是ES6语法;var有提升变量
- var和let是变量可修改;const是常量,不可修改
- let const有块级作用域,var没有
-
- *
typeof返回哪些类型
- undefined
- string
- number
- boolean
- symbol
- object(typeof null === 'object')
- function
-
- *
列举强制类型转换和隐式类型转换
强制:parseInt parseFloat toString
隐式:if、逻辑运算、==、+拼接字符串
手写深度比较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的value值
const res = isEqual(obj1[key],obj2[key])
if(!res){
return false
}
}
return true
}
const obj1 = {
a:100,
b:{
x:100,
y:200
}
}
const obj2 = {
a:100,
b:{
x:100,
y:200
}
}
split()和join()的区别
'1-2-3'.split('-') //[1,2,3]
[1,2,3].join('-') //'1-2-3'
数组的pop push unshift shift分别是什么
- pop 在末尾删除一个值,返回的是数组最后的一个值
const arr = [10,20,30,40]
const popRes = arr.pop()
console.log(popRes) //40
console.log(arr) //[10,20,30]
- push 在数组末尾插入一个数值,返回的是数组的长度
const arr = [10,20,30,40]
const pushRes = arr.push(50)
console.log(pushRes) // 5
console.log(arr) //[10,20,30,40,50]
- unshift 在数组第一位插入一个值,返回的是数组的长度
const arr = [10,20,30,40]
const unshiftRes = arr.unshift(5)
console.log(unshiftRes) // 5
console.log(arr) //[5,10,20,30,40]
- shift 删除数组第一个值,返回的是数组的被删除的值
const arr = [10,20,30,40]
const shiftRes = arr.shift(5)
console.log(shiftRes) // 10
console.log(arr) //[20,30,40]
纯函数
1、不改变原数组(没有副作用)
2、返回的是一个数组
concat
const arr = [10,20,30,40]
const arr1 = arr.concat([50,60,70])
console.log(arr) //[10,20,30,40]
console.log(arr1) //[10,20,30,40,50,60,70]
map
const arr = [10,20,30,40]
const arr2 = arr.map(num=>num*10)
console.log(arr) //[10,20,30,40]
console.log(arr2) //[100,200,300,400]
filter
const arr = [10,20,30,40]
const arr3 = arr.filter(num=>num>25)
console.log(arr) //[10,20,30,40]
console.log(arr3) //[30,40]
slice
const arr = [10,20,30,40]
const arr4 = arr.slice()
console.log(arr) //[10,20,30,40]
console.log(arr4) //[10,20,30,40]
slice和splice的区别
slice纯函数
const arr = [10,20,30,40,50]
const arr1 = arr.slice(1,4) //第一个参数为从第几个位置开始,第二个参数为到第几个位置前结束
const arr2 = arr.slice(2)
const arr3 = arr.slice(-2) //截取最后两位
console.log(arr1) //[20,30,40]
console.log(arr2) //[30,40,50]
console.log(arr3) //[40,50]
splice非纯函数
const arr = [10,20,30,40,50]
const spliceRes = arr.splice(1,2,'a','b','c')//参数含义:把第一个参数到第二个参数位置剪切下来,把后面的参数放在剪切区域内
console.log(arr) //[10,'a','b','c',40,50]
console.log(spliceRes) //[20,30]
[10,20,30].map(parseInt)
const res = [10,20,30].map(parseInt)
console.log(res) //[10,NaN,NaN]
//拆解
[10,20,30].map((num,index) = >{
return parseInt(num,index)
})
ajax请求get和post的区别
- get在浏览器回退是无害的,而post则会再次提交请求
- get产生的url地址可以被收藏,而post不可以
- get请求会被浏览器主动缓存,而post不会,除非手动设置
- get请求只能进行url编码,而post支持多种编码方式
- get请求参数会被完整的保存在浏览器历史记录里,而post参数不会被保留
- get请求在url中传送参数是有长度限制的,而post没有限制
- 对参数的数据类型,get只接受ASCLL字符,而post没有限制
- get比post更不安全,因为参数直接暴漏在url上,不能传递敏感信息
- get参数通过url传递,post放在request body中
-
- *
JavaScript中 call和apply
apply()方法 接收两个参数,一个是函数运行的作用域(this),另一个是参数数组。
call()方法 第一个参数和apply()方法的一样,但是传递给函数的参数必须列举出来。
阻止事件冒泡和默认行为
event.stopPropagation()
event.preventDefault()
查找、添加、移动、删除Dom节点
const div1 = document.getElementById("div1")
//添加新节点
const newP = document.createElement('p')
newP.innerHTML = "this is p1"
div1.appendChild(newP)//添加新创建的元素
//移动已有节点,注意是移动
const p2 = document.getElementById('p2')
div1.appendChild(p2)
//获取子元素列表
const div1 = document.getElementById("div1")
const div1ChildNodes = div1.childNodes
console.log(div1.childNodes)//打印出两种标签,一种是p标签,一种是text标签,因为p标签里面含有文本,text的nodeType为3,p的nodeType为1,所以通过转化为数组过滤。
const div1ChildNodesP = Array.prototype.slice.call(div1.childNodes).filter(child=>{
if(child.nodeType == 1){
return true
}
return false
})
//删除子节点
div1.removeChild(div1ChildNodesP[0])
//获取父元素
const div1 = document.getElementById("div1")
const parent = div1.parentNode
如何减少DOM操作
- 缓存DOM查询结果
- 多次DOM操作,合并到一次插入
-
- *
函数声明和函数表达式的区别
函数声明function fn(){}
函数表达式const fn = function(){}
new Object()和Object.create()的区别
{}等同于new Object(),原型链Object.prototype
Object.create(null)没有原型
Object.create({})可以指定原型
常见的正则表达式
字符串字母开头,后面字母数字下划线,长度6-30
const res = /^[a-zA-Z]\w{5,29}$/
邮政编码
const res = /\d{6}/
去除两端空格
String.prototype.trim = function(){
return this.replace(/^\s+/,'').replace(/\s+$/,'')
}
获取多个数字中的最大值
//第一种获取最大值
Math.max(10,20,30,40) //40
//第二种获取最大值
function max(){
const nums = Array.prototype.slice.call(arguments)//变为数组
let max = nums.length ? nums[0] : null
nums.forEach(n=>{
if(n>max) {
max = n
}
})
return max
}
//获取最小值
Math.min(10,20,30,40) //10
捕获js异常
//第一种手动捕获异常
try{
}.catch(ex){
console.error(ex) //手动捕获异常
}.finally{
}
//第二种自动捕获异常
window.onerror = function(message,source,lineNum,colNum,error){
console.log(message,source,lineNum,colNum,error)
}
json
json是一种数据格式,本质是一串字符串
json格式和js对象结构一致,对js语言更友好
window.json是一个全局对象:JSON.stringify JSON.parse
获取当前页面url参数
location.search
URLSearchParams
//传统方式
functoin query1(name){
const search = location.search.substr(1)//去掉前面的‘?’
const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`,'i')
const res = search.match(reg)
if(res == null){
return null
}
return res[2]
}
//URLSearchParams
funcrion query2(name){
const search = location.search
const p = new URLSearchParams(search)
return p.get(name)
}
//将url参数解析为json对象
function queryToObj(){
const res = {}
const search = location.search.substr(1)
search.split('&').forEach(paramsStr=>{
const arr = paramsStr.split('=')
const key = arr[0]
const val = arr[1]
res[key] = val
})
return res
}
数组排平[1,2,[3,4,[5]],6] => [1,2,3,4,5,6]
function flat(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
}
//第二种
function unique(arr){
const set = new Set(arr)
return [...set]
}
手写深拷贝
Object.assign为浅拷贝
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跟新一次视图
//设置一个div宽度为100px,3s后变为640px,即增加540px
//60帧/s 3s->180帧 每次变化3px
const $div1 = $("#div1")
let curWidth=100
let maxWidth=640
//第一种
function animate(){
curWidth =+ curWidth
$div1.css('width',curWidth)
if(curWidth