(十三)真题模拟【告诉你答案是什么】
真题模拟
- 面试真题
- 讲解前提示
- 何为变量提升
- 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()
前端性能如何优化?一般从哪几个方面考虑?
- 原则:多使用内存、缓存,减少计算、减少网络请求
- 方向:加载页面,页面渲染,页面操作流畅度
(十三)真题模拟【告诉你答案是什么】相关推荐
- 计算机一级真题模拟试题,2016年3月计算机一级真题模拟试题及答案.doc
2016年3月计算机一级真题模拟试题及答案 下文是关于2016年3月计算机一级真题模拟试题及答案相关内容,希望对你有一定的帮助: 第一篇:<2016年全国计算机一级考试试题附答案> 201 ...
- 北航数据结构与c语言2017答案,2022年北京航空航天大学991数据结构与C语言程序设计考研资料汇总:参考书目-历年考研真题-模拟题库-笔记和课后习题详解...
北京航空航天大学软件学院官网网址: 991数据结构与C语言程序设计考研参考书目: 谭浩强<C程序设计>(第4版)笔记和课后习题详解 谭浩强<C程序设计>(第4版)精讲班[教材精 ...
- 国家司法考试真题模拟APP
国家司法考试真题模拟 – MyExam 应用描述 你想便捷的使用iPad备考国家司法考试吗? MyExam <国家司法考试真题模拟>就是为国家司法考试而设计的平板模拟类考试应用, 所有的 ...
- 临朐教师招聘计算机题,2019年山东省潍坊市临朐县中小学语文教师招聘/编制考试历年真题试卷及参考答案...
2019年山东省潍坊市临朐县中小学语文教师招聘/编制考试历年真题试卷及参考答案 古诗文默写题. 51.(1)巴山楚水凄凉地,二十三年弃置身.怀旧空吟闻笛赋,到乡翻似烂柯人.__________,___ ...
- 淮安计算机教师考编试题及答案,2020年江苏省淮安市市直机关幼儿园幼儿教师招聘/编制考试历年真题试卷及参考答案...
2020年江苏省淮安市市直机关幼儿园幼儿教师招聘/编制考试历年真题试卷及参考答案 1.喝水时,小明不小心被热水烫伤了小手.教师应首先对小明烫伤的小手进行的处理是[] A.肥皂水冲洗 B.冷水冲洗 C. ...
- 2022管理类联考真题试卷不含答案-文都管联院
2022管理类联考真题试卷不含答案
- 英语四六级听力真题模拟题
还没准备好 又双叒叕要考四六级啦 给大家分享一下六级听力 (真题模拟题附带一百篇英语广播原文哟~~) 关注公众号" 编译未来 " 回复 " 听力 "领取哟 ps ...
- 2022.12六级真题第1套答案及详解(15页)
Hey大家好!今天我来给大家分享一份超棒的资料--2022年12月六级真题第1套答案及详解!包含答案,还有详细的解析哦! 对于每一道题目,都有对应的答案解析,不仅能够帮助大家检验答案的正确性,还能够帮 ...
- 计算机软考英语题翻译,软考专业英语真题、译文及答案.docx
软考专业英语真题.译文及答案 09上半年软件设计师英文真题.译文及答案 For nearly ten years, the Unified Modeling Language (UML) has be ...
最新文章
- 基于强化学习的自动化剪枝模型
- SHELL编程之执行环境----邹立巍的博客
- [Phonegap+Sencha Touch] 移动开发18 Sencha Touch项目通过phonegap打包后的程序名字的问题...
- Flex与javascript通信
- 用计算机名怎么共享电视盒,机顶盒怎么通过电脑实现局域网共享
- Mysql Explain用法pdf
- 为vs2008添加Mobile Web Forms模板
- 律师总结二手房买卖中的八大陷阱
- java编程练习题三
- IntelliJ IDEA开发Java web项目,设置JSP代码自动补全的方法
- 网络邻居无法查找计算机,局域网中无法找到网上邻居的原因
- 路由器WIFI密码忘记了怎么办
- 离散帕斯瓦尔定理、帕斯瓦尔定理的证明
- 荣耀手机如何批量删除日历日程?日历日程提醒便签
- python批量改变图像大小
- oracle异构mysql_Oracle GoldenGate学习之--异构平台同步(Mysql到Oracle)
- 树莓派无线网络及VNC设置
- IDM移动端功能升级说明
- selenium 火狐下载弹框去除
- Android R 11 后台定位权限没有 始终允许选项的解决方法
热门文章
- 【转载】solr教程,值得刚接触搜索开发人员一看
- 避免在循环体中声明创建对象
- Spring Boot 批量上传: The field files exceeds its maximum permitted size of 1048576 bytes.
- SpringCloud教程 | 第三篇: 服务消费者(Feign)
- JavaWeb学习总结(二):Tomcat服务器学习和使用(一)
- Mongodb固定集合
- 60.extjs-布局 (在column布局中使用fieldset 和 在fieldset中使用column布局)
- 洛谷P1082 同余方程 数论
- 【.Net Micro Framework PortingKit – 12】SysTick驱动开发
- Ajax+asp.net无刷新验证用户名