JS 学习总结
1. typeof能判断的类型?(JS变量类型)
答:undefined、number、string、boolean、symbol、object、function
2. 何时使用===,何时使用==(强制类型转换)
答:任何时候都用===,除非是判断==null
3. window.onload和DOMContentLoaded的区别(页面加载过程)
答:window.onload是在页面元素全部加载结束后触发,二DOMContentLoaded是在页面的骨架渲染出来,而图片等资源尚未渲染时触发,用户等待时间短
4. JS创建10个<a>
标签,点击弹出对应的序号(JS作用域)
答:
for(let i = 0; i < 10; i++){
const a = document.createElement('a');
a.href="javascript:;";
a.addEventListener('click', function () {
alert(i)
})
a.innerHTML = `标签${i}`;
document.body.appendChild(a)
}
5. 手写节流throttle和防抖debounce(性能、体验优化)
- 防抖debounce
function debounce (fn ,delay = 500) {
let timer = null
return function () {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout( () => {
fn.apply(this, arguments)
}, delay)
}
}
const input = document.getElementById('input')input.addEventListener('keyup', debounce(function(){
console.log(this.value)
}, 1000))
- 节流throttle
function throttle(fn, delay = 100) {
let timer = null
return function () {
if (timer) {
return
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay);
}
}
const div = document.getElementById('div')
div.addEventListener('drag', throttle(function(e){
console.log(e.offsetX, e.offsetY)
}, 200))
6. Promise解决什么问题?(JS异步)
答:回调地狱
7. 值类型和引用类型的区别(值类型和引用类型)
答:值类型是存放在栈中。引用类型是放在堆中,栈中存放的是该变量在堆中的内存地址。
8. 手写深拷贝 (值类型和引用类型)
/**
* 深拷贝
* @param {Object} obj 要拷贝的对象
*/
function deepClone(obj) {
if (typeof obj !== 'object' || obj === null) return obj
let newObj
if (obj instanceof Array) {
newObj = []
} else {
newObj = {}
}
for (let key in obj) {
if (obj.hasOwnProperty(key))
newObj[key] = deepClone(obj[key])
}
return newObj
}
9. 如何准确判断一个变量是不是数组?(原型链)
答:a instanceof Array
10. 手写一个简易的jQuery, 考虑插件和扩展性 (class)
答:
class jQuery {
constructor(selector) {
this.selector = selector
const res = document.querySelectorAll(selector)
for(let i = 0; i < res.length; i++) {
this[i] = res[i]
}
this.length = res.length
}
get (index) {
return this[index]
}
each (fn) {
for(let i = 0; i < this.length; i++) {
fn(this[i])
}
}
on (type, fn) {
return this.each(function (ele) {
ele.addEventListener(type, fn, false)
})
}
}
const p = new jQuery('p')
console.log(p.get(0))
// 插件
jQuery.prototype.dialog = function (info) {
alert(info)
}
// 造轮子
class myJQuery extends jQuery {
constructor(selector) {
super(selector)
}
// 扩展自己的方法
addClass(className) {
}
style(data) {
}
}
11. class的原型本质,怎么理解?(原型和原型链)
答:所有的实例都有隐式原型__proto__
,所有的class都有显示原型prototype
,实例的隐式原型__proto__
强等于class的显示原型 prototype
,而class的显示原型prototype的隐式原型__proto__
等于父类的显示原型prototype
12. this的不同应用场景,如何取值?(作用域)
- 作为普通函数this指向window
- 使用call、apply、bind,传入什么this就指向什么
- 作为对象方法被调用,指向调用它的对象
- 在class方法被调用,指向调用它的对象
- 箭头函数,不改变this指向,this是上级作用域的this
13. 手写bind函数(this)
答:
const obj = {
name: 'yibo'
}
function fn(a, b) {
console.log(this)
console.log(a + b)
return a + b
}
function myBind(obj) {
const context = this
const newArguments = Array.prototype.slice.call(arguments)
newArguments.shift()
return function () {
return context.apply(obj, newArguments)
}
}
const res = fn(1, 2)
console.log(res)
Function.prototype.myBind = myBind
const myFn = fn.myBind(obj, 5, 8)
const res2 = myFn()
console.log(res2)
14. 实际开发中闭包的应用场景,举例说明
答:
// 闭包隐藏数据,只提供API
function createCache () {
// 闭包中的数据,被隐藏,不被外接访问
const data = {}
return {
set: function (key, val) {
data[key] = val
},
get: function (key) {
return data[key]
}
}
}
const c = createCache()
c.set('a', 100)
console.log(c.get('a'))
15. 同步和异步的区别是什么?(JS异步和单线程)
答:同步会阻塞代码执行,异步不会阻塞代码执行
16. 手写用Promise加载一张图片(Promise)
答:
const url = 'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg'
function loadImg(src) {
return new Promise((resolve, reject) => {
console.log('start')
const img = document.createElement('img')
img.onload = () => {
console.log('loaded')
resolve(img)
}
img.onerror = () => {
resolve(new Error(`图片加载失败${src}`))
}
img.src = src
console.log('end')
})
}
loadImg(url)
.then(img => {
document.body.appendChild(img)
return img
})
.then(img => {
console.log(img.height)
})
.catch(err => console.log(err))
17. 前端使用异步的场景有哪些?
答:网络请求、图片加载、定时任务
18. DOM是哪种数据结构?
答:树形结构
19. DOM操作的常用API
增删改查:getElementsByTagName、getAttribute、setAttribute、createElement、appendChild、removeChild
20. attribute和property的区别
property: 修改对象属性,不会体现到HTML结构中
attribute:修改HTML属性,会改变HTML结构
两者都可能引起DOM重新渲染
21. 一次性插入多个DOM节点,考虑性能
答:
const list = document.getElementById('list')
// 创建一个文档片段
const fragment = document.createDocumentFragment()
for(let i = 0; i < 10; i++){
const li = document.createElement('li')
li.innerHTML = i
// 插入到文档片段,文档片段是在内存中
fragment.appendChild(li)
}
// 将文档片段一次性插入
list.appendChild(fragment)
22. 如何识别浏览器的类型
答:UA,navigator.userAgent
23. 分析拆解URL各个部分
答:${protocol}${host}${pathname}${search}${hash} === ${href}
24. 编写一个通用的事件监听函数
答:
function bindEvent(ele, type, selector, fn) {
if(!fn) {
fn = selector
selector = null
}
ele.addEventListener(type, function(event){
const target = event.target
if(selector){
if(target.matches(selector)){
fn.call(target, event)
}
}
else {
fn.call(target, event)
}
})
}
25. 描述事件冒泡的流程
答:基于DOM属性结构,事件会顺着触发元素往上冒泡,应用场景:代理
26. 无限下拉的图片列表,如何监听每个图片的点击?
答:事件代理,用e.target获取触发元素,用matches来判断是否是触发元素
27. 手写一个简易的ajax
答:
function ajax(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', url, true)
xhr.onreadystatechange = function () {
if(xhr.readyState === 4) {
if(xhr.status === 200) {
resolve(JSON.parse(xhr.responseText))
}else if(xhr.status === 404){
reject(new Error('404 not found'))
}
}
}
xhr.send()
})
}
const url = '/data/test.json'
ajax(url)
.then(res=>console.log(res))
.catch(err=>console.log(err))
28. 描述cookie、localStorage、sessionStorage 的区别
答:容量、API易用性、是否跟随http请求发送出去
cookie
本身用于浏览器和server通讯
被”借用“到本地存储来
可用window.cookie=’‘来修改
缺点
存储大小:最大4kb
http请求时需要发送到服务端,增加请求数据量
只能用document.cookie=’'来修改,太过简陋
localStorage、sessionStorage
HTML5专门为存储而设计,最大可存5M
API简单易用,setItem、getItem
不会随http请求发送到服务器端
localStorage数据会永久存储,除非代码或手动删除
sessionStorage数据只存在于当前会话,浏览器关闭则清空
一般用localStorage更多一些
29. 从输入url到渲染出页面的整个过程
答:下载资源:各种资源类型,下载过程。渲染页面:结合HTML、CSS、JavaScript、图片等
30. window.onload和DOMContent的区别
答:
window.addEventListener('load', funciton () {
// 页面的全部资源加载完才会执行,包括图片、视频等
})
document.addEventListener('DOMContentLoaded', function () {
// DOM 渲染完即可执行,此时图片、视频可能还没加载完
})
31. 为何建议把CSS放在head中?
答:让DOM在生成之前就和CSS整合,然后一次性渲染完。
32. 为何建议把JS放在body之后?
答:页面渲染过程比较长,被js阻碍
33. 常见的web前端攻击方式有哪些?
答:XSS跨站请求攻击:替换特殊字符 <、 >、