最近在找工作,总结一些面试题和解答,如解答有误或不完善还请各位评论区指正补充,谢谢!
1. 对象的深拷贝
方法一:使用JSON.parse和JSON.stringify
let targetObject = JSON.parse(JSON.stringify(source))
// 该方法简便,但是不能识别undefined,symbol和function(){}
方法二:遍历+递归
function deepCopy(source) {
if(!source) return source // 兼容null,undefined
let targetObject = source.constructor === Array ? [] : {}
for (let key in source) {
if(source.hasOwnProperty(key)) { // 是自有非继承属性
if(source[key] && typeof(source[key]) === 'object') { //是对象需要递归,typeof [] 也等于object
targetObject[key] = source[key].constructor === Array ? [] : {}
targetObject[key] = deepCopy(source[key])
} else { //非对象直接赋值
targetObject[key] = source[key]
}
}
}
return targetObject
}
2. 原生ajax请求
function ajax(){
// 五步走 param为传入的参数对象
// 第一步 创建异步对象
var xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest() // ie7以上
} else {
xhr = new ActiveXObject() // // ie7以下
}
// 第二步 设置请求方法
if (param.type.toLowerCase() === 'get') { // get请求
xhr.open(param.type, param.url + '?' + formatParams(param.data), true)
} else if (param.type.toLowerCase() === 'post') { // post请求
xhr.open(param.type, param.url, true) // true为异步,false为同步
}
// 第三步 设置请求头 (get和post设置请求头时有区别吗?)
xhr.setRequestHeader("content-type", "application/x-www-form-urlencode")
// 第四步 发送请求
if (param.type.toLowerCase() === 'get') { // get请求
xhr.send(null)
} else if (param.type.toLowerCase() === 'post') { // post请求
xhr.send(JSON.stringify(param.data))
}
// 第五步 让异步对象接受服务器的响应数据
xhr.onreadystatechange = function () {
// 0 未初始化未调用open
// 1.启动 调用open 未调用 send
// 2. 发送 已调用send() 但是未响应
// 3. 接收 已经接收部分响应数据
// 4.完成 完成全部数据响应
/**
*status 状态说明
* 200 服务器成功返回页面
* 400 语法错误 服务器不识别
* 401 请求需要用户认证
* 404 知道url 服务器找不到
* 500 服务器错误 无法完成请求
*
*/
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
param.success && param.success(xhr.responseText)
} else {
param.error && param.error()
}
}
}
// 格式化参数
function formatParams(data) {
if (!data) return
var arr = []
for (var i in data) {
arr.push(`${encodeURIComponent(name)}=${encodeURIComponent(data[i])}`)
}
return arr.join('&')
}
}
3. 防抖和节流
// 防抖
function debounce(fn) {
let timeout = null
return function() {
clearTimeout(timeout)
timeout = setTimeout( () => {
fn.apply(this, arguments)
}, 500)
};
}
// 节流
function throttle(fn) {
let canRun = true
return function() {
if(!canRun) return
canRun = false
setTimeout( () => {
fn.apply(this, argument)
this.canRun = true
}, 500)
}
}
4. 两个事件循环题目
// (一)
console.log(1)
setTimeout(() => {
console.log(2)
new Promise(resolve => {
console.log(4)
resolve()
}).then(() => {
console.log(5)
})
})
new Promise(resolve => {
console.log(7)
resolve()
}).then(() => {
console.log(8)
})
setTimeout(() => {
console.log(9)
new Promise(resolve => {
console.log(11)
resolve()
}).then(() => {
console.log(12)
})
})
// (二)
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(function () {
console.log('setTimeout');
}, 0)
async1();
new Promise(function (resolve) {
console.log('promise1');
resolve();
}).then(function () {
console.log('promise2');
});
console.log('script end');
5. 浏览器渲染引擎和JS引擎
6. web安全
- 跨站脚本攻击
- input "<script></script>" ---> 将输入字符"<"转义,过滤 - 减少使用JSONP进行跨域请求 - 跨站请求伪造
弹窗,图片,被攻击者带上cookie冒充身份进行攻击操作 - 检测http referer 是否同域名 - token - session的时效性 - http劫持
使用https加密 - get/post请求
- get在url后面带上传值,敏感信息要注意,可用post代替 - get请求会被浏览器缓存
- 跨域JSONP