01 强制类型转换和隐式类型转换
强制:parseInt
、parseFloat
、toString
隐式:if
、逻辑运算、==、+
拼接字符串
02 new Object() 和 Object.create() 区别
// Object.create(null) // 没有原型
// Object.create({}) // 可指定原型
const obj1 = {
a: 1,
b: 2
}
const obj2 = new Object(obj1)
const obj3 = Object.create(obj1)
obj2 === obj1 // true
obj3.__proto__ === obj1 // true
03 描述事件冒泡的流程
基于 DOM 树形结构,事件会顺着触发元素往上冒泡,应用场景:代理
04 xhr.status
2xx - 表示成功处理信息,如 200 - 成功处理请求,204 - 成功处理请求但没有返回内容
3xx - 需要重定向,浏览器直接跳转,如 301 - 永久重定向,302 - 临时重定向,304 - 网页未修改,不会返回内容
4xx - 客户端请求错误,如 403 - 拒绝请求, 404 - 找不到请求网页
5xx - 服务端错误
05 Promise加载图片
function loadImg(src) {
return new Promise(
(resolve, reject) => {
const img = document.createElement('img')
img.onload = () => {
resolve(img)
}
img.onerror = () => {
const err = new Error(`图片加载失败 ${src}`)
reject(err)
}
img.src = src
}
)
}
loadImg(url1).then(img1 => {
console.log(img1.width)
return img1 // 普通对象
}).then(img1 => {
console.log(img1.height)
return loadImg(url2) // promise 实例
}).then(img2 => {
console.log(img2.width)
return img2
}).then(img2 => {
console.log(img2.height)
}).catch(ex => console.error(ex))
06 如何减少DOM操作
const list = document.getElementById('list')
// 创建一个文档片段,此时还没有插入到DOM结构中
const frag = document.createDocumentFragment()
for (let i = 0; i < 20; i++) {
const li = document.createElement('li')
li.innerHTML = `List item ${i}`
// 先插入文档片段中
frag.appendChild(li)
}
list.appendChild(frag)
07 split() 和 join() 的区别
'1-2-3'.split('-') // [1, 2, 3]
[1, 2, 3].join('-') // '1-2-3'
08 函数 call 和 apply 的区别
fn.call(this, p1, p2, p3)
fn.apply(this, arguments)
09 window.onload 和 DOMContentLoaded 的区别
// 页面的全部资源加载完才会执行,包括图片、视频等
window.onload = function() {}
window.addEventListener('load', function() {})
// DOM 渲染完即可执行,此时图片、视频还可能没有加载完
document.addEventListener('DOMContentLoaded', function(){})
$(document).ready(function(){})
10 函数声明和函数表达式的区别
函数声明会在代码执行前预加载,而函数表达式不会
11 获取多个数字中的最大值
function max() {
const nums = Array.prototype.slice.call(arguments)
let max = 0
nums.forEach(n => {
if(n > max) {
max = n
}
})
return max
}
// 方法2
Math.max(10, 30, 20, 40)
12 解析 URL 参数
function query(name) {
const search = location.search.substr(1) // 类似 array.slice(1)
// search: 'a=10&b=20&c=30'
const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`, 'i')
const res = search.match(reg)
if (res === null) {
return null
}
return res[2]
}
query('d')
// URLSearchParams
function query(name) {
const search = location.search
const p = new URLSearchParams(search)
return p.get(name)
}
console.log( query('b') )
13 手写字符串 trim 保证浏览器兼容性
String.prototype.trim = function() {
return this.replace(/^\s+/, '').replace(/\s+$/, '')
}
14 数组去重
function unique(arr) {
const res = []
arr.forEach(item => {
if (res.indexOf(item) < 0) {
res.push(item)
}
})
return res
}
// 方法2
Array.from(new Set(arr));
15 深度比较 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
}
16 数组降维 flat
function flat(arr) {
// 验证 arr 中,还有没有深层数组 [1, 2, [3, 4]]
const isDeep = arr.some(item => item instanceof Array)
if (!isDeep) {
return arr // 已经是 flatern [1, 2, 3, 4]
}
const res = Array.prototype.concat.apply([], arr)
return flat(res) // 递归
}
17 单线程和异步
单线程:同一时间只能做一件事,两段 JS 不能同时执行
原因:避免 DOM 渲染的冲突,浏览器渲染 DOM,JS 可以修改 DOM,当 JS 执行的时候,浏览器 DOM 渲染会暂停
JS 实现异步的具体解决方案——Event-Loop 事件轮询
同步代码,直接执行;异步函数先放在异步队列中,待主进程的同步函数执行完毕,轮询执行异步队列的函数
$.ajax({
url: './data.json',
succcess: function() {
console.log('a')
}
})
setTimeout(function(){
console.log('b')
}, 1000)
setTimeout(function(){
console.log('c')
})
console.log('d')
// 输出结果取决于success所用的时间
End of File
行文过程中出现错误或不妥之处在所难免,希望大家能够给予指正,以免误导更多人,最后,如果你觉得我的文章写的还不错,希望能够点一下喜欢和关注,为了我能早日成为优秀作者献上一发助攻吧,谢谢!^ ^