真题模拟

  • 面试真题
  • 讲解前提示
  • 何为变量提升
    • var和let const的区别
    • typeof返回哪些类型
    • 列举强制类型转换和隐式类型转换
  • 手写深度比较 isEqual
    • 手写深度比较,模拟lodash isEqual
    • split() 和join()的区别
    • 数组pop push unshift shift分别做什么
    • 数组的API,有哪些是纯函数
  • 你是否真的会用数组map
    • 数组slice和splice的区别
    • [10,20,30].map(parseInt)返回结果是什么
    • ajax请求get和post的区别
  • 再学闭包
    • 函数call和apply的区别
    • 事件代理(委托)是什么
    • 闭包是什么?有什么特效?有什么负面影响
  • 回顾DOM操作和优化
    • 如何阻止时间冒泡和默认行为
    • 查找、添加、删除、移动DOM节点的方法
    • 如何减少DOM操作
  • jsonp本质是ajax吗
    • 解释jsonp的原理,为何它不是真正的ajax
    • document load和ready的区别
    • 两等和三等的不同
  • 是否用过Object.create()
    • 函数声明和函数表达式的区别
    • new Object() 和 Object.create()的区别
    • 关于this的场景题
  • 常见的正则表达式
    • 关于作用域和自由变量的场景题 - 1
    • 判断字符串以字母开头,后面字母数字下划线,长度6-30
    • 关于作用域和自由变量的场景题 - 2
  • 如何获取最大值
    • 手写字符串trim方法,保证浏览器兼容性
    • 如何获取多个数字中的最大值
    • 如何用JS实现继承
  • 解析url参数
    • 如何捕获JS程序中的异常
    • 什么是JSON
    • 获取当前页面url参数
  • 数组去重有几种方式
    • 将url参数解析为JS对象
    • 手写数组flatern,考虑多层级
    • 数组去重
  • 是否用过requestAnimationFrame
    • 手写深拷贝
    • 介绍一下RAF requestAnimationFrame
    • 前端性能如何优化?一般从哪几个方面考虑?

面试真题

  • 搜集网上的高频JS初级面试题
  • 验证和复习之前学过的知识
  • 补充其他技能,如正则表达式、数组API

讲解前提示

  • 题目没有按照知识点或者难度排序,即混排
  • 只筛选了初级面试题,即本课程知识体系之内的
  • 如您遇到了其他未讲到的面试题,欢迎提供,让课程更完善

何为变量提升

var和let const的区别

  • var是ES5语法,let const是ES6语法,var有变量提升
  • var和let是变量,可修改;const是常量,不可修改
  • let const有块级作用域,var没有
/ // 变量提升 ES5
// console.log(a) // undefined
// var a = 200// var a
// console.log(a) // undefined
// a = 200// 块级作用域
for (let i = 0; i < 10; i++) {let j = i + 1
}
console.log(j)

typeof返回哪些类型

  • undefined string number boolean symbol
  • object(注意,typeof null === ‘object’)
  • function

列举强制类型转换和隐式类型转换

  • 强制:parseInt parseFloat toString等
  • 隐式:if、逻辑运算、==、+拼接字符串

手写深度比较 isEqual

手写深度比较,模拟lodash isEqual

// 判断是否是对象或数组
function isObject(obj) {return typeof obj === 'object' && obj !== null
}
// 全相等(深度)
function isEqual(obj1, obj2) {if (!isObject(obj1) || !isObject(obj2)) {// 值类型(注意,参与 equal 的一般不会是函数)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
}// 测试
const obj1 = {a: 100,b: {x: 100,y: 200}
}
const obj2 = {a: 100,b: {x: 100,y: 200}
}
// console.log( obj1 === obj2 )
console.log( isEqual(obj1, obj2) )const arr1 = [1, 2, 3]
const arr2 = [1, 2, 3, 4]

split() 和join()的区别

'1-2-3'.split('-') //[1,2,3]
[1,2,3].join('-')

数组pop push unshift shift分别做什么

// 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]

数组的API,有哪些是纯函数

// // 纯函数:1. 不改变源数组(没有副作用);2. 返回一个数组
// const arr = [10, 20, 30, 40]// // concat
// const arr1 = arr.concat([50, 60, 70])
// // map
// const arr2 = arr.map(num => num * 10)
// // filter
// const arr3 = arr.filter(num => num > 25)
// // slice
// const arr4 = arr.slice()// // 非纯函数
// // push pop shift unshift
// // forEach
// // some every
// // reduce

你是否真的会用数组map

数组slice和splice的区别

  • 功能区别(slice - 切片,splice - 剪接)
  • 参数和返回值
  • 是否纯函数
// const arr = [10, 20, 30, 40, 50]// // slice 纯函数
// const arr1 = arr.slice()
//console.log(arr1,arr) [10, 20, 30, 40, 50],[10, 20, 30, 40, 50]
// const arr2 = arr.slice(1, 4)
//console.log(arr2,arr) [20, 30, 40],[10, 20, 30, 40, 50]
// const arr3 = arr.slice(2)
//console.log(arr3,arr) [30, 40, 50],[10, 20, 30, 40, 50]
// const arr4 = arr.slice(-3)
// console.log(arr4,arr) [30, 40, 50],[10, 20, 30, 40, 50]// // splice 非纯函数
// const spliceRes = arr.splice(1, 2, 'a', 'b', 'c')
//console.log(spliceRes,arr) [20, 30],[10, "a", "b", "c", 40, 50]
// const spliceRes1 = arr.splice(1, 2)
// console.log(spliceRes1, arr) [20, 30], [10, 40, 50]
// const spliceRes2 = arr.splice(1, 0, 'a', 'b', 'c')
// console.log(spliceRes2, arr) [],[10, "a", "b", "c", 20, 30, 40, 50]

[10,20,30].map(parseInt)返回结果是什么

  • map的参数和返回值
  • parseInt参数和返回值
const res = [1, 2, 3].map(parseInt)
console.log(res) //[1, NaN, NaN]
// 拆解
[1, 2, 3].map((num, index) => {return parseInt(num, index)
})
//parseInt(string, radix) 函数将给定的字符串以指定基数(radix/base)解析成为整数。就是 你想把string当成radix进制数解析成10进制
//radix传入0时会把1当成是10进制数,所以“1”成功了。
//radix传入1时...没有1进制数,所以不可能转换成功,返回NaN
//radix传入2时,"3"不能当作2进制数处理所以也返回NaN

ajax请求get和post的区别

  • get一般用于查询操作,post一般用户提交操作
  • get参数拼接在url上,post放在请求体内(数据体积可更大)
  • 安全性:post易于防止CSRF

再学闭包

函数call和apply的区别

fn.call(this,p1,p2,p3)
fn.apply(this,arguments)

事件代理(委托)是什么

闭包是什么?有什么特效?有什么负面影响

  • 回顾作用域和自由变量
  • 回顾闭包应用场景:作为参数被传入,作为返回值被返回
  • 回顾:自由变量的查找,要在函数定义的地方(而非执行的地方)
  • 影响:变量会常驻内存,得不到释放,闭包不要乱用
// // 自由变量示例 —— 内存会被释放
// let a = 0
// function fn1() {
//     let a1 = 100//     function fn2() {
//         let a2 = 200//         function fn3() {
//             let a3 = 300
//             return a + a1 + a2 + a3
//         }
//         fn3()
//     }
//     fn2()
// }
// fn1()// // 闭包 函数作为返回值 —— 内存不会被释放
// function create() {
//     let a = 100
//     return function () {
//         console.log(a)
//     }
// }
// let fn = create()
// let a = 200
// fn() // 100function print(fn) {let a = 200fn()
}
let a = 100
function fn() {console.log(a)
}
print(fn) // 100

回顾DOM操作和优化

如何阻止时间冒泡和默认行为

event.stopProppagation()
event.preventDefault()

查找、添加、删除、移动DOM节点的方法

基础中的基础,不再演示,可回顾之前的章节

如何减少DOM操作

  • 缓存DOM查询结果
  • 多次DOM操作,合并到一次插入

jsonp本质是ajax吗

解释jsonp的原理,为何它不是真正的ajax

  • 浏览器的同源策略(服务端没有同源策略)和跨域
  • 哪些html标签能绕过跨域
  • jsonp的原理

document load和ready的区别

两等和三等的不同

  • 两等会尝试类型转换
  • 三等严格相等
  • 哪些场景才用两等?

是否用过Object.create()

函数声明和函数表达式的区别

  • 函数声明function fn(){…}
  • 函数表达式 const fn = function(){…}
  • 函数声明会在代码执行前预加载,而函数表达式不会
// // 函数声明
// const res = sum(10, 20)
// console.log(res) 30
// function sum(x, y) {
//     return x + y
// }// // 函数表达式
// var res = sum(10, 20) sum is not a function
// console.log(res)
// var sum = function (x, y) {
//     return x + y
// }

new Object() 和 Object.create()的区别

  • {}等同于new Object(),原型Object.prototype
  • Object.create(null)没有原型
  • Object.create({…})可指定原型
const obj1 = {a: 10,b: 20,sum() {return this.a + this.b}
}const obj2 = new Object({a: 10,b: 20,sum() {return this.a + this.b}
})
//console.log(obj1===obj2) false
const obj21 = new Object(obj1)
//console.log(obj21===obj1) true
const obj3 = Object.create(null)
//console.log(obj3) 返回空对象,没有原型,没有属性
const obj4 = new Object()
//console.log(obj4) 返回空对象{},有原型const obj5 = Object.create({a: 10,b: 20,sum() {return this.a + this.b}
})//创建一个空对象,把空对象原型指向传入的对象
//console.log(obj5===obj1) false
const obj6 = Object.create(obj1)
//console.log(obj6===obj1) false
//console.log(obj6.__proto__===obj1) true
obj1.c = 1000;
console.log(obj6.c) //1000

关于this的场景题

 const User = {count:1,getCount:function(){return this.count;}
}
console.log(User.getCount()) //1
const func = User.getCount
console.log(func()) //undefined,this指window

常见的正则表达式

关于作用域和自由变量的场景题 - 1

let i;
for(i=1;i<=3;i++){setTimeout(function(){console.log(i)},0)
}

判断字符串以字母开头,后面字母数字下划线,长度6-30

const reg =  /^[a-zA-Z]\w{5, 29}$/
学习正则表达式的规则
手写常见的正则表达式
// 邮政编码
/\d{6}/// 小写英文字母
/^[a-z]+$/// 英文字母
/^[a-zA-Z]+$/// 日期格式 2019.12.1
/^\d{4}-\d{1,2}-\d{1,2}$/// 用户名
/^[a-zA-Z]\w{5, 17}$/// 简单的 IP 地址匹配
/\d+\.\d+\.\d+\.\d+/

https://deerchao.cn/tutorials/regex/regex.htm

关于作用域和自由变量的场景题 - 2

let a = 100
function test(){alert(a) //100a = 10alert(a) //10
}
test()
alert(a) //10

如何获取最大值

手写字符串trim方法,保证浏览器兼容性

String.prototype.trim = function(){return this.replace(/^\s+/,'').replace(/\s+$/,'')
}
//原型、this、正则表达式

如何获取多个数字中的最大值

//方式一
function max(){const nums = Array.prototype.slice.call(arguments) //变为数组let max = 0nums.forEach(n => {if(n > max){max = n}})return max
}
//方式二
Math.max(10,30,20,40)
//以及Math.min

如何用JS实现继承

  • class继承
  • prototype继承

解析url参数

如何捕获JS程序中的异常

try{//todo
}catch(ex){console.log.error(ex) //手动捕获catch
}finally{//todo
}
//自动捕获
window.onerror = function(message,source,lineNum,colNum,error){//第一,对跨域的js,如CDN的,不会有详细的报错信息//第二,对于压缩的js,还要配合sourceMap反查到未压缩代码的行、列
}

什么是JSON

  • json是一种数据格式,本质是一段字符串
  • json格式和JS对象结构一致,对JS语言更友好
  • window.JSON是一个全局对象:JSON.stringify JSON.parse
    key和value必须用双引号(除非是bool或者数字)

获取当前页面url参数

  • 传统方式,查找location.search
  • 新API,URLSearchParams
// // 传统方式
// 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.searchconst p = new URLSearchParams(search)return p.get(name)
}
console.log( query('b') )

数组去重有几种方式

将url参数解析为JS对象

//传统方式,分析search
function queryToObj(){const res = {}const search = location.search.substr(1) //去掉前面的?号search.split('&').forEach(paramStr => {const arr = paramStr.split('=')const key = arr[0]const val = arr[1]res[key] = val})return res
}
//使用URLSearchParams
function queryToObj(){const res = {}const pList = new URLSearchParams(location.search)pList.forEach((val,key) => {res[key] = val})return res
}

手写数组flatern,考虑多层级

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) // 递归
}const res = flat( [1, 2, [3, 4, [10, 20, [100, 200]]], 5] )
console.log(res) //[1,2,3,4,10,20,100,200,5]

数组去重

  • 传统方式,遍历元素挨个比较、去重
  • 使用Set
  • 考虑计算效率
// // 传统方式
// function unique(arr) {
//     const res = []
//     arr.forEach(item => {
//         if (res.indexOf(item) < 0) {
//             res.push(item)
//         }
//     })
//     return res
// }// 使用 Set (无序,不能重复)
function unique(arr) {const set = new Set(arr)return [...set]
}
const res = unique([30, 10, 20, 30, 40, 10])
console.log(res)

是否用过requestAnimationFrame

手写深拷贝

/*** 深拷贝* @param {Object} obj 要拷贝的对象*/
function deepClone(obj = {}) {if (typeof obj !== 'object' || obj == null) {// obj 是 null ,或者不是对象和数组,直接返回return obj}// 初始化返回结果let resultif (obj instanceof Array) {result = []} else {result = {}}for (let key in obj) {// 保证 key 不是原型的属性if (obj.hasOwnProperty(key)) {// 递归调用!!!result[key] = deepClone(obj[key])}}// 返回结果return result
}
const obj1 = {age: 20,name: 'xxx',address: {city: 'beijing'},arr: ['a', 'b', 'c']
}const obj2 = deepClone(obj1)
obj2.address.city = 'shanghai'
obj2.arr[0] = 'a1'
console.log(obj1.address.city)
console.log(obj1.arr[0])
//注意Object.assign不是深拷贝
const obj = {a:10,b:20,c:30}
Object.assign(obj,{d:40})
{a:10,b:20,c:30,d:40}
console.log(obj) //{a:10,b:20,c:30,d:40}const obj1 = Object.assign({},obj,{e:50})
console.log(obj) //{a:10,b:20,c:30,d:40}
console.log(obj1) //{a:10,b:20,c:30,d:40,e:50}
obj.a = 100
console.log(obj1) //{a:10,b:20,c:30,d:40,e:50}
const obj = {a:10,{x:100,y:100}}
const obj1 = Object.assign({},obj,{c:30})
console.log(obj) //{a:10,{x:100,y:100}}
console.log(obj1) //{a:10,{x:100,y:100},c:30}
obj.a = 100
console.log(obj) //{a:100,{x:100,y:100}}
nsole.log(obj1) //{a:10,{x:100,y:100},c:30}
obj.b.x = 101
console.log(obj1.b.x) //101

介绍一下RAF requestAnimationFrame

  • 要想动画流畅,更新频率要60帧/s,即16.67ms更新一次视图
  • setTimeout要手动控制频率,而RAF浏览器会自动控制
  • 后台标签或隐藏iframe中,RAF会暂停,而setTimeout依然执行
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>JS 真题演示</title><style>#div1 {width: 100px;height: 50px;background-color: red;}</style></head><body><p>JS 真题演示</p><div id="div1"></div><script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.js"></script><script src="./RAF.js"></script></body>
</html>
// 3s 把宽度从 100px 变为 640px ,即增加 540px
// 60帧/s ,3s 180 帧 ,每次变化 3pxconst $div1 = $('#div1')
let curWidth = 100
const maxWidth = 640// // setTimeout
// function animate() {
//     curWidth = curWidth + 3
//     $div1.css('width', curWidth)
//     if (curWidth < maxWidth) {
//         setTimeout(animate, 16.7) // 自己控制时间
//     }
// }
// animate()// RAF
function animate() {curWidth = curWidth + 3$div1.css('width', curWidth)if (curWidth < maxWidth) {window.requestAnimationFrame(animate) // 时间不用自己控制}
}
animate()

前端性能如何优化?一般从哪几个方面考虑?

  • 原则:多使用内存、缓存,减少计算、减少网络请求
  • 方向:加载页面,页面渲染,页面操作流畅度

(十三)真题模拟【告诉你答案是什么】相关推荐

  1. 计算机一级真题模拟试题,2016年3月计算机一级真题模拟试题及答案.doc

    2016年3月计算机一级真题模拟试题及答案 下文是关于2016年3月计算机一级真题模拟试题及答案相关内容,希望对你有一定的帮助: 第一篇:<2016年全国计算机一级考试试题附答案> 201 ...

  2. 北航数据结构与c语言2017答案,2022年北京航空航天大学991数据结构与C语言程序设计考研资料汇总:参考书目-历年考研真题-模拟题库-笔记和课后习题详解...

    北京航空航天大学软件学院官网网址: 991数据结构与C语言程序设计考研参考书目: 谭浩强<C程序设计>(第4版)笔记和课后习题详解 谭浩强<C程序设计>(第4版)精讲班[教材精 ...

  3. 国家司法考试真题模拟APP

    国家司法考试真题模拟 – MyExam 应用描述  你想便捷的使用iPad备考国家司法考试吗? MyExam <国家司法考试真题模拟>就是为国家司法考试而设计的平板模拟类考试应用, 所有的 ...

  4. 临朐教师招聘计算机题,2019年山东省潍坊市临朐县中小学语文教师招聘/编制考试历年真题试卷及参考答案...

    2019年山东省潍坊市临朐县中小学语文教师招聘/编制考试历年真题试卷及参考答案 古诗文默写题. 51.(1)巴山楚水凄凉地,二十三年弃置身.怀旧空吟闻笛赋,到乡翻似烂柯人.__________,___ ...

  5. 淮安计算机教师考编试题及答案,2020年江苏省淮安市市直机关幼儿园幼儿教师招聘/编制考试历年真题试卷及参考答案...

    2020年江苏省淮安市市直机关幼儿园幼儿教师招聘/编制考试历年真题试卷及参考答案 1.喝水时,小明不小心被热水烫伤了小手.教师应首先对小明烫伤的小手进行的处理是[] A.肥皂水冲洗 B.冷水冲洗 C. ...

  6. 2022管理类联考真题试卷不含答案-文都管联院

    2022管理类联考真题试卷不含答案

  7. 英语四六级听力真题模拟题

    还没准备好 又双叒叕要考四六级啦 给大家分享一下六级听力 (真题模拟题附带一百篇英语广播原文哟~~) 关注公众号" 编译未来 " 回复 " 听力 "领取哟 ps ...

  8. 2022.12六级真题第1套答案及详解(15页)

    Hey大家好!今天我来给大家分享一份超棒的资料--2022年12月六级真题第1套答案及详解!包含答案,还有详细的解析哦! 对于每一道题目,都有对应的答案解析,不仅能够帮助大家检验答案的正确性,还能够帮 ...

  9. 计算机软考英语题翻译,软考专业英语真题、译文及答案.docx

    软考专业英语真题.译文及答案 09上半年软件设计师英文真题.译文及答案 For nearly ten years, the Unified Modeling Language (UML) has be ...

最新文章

  1. 基于强化学习的自动化剪枝模型
  2. SHELL编程之执行环境----邹立巍的博客
  3. [Phonegap+Sencha Touch] 移动开发18 Sencha Touch项目通过phonegap打包后的程序名字的问题...
  4. Flex与javascript通信
  5. 用计算机名怎么共享电视盒,机顶盒怎么通过电脑实现局域网共享
  6. Mysql Explain用法pdf
  7. 为vs2008添加Mobile Web Forms模板
  8. 律师总结二手房买卖中的八大陷阱
  9. java编程练习题三
  10. IntelliJ IDEA开发Java web项目,设置JSP代码自动补全的方法
  11. 网络邻居无法查找计算机,局域网中无法找到网上邻居的原因
  12. 路由器WIFI密码忘记了怎么办
  13. 离散帕斯瓦尔定理、帕斯瓦尔定理的证明
  14. 荣耀手机如何批量删除日历日程?日历日程提醒便签
  15. python批量改变图像大小
  16. oracle异构mysql_Oracle GoldenGate学习之--异构平台同步(Mysql到Oracle)
  17. 树莓派无线网络及VNC设置
  18. IDM移动端功能升级说明
  19. selenium 火狐下载弹框去除
  20. Android R 11 后台定位权限没有 始终允许选项的解决方法

热门文章

  1. 【转载】solr教程,值得刚接触搜索开发人员一看
  2. 避免在循环体中声明创建对象
  3. Spring Boot 批量上传: The field files exceeds its maximum permitted size of 1048576 bytes.
  4. SpringCloud教程 | 第三篇: 服务消费者(Feign)
  5. JavaWeb学习总结(二):Tomcat服务器学习和使用(一)
  6. Mongodb固定集合
  7. 60.extjs-布局 (在column布局中使用fieldset 和 在fieldset中使用column布局)
  8. 洛谷P1082 同余方程 数论
  9. 【.Net Micro Framework PortingKit – 12】SysTick驱动开发
  10. Ajax+asp.net无刷新验证用户名