1、何为变量提升
var、let 、const的区别?
· var 是 ES5 语法,let、const是 ES6 语法,var 有变量提升
· var、let 是变量,可以修改;const 是常量,不可修改
· let、const 是块级作用域,var 没有;
typeof 返回哪些类型?
· undefined、string、number、boolean、symbol
· object (注意:typeof null === 'object')
· function
列举强制类型转换和隐式类型转换?
· 强制: parseInt、 parseFloat、toString等
· 隐式:if、逻辑运算、== 和 + 拼接字符串
2、手写深度比较 isEqual ?
手写深度比较,模拟 lodash.isEqual ?
// 判断是否是对象
function isObject(obj) {
return typeof obj === 'object' && obj !== null
}
function isEqual(obj1, obj2) {
if (!isObject(obj) || !isObject(obj2)) {
// 判断如果不是对象,就比较值类型
return obj1 === obj2;
}
let obj1keys = Object.keys(obj1)
let obj2keys = Object.keys(obj2)
// 判断对象或者数组长度是否相等
if (obj1keys.length !== obj2keys.length) {
return false
}
// 以obj1为基准,和obj2依次递归比较
for (let key in obj1) {
let res = isEqual(obj1[key], obj2[key])
if (!res) {
return false
}
}
return true
}
let obj = {
a: 100,
b: {
x: 100,
y: 200
}
}
let obj2 = {
a: 100,
b: {
x: 100,
y: 200
}
}
let flag = isEqual(obj, obj2)
let arr1 = [1, 2, 3, 4]
let arr2 = [1, 2, 3, 4, 9]
let flag2 = isEqual(arr1, arr2)
console.log(flag2)
split()和join()的区别?
数组的 pop、push、unshift 和 shift分别做什么?
· 功能是什么?
· 返回值是什么?
· 是否对原数组造成影响?
pop: 方法移除数组的最后一个元素,并返回该元素。
push: 将新元素添加到数组的末尾,并返回新的长度。
unshift: 将新元素添加到数组的开头,并返回新的长度。
shift: 删除数组的第一个元素,并返回该元素。
array中纯函数的特点: 1、不会改变原数组;2、返回一个数组; 例如: concat、map、filter、slice
3、你是否真的会用数组map
数组 slice 和 splice的区别?
slice() 方法以新的数组对象,返回数组中被选中的元素。
slice() 方法选择从给定的 start 参数开始的元素,并在给定的 end 参数处结束,但不包括。不会改变原数组
splice() 方法向/从数组添加/删除项目,并返回删除的项目。会改变原数组
[10,20,30].map(parseInt) 的返回结果是什么?
主要考察拆解函数;parseInt()的第二个参数,进制转换(接收两个参数),parseInt方法还可以接受第二个参数(2到36之间),表示被解析的值的进制,返回该值对应的十进制数。默认情况下,parseInt的第二个参数为10,即默认是十进制转十进制。详细请看该博文:blog.csdn.net/josavion/ar…
ajax请求 get 和 post的区别?
· get 一般用于查询操作, post 一般用户提交操作
· get 参数拼接在 url上,post 放在请求体内(数据体积可更大)
· 安全性: post易于防止 CSRF
4、再学闭包
函数 call 和 apply 的区别?
事件代理(委托)是什么 ?
事件委托,通俗地来讲,就是把一个元素响应事件(click、keydown......)的函数委托到另一个元素;DOM 中事件委托的实现是利用事件冒泡的机制;
委托的优点
1. 减少内存消耗
试想一下,若果我们有一个列表,列表之中有大量的列表项,我们需要在点击列表项的时候响应一个事件;
<ul id="list">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
......
<li>item n</li>
</ul>
// ...... 代表中间还有未知数个 li
如果给每个列表项一一都绑定一个函数,那对于内存消耗是非常大的,效率上需要消耗很多性能;
因此,比较好的方法就是把这个点击事件绑定到他的父层,也就是 ul 上,然后在执行事件的时候再去匹配判断目标元素;
所以事件委托可以减少大量的内存消耗,提高效率。
2. 动态绑定事件
比如上述的例子中列表项就几个,我们给每个列表项都绑定了事件;
在很多时候,我们需要通过 AJAX 或者用户操作动态的增加或者去除列表项元素,那么在每一次改变的时候都需要重新给新增的元素绑定事件,给即将删去的元素解绑事件;
如果用了事件委托就没有这种麻烦了,因为事件是绑定在父层的,和目标元素的增减是没有关系的,执行到目标元素是在真正响应执行事件函数的过程中去匹配的;
所以使用事件在动态绑定事件的情况下是可以减少很多重复工作的。
闭包是什么?有什么特性?有什么负面影响?
5、回顾 DOM 操作和优化
如何阻止事件冒泡和默认行为?
查找、添加、删除和移动 DOM节点的方法?
如何减少 DOM 操作?
6、jsonp 本质是ajax吗?
解释jsonp 的原理,为何他不是真正的 ajax?
document load 和 ready 的区别?
== 和 === 的不同?
7、是否用过 Object.create() ?
函数声明和函数表达式的区别?
// // 函数声明
const res = sum(10, 20)
console.log(res)
function sum(x, y) {
return x + y
}
// // 函数表达式
var res = sum(10, 20)
console.log(res)
var sum = function (x, y) {
return x + y
}
new Object 和 Object.create()的区别?
关于 this 的场景题?
答案: 1 (this指向User)、 undefined(this指向window,所以为undefined)
8、常见的正则表达式?
关于作用域和自由变量的场景题 - 1
答案: 3
判断字符串以字母开头,后面字母数字下划线,长度6 - 30
关于作用域和自由变量的场景题 - 2
答案: 100、 10、10
9、如何获取最大值?
手写字符串trim()方法,保证浏览器兼容性?
如何获取多个数字中的最大值?
如何用JS实现继承?
class 继承
10、解析 URL 参数
如何捕获 JS 程序中的异常?
什么是 JSON ?
获取当前页面中 url 参数?
11、数组去重有几种方式?
将 url 参数解析为 JS 对象?
方式一:
function urlFn() {
let obj = {}
let params = location.search.substr(1) // 去掉前面的?
// ?a=10&b=20&c=30
params.split('&').forEach(item => {
let arr = params.split('=')
const key = arr[0]
const value = arr[1]
obj[key] = value
})
return obj
}
方式二:
function urlFn2() {
let obj = {}
let pList = new URLSearchParams(location.search)
pList.forEach((val, key) => {
obj[key] = val
})
return obj
}
手写数组 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)
数组去重?
// 传统方式
function unique(arr) {
let res = []
arr.forEach(item => {
if (res.indexOf(item) < 0) {
res.push(item)
}
})
return res
}
let arr = unique([1,3,4,5, 2, 3, 4, 5, 6, 5, 6, 7])
console.log(arr)
// 使用Set (无序,不能重复),比传统方式快一点
function setUnique(arr) {
const setArr = new Set(arr)
return [...setArr]
}
let arr2 = setUnique([1,3,4,5, 2, 3, 4, 5, 6, 5, 6, 7])
console.log(arr2)
12、是否用过 requestAnimationFrame?
手写深拷贝?
function deepClone(obj={}) {
if (typeof obj !== 'object' || obj == null) {
return obj
}
// 初始化返回结果
let result
// 判断是对象还是数组
if (obj instanceof Array) {
result = []
} else {
result = {}
}
// 递归
for (let key in obj) {
// 保证key不是原型的属性
if (obj.hasOwnProperty(key)) {
// 递归调用
result[key] = deepClone(obj[key])
}
}
// 返回结果
return result
}