javascript面试题积累
1、前端工程化 https://www.cnblogs.com/fsyz/p/8274727.html
工程化要解决的是如何提高整个系统生产效率和质量。
前端工程化:需要解决的问题是如何提高编码->测试->维护阶段的生产效率。
开发和部署:
从开发角度,要解决的问题包括:
- 提高开发生产效率;
- 降低维护难度。
从部署角度,要解决的问题主要是资源管理,包括:
- 代码审查。
- 压缩打包。
- 增量更新。
- 单元测试。
要解决上述问题,需要引入构建/编译阶段。
简单归纳为要从这几个方向去提高效率:模块化、组件化、规范化、自动化。
2、前端设计模式
1. 单例模式
2. 工厂模式
3. 代理模式
4. 观察者模式
3、前端性能优化手段
减少HTTP请求数量和大小
较少DOM的直接操作
多利用浏览器缓存、各种缓存机制。较少操作
预加载、懒加载
文件优化。提高生产模式下的系统性能
webpack优化项目配置
节流
4、如何渲染几万条数据并不卡住界面
不能一次性将几万条都渲染出来,而应该一次渲染部分 DOM,可以通过定时器等方法,延迟分批渲染
5、跨域、同源策略
同源策略:由于浏览器会判断 协议、域名、端口 是否相同,只要这三者任意一个不同 ,就会产生跨域问题。
解决方案:
代理
通过jsonp跨域
nginx代理跨域
6、call、apply、bind的区别 https://www.runoob.com/w3cnote/js-call-apply-bind.html
这三个都可以用来改变 this 的指向,不过三者也有区别
- call 的参数是字符串类型,obj.myFun.call(db,'1', '2')
- apply的参数是数组类型,obj.myFun.apply(db, ['1', '2'])
- bind返回的是函数,所以需要在后面再加个 ()来执行,obj.myFun.bind(db)()
7、js数据类型
- 基本数据类型:number、string、boolem、null、undefined
- 引用类型:object、function
- es6:symbol
8、理解JS中&&和||
- 出现在条件判断语句中
- &&
- 两边条件都为true,结果才为true
- 如果有一个为false,结果为false
- 当第一个条件为false时,就不再判断后面的条件
- ||
- 只要有一个条件为true时,结果就为teue
- 当两个条件都为false时,结果才为false
- 当一个条件为true时,后面的条件不再判断
- 赋值语句中
- a && b
- 计算 a 的结果。如果为true,执行表达式 b 的结果,并返回 b 的结果。如果为 false ,返回 a 的结果
- a || b
- 计算 a的结果。如果为false,执行 b ,并返回 b的结果。如果为 true,返回 a 的结果
9、浏览器轮询机制和宏任务以及微任务
- JavaScript 是一门单线程语言,但如果完全由上到下执行代码,假如一个代码块执行了很长时间,后面必须等待当前执行完毕,这样的效率是非常低的,所以有了异步的概念。JavaScript 的主线程是单线程的,但是也有其他的线程去帮我们实现异步操作,比如定时器线程、事件线程、Ajax 线程
- settimeout这种函数的第二个参数是需要延迟的毫秒数。如果是3000.。。意思就是:跟着主线程一起走3000之后把这个函数中需要执行的语句放在任务队列中去,在主线程执行完毕后再执行这些事件
- settimeout这类的异步会被放在宏任务队列中
- promise会被放在微任务队列中去
- 主线程相当于一个整体的宏任务
- 执行顺序:整体的宏任务 --> 微任务队列中的事件 --> 宏任务队列中的事件
10、防抖和节流
防抖 指触发事件n秒后函数只执行一次。如果在n秒内再次触发事件,将重新计时n秒 例如: 点击按钮,2秒后调用函数 在第1.5秒时又点了,则重新计算2秒 拍照或者下拉触底加载下一页 节流 连续发生的事件在n秒内只执行一次函数
// 防抖debounce // 让输入完毕后过1秒再查询(延迟查询) function debounce(func, wait) { let timeout; return function() { if(timeout) clearTimeout(timeout); timeout = setTimeout(function() { func.apply(this) }, wait) } } // 让输入完毕后立即查询,过2秒才能再查询(立即执行) function debounce(func, wait) { let timeout; // 定时器 return function() { if(timeout) clearTimeout(timeout); let callNow = !timeout; //类型转换 timeout = setTimeout(function() { timeout = null; }, wait); if(callNow) { func.apply(this) } } } // 节流 // 固定的时间去执行 function throttle(func, wait) { let timeout; return function() { if(!timeout) { timeout = setTimeout(() => { timeout = null; func.apply(this) }, wait) } } }
11、数组去重几种方法
- 定义一个新数组,并存放原数组的第一个元素,然后将元素组一一和新数组的元素对比,若不同则存放在新数组中。
- 利用ES6的set
12、箭头函数和普通函数的区别
- 箭头函数是匿名函数,不能作为构造函数,不能使用new,
- 箭头函数的 this 永远指向其上下文的 this ,任何方法都改变不了其指向
- 不绑定arguments(如果有要使用arguments的时候可以使用rest参数代替)
- 不可以使用yield命令,因此箭头函数不能用作Generator函数
13、基本数据类型和引用数据类型的区别
基础数据类型的数据存储在栈内存中,引用数据类型的数据存储在堆内存中,引用储存在栈内存中。
14、new一个实例对象会发生什么
- 创建一个新对象
- 将构造函数的作用域赋给新对象(this)
- 执行构造函数中的代码(为新对象添加属性)
- 返回该对象。
15、从输入网址到页面呈现都发生了什么
1、客户端获取URL 2、DNS解析获取IP及端口号 3、两端建立TCP\IP连接 4、发送HTTP连接或者HTTPS连接 5、服务端处理请求 6、返回响应数据 7、浏览器解析数据渲染数据 8、断开TCP\IP连接
16、条件判断
- undefined、null、false、NaN、' '、0 这些值都会判断为false,其他的为true
17、typeof 和 instanceof 类型判断
- 基本类型使用 typeof 来判断足够,引用类型都会返回 ‘object’,函数类型返回 ‘function’,null类型返回 ‘object
- instanceof 可以更精确的判断引用类型的类型。例:myObj instanceof Object 使用原型链来判断左边的原型上是否存在右边的类型
18、this指向问题
- js 中的 this 在定义的地方是决定不了的this的值的,只有在使用调用的时候才会决定this的指向。默认指向它上一级调用者的this
- https://www.cnblogs.com/pssp/p/5216085.html
- https://www.cnblogs.com/sdzj/p/10476992.html
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this
19、== 和 ===
- == 判断的值是否相等,先检查两个操作数数据类型,如果相同, 则进行===比较, 如果不同, 则愿意为你进行一次类型转换, 转换成相同类型后再进行比较
- ===(全等)判断的是 值和类型全部都要相等才可以。如果类型不同,直接就是false
20、闭包
- js中 如果函数被调用的话,调用完就会被清理。如果是被使用的话,会一直存在在内存中 使用:var a =a()、调用:a()
- 闭包的概念:函数A中,有一个函数B,函数B中可以访问函数A中定义的变量或者是数据,此时形成了闭包
- 闭包的作用:缓存数据,延长作用域链
- 闭包的优点和缺点:缓存数据,有可能导致内存泄漏
- https://blog.csdn.net/TerranceTang/article/details/104467326
21、原型和原型链和构造函数的关系
22、立即执行函数
- (function(){})() or (function(){}())
- 页面加载完成后只执行一次的函数。
- 将设置函数中的变量包裹在局部作用域中,不会泄露成全局变量。
- 传参:(function(window){})(window) 全局变量被作为一个参数传递给立即执行参数,这样它在函数内部不使用window也可以被访问到。
- 立即执行函数和闭包的结合
- 立即执行函数只是函数的一种调用方式,只是声明完之后立即执行,这类函数一般都只是调用一次,调用完之后会立即销毁,不会占用内存。
- 闭包则主要是让外部函数可以访问内部函数的作用域,也减少了全局变量的使用,保证了内部变量的安全,但因被引用的内部变量不能被销毁,增大了内存消耗,使用不当易造成内存泄露。
23、深浅拷贝
内存中一共分为栈内存和堆内存两大区域,(引用类型)深拷贝就是堆内存的再次开辟,一份新的值。浅拷贝就是栈内存中引用的复制。基本类型不存在深浅拷贝
基本类型复制: var a = 1; var b = a;//复制 console.log(b)//1 a = 2;//改变a的值 console.log(b)//1 console.log(a) //2 因为a,b都是属于基本类型,基本类型的复制是不会影响对方的,因为基本类型是每一次创建变量都会在栈内存中开辟一块内存, 用来存放值,所以基本类型进行复制是不会对另外一个变量有影响的; 引用类型复制: 数组深拷贝: concat、slice仅适用于一维数组 深拷贝实现: JSON.parse(JSON.stringify())和递归以及JQuery库的extend方法