列举强制类型转换
- 强制:parseInt、parseFloat、toString等
- 隐式:if、逻辑运算(>=等)、==、+拼接字符串
手写深度比较,模拟 lodash.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
}
const objKeys1 = Object.keys(obj1)
const objKeys2 = Object.keys(obj2)
if (objKeys1.length !== objKeys2.length) {
return false
}
for (let key in obj1) {
const res = isEqual(obj1[key], obj2[key])
if (!res) {
return false
}
}
return true
}
Ps:结束循环
- for...in和for...of 用break、continue可以结束循环,如果 for...in和for...of 在函数内可以用return结束函数
- forEach 不管在不在函数内 return 相当于 for 循环的 continue
列举纯函数API
-
纯函数:1、不改变原数组(没有副作用);2、返回一个数组
- concat、map、filter、slice
-
非纯函数
- push、pop、shift、unshift、forEach、some、every、reduce、splice
[10, 20, 30].map(parseInt)
打印[10,NaN,NaN]
分解一下
[10,20,30].map((item,index) => {
return parseInt(item, index)
})
其中 parseInt(string, radix)
-
第一个参数是要要被解析的字符串
-
第二个参数可选。表示要解析的数字的基数。
- 该值介于 2 ~ 36 之间。如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。
new Object() 和 Object.create() 的区别
- {} 等同于 new Object(), 原型 Object.prototype
- Object.create(null) 没有原型
- Object.create({...}) 可指定原型
手写 trim 方法
String.prototype.trim = function(){ return this.replace(/^\s+/,'').replace(/\s+$/,'') }
获取多个数字中的最大值
function max(){
const nums = [].slice.call(arguments)
let max = 0
for(let item of nums){
max = item >= max ? item : max
}
return max
}
或者
Math.max(10, 20, 30, 40)
//还有Math.min()
如何捕获 JS 中的异常
- 手动捕获
try{
}catch(ex){
}finally{}
- 自动捕获
window.onerror = function(message, source, lineNum, cloNum, error){
//第一,对跨域的 js,如 CDN 的,不会有详细的报错信息
//第二,对于压缩的 js,需要配合 sourceMap 反查到未压缩代码的行、列
}
什么是 JSON
- json 是一种数据结构,本质是一段字符串
- json 格式和 js 对象结构一致, 对 js 语言更友好
解析 URL 参数
- 传统方式: location.search
- 新 API: URLSearchParams
//假设 URL 是 http://localhost:8080?a=10
function query(name){
const search = location.search
const p = new URLSearchParams(search)
return p.get(name)
}
query('a') //打印 10
手写数组 flatern (数组扁平化)
// 手写
function flatern(arr, result = []) {
if (!(arr instanceof Array)) {
result.push(arr)
return result
}
for (let item of arr) {
result = flatern(item, result)
}
return result
}
更简单的方法(深度超过1层不能拍平 [1,2,3,[4,5,[6,7]]])
Array.prototype.concat.apply([],arr)
[].concat(...arr)
简单方法的拍平所有深度的方法
function flatern(arr){
let isDeep = arr.some(item => item instanceof Array)
if(!isDeep){
return arr
}
const res = [].concat(...arr)
return flatern(res)
}
数组去重
- 传统方式 双层 for 循环
- es6 Set
function unique(arr){
let set = new Set(arr)
return Array.from(set)
// 或者用 return [...set] 也可以
}
- 单层循环
function unique(arr){
let res = []
for(let item of arr){
if(res.indexOf(item) < 0){
res.push(item)
}
}
}
总结:对于性能来说,用 Set 更好,原因是单层循环中 indexOf() 其实也算一种遍历
深拷贝
function deepClone(obj = {}) {
if (typeof obj !== 'object' || obj == null) return obj
let result = obj instanceof Array ? [] : {}
for (let key in obj) {
// baozhengkey不是原型属性
if (obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key])
}
}
}
-
关于 obj == null ------>️ obj === null || boj === undefined
-
JSON.parse(JSON.stringify()) 这个也是深拷贝,也可以拷贝方法
const obj2 = JSON.parse(JSON.stringify(obj1))
-
数组的 slice 方法,当没有参数时是深拷贝数组 const deepCloneArr = arr.slice()
-
es6的解构赋值,只能深拷贝第一层,后面的层数是浅拷贝
const obj2 = {...obj1}
- Object.assign 同 es6 的解构赋值一样,只拷贝第一层,后面的层数是浅拷贝
介绍一下 RAF(requestAnimationFrame)
- 要想动画流畅,更新频率要大于 60帧/s,即小于 16.67ms 更新一次视图
- setTimeout 控制动画时,要手动控制频率,而 RAF 浏览器会自动控制
- 当后台标签或隐藏 iframe 中,RAF会暂停,而 setTimeout 依然执行
- 切换窗口等操作时 RAF 会暂停
setTimeout
// 3s 内把宽度从 100px变成 645px,即增加 540px
// 60帧/s 3s -> 180帧 每帧变化 540/180 = 3px
let oDiv = document.querySelector('div')
let curWidth = 100
let maxWidth = 640
function animate() {
curWidth += 3
oDiv.style.width = `${curWidth}px`
if (curWidth < maxWidth) {
setTimeout(animate, 16.7) //自己控制时间
}
}
animate()
RAF
// 3s 内把宽度从 100px变成 645px,即增加 540px
// 60帧/s 3s -> 180帧 每帧变化 540/180 = 3px
let oDiv = document.querySelector('div')
let curWidth = 100
let maxWidth = 640
function animate() {
curWidth += 3
oDiv.style.width = `${curWidth}px`
if (curWidth < maxWidth) {
window.requestAnimationFrame(animate)
}
}
animate()