30.DOM常见的操作有哪些?
创建节点
createElement 创建新元素,接受一个参数,即要创建元素的标签名
查询节点
querySelector 传入任何有效的css 选择器,即可选中单个 DOM元素(首个) 如果页面上没有指定的元素时,返回 null
querySelectorAll 返回一个包含节点子树内所有与之相匹配的Element节点列表,如果没有相匹配的,则返回一个空节点列表
更新节点
innerHTML 不但可以修改一个DOM节点的文本内容,还可以直接通过HTML片段修改DOM节点内部的子树
innerText
style dom对象.style.样式属性 = ‘’
添加节点
innerHTML
appendChild 把一个子节点添加到父节点的最后一个子节点
insertBefore(新dom,指定dom对象) 把子节点插入到指定的位置的前面
setAttribute 在指定元素中添加一个属性节点,如果元素中已有该属性改变属性值
删除节点
removeChild 拿到父节点,要删除的节点dom对象。父.removeChild(子)
31.说说你对BOM的理解,常见的BOM对象你了解哪些?
BOM (Browser Object Model),浏览器对象模型,提供了独立于内容与浏览器窗口进行交互的对象 。
浏览器的全部内容可以看成DOM,整个浏览器可以看成BOM。
BOM对象:
window: Bom的核心对象是window,它表示浏览器的一个实例 。 在浏览器中,window对象有双重角色,即是浏览器窗口的一个接口,又是全局对象
location:获取url地址信息
navigator: 对象主要用来获取浏览器的属性,区分浏览器类型
screen: 保存的纯粹是客户端能力信息,也就是浏览器窗口外面的客户端显示器的信息,比如像素宽度和像素高度
history: 主要用来操作浏览器URL的历史记录,可以通过参数向前,向后,或者向指定URL跳转
32.BOM和DOM区别?
BOM(浏览器对象):与浏览器交互的方法和对象
BOM是浏览器对象模型,它指的是将浏览器当作一个对象来对待,这个对象主要定义了与浏览器进行交互的方法和接口
BOM的核心是window,而window对象具有双重角色,它既是js访问浏览器窗口的一个接口,又是一个全局对象(Global)
这就意味着网页中定义的任何对象、变量和函数,都会作为全局对象的一个属性或者方法存在
DOM(文档对象模型):处理网页内容的方法和接
DOM是文档对象模型,它指的是把文档当作一个对象来对待,这个对象主要定义了处理网页的内容和接口
33.如何解决跨域问题?
了解同源策略: 同源是指"协议+域名+端口"三者相同,它是浏览器最核心也最基本的安全功能如果缺少了同源策略,浏览器很容易受到XSS、CSRF等攻击
通过jsonp跨域
nginx代理跨域
nodejs中间件跨域
后端在头部信息中设置安全域名
前端代理
34.异步加载js方式?
设置``属性 async="async" (一旦脚本可用,则会异步执行)
动态创建 script DOM:document.createElement('script');
XmlHttpRequest 脚本注入
异步加载库 LABjs
模块加载器 Sea.js
35.哪些操作会导致内存泄漏?
内存泄漏: JavaScript 内存泄露指对象在不需要使用它时仍然存在,导致占用的内存不能使用或回收
未使用 var 声明的全局变量
闭包函数(Closures)
循环引用(两个对象相互引用)
控制台日志(console.log)
移除存在绑定事件的DOM元素(IE)
setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏
垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为 0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收
36.XML和JSON的区别?
数据体积:JSON数据体积更小
数据交互:JSON与JavaScript得交互更加方便,更容易被解析,更好的数据传输
传输速度:JSON传输速度快
数据描述:JSON对数据的描述相比XML较差
37.说说你对递归得理解?
递归: 在数学与计算机科学中,是指在函数的定义中使用函数自身的方法
38.说说你对函数式编程的理解?优缺点?纯函数,高阶函数,柯里化
主要的编程范式有三种:命令式编程,声明式编程和函数式编程
函数式编程: 更加强调程序执行的结果而非执行的过程,简单来讲,就是要把过程逻辑写成函数,定义好输入参数,只关心它的输出结果
纯函数: 纯函数是对给定的输入返还相同输出的函数,并且要求你所有的数据都是不可变的,即纯函数=无状态+数据不可变
函数内部传入指定的值,就会返回确定唯一的值
不会造成超出作用域的变化,例如修改全局变量或引用传递的参数
高阶函数: 是以函数作为输入或者输出的函数被称为高阶函数
柯里化: 把一个多参数函数转化成一个嵌套的一元函数的过程
优点:
更好的管理状态
更简单的复用
减少代码量,提高维护性
缺点:
性能:函数式编程相对于指令式编程,性能绝对是一个短板,因为它往往会对一个方法进行过度包装,从而产生上下文切换的性能开销
资源占用:在 JS 中为了实现对象状态的不可变,往往会创建新的对象,因此,它对垃圾回收所产生的压力远远超过其他编程方式
递归陷阱:在函数式编程中,为了实现迭代,通常会采用递归操作
39.Javascript中如何实现函数缓存?函数缓存有哪些应用场景?
函数缓存,就是将函数运算过的结果进行缓存
实现方式: 实现函数缓存主要依靠闭包、柯里化、高阶函数
应用场景:
对于昂贵的函数调用,执行复杂计算的函数
对于具有有限且高度重复输入范围的函数
对于具有重复输入值的递归函数
对于纯函数,即每次使用特定输入调用时返回相同输出的函数
40. JSON 的了解?
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
它是基于JavaScript的一个子集。数据格式简单, 易于读写, 占用带宽小
{‘age’:‘12’, ‘name’:‘back’}
41. document.write 和 innerHTML 的区别?
document.write 只能重绘整个页面
innerHTML 可以重绘页面的一部分
42. 请解释一下 JavaScript 的同源策略?
概念:同源策略是客户端脚本(尤其是Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。
这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。
指一段脚本只能读取来自同一来源的窗口和文档的属性。
43. 介绍一下闭包和闭包常用场景?
闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包常见方式,就是在一个函数的内部创建另一个函数
使用闭包主要为了设计私有的方法和变量,闭包的优点是可以避免变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。在js中,函数即闭包,只有函数才会产生作用域的概念。
闭包有三个特性:
函数内再嵌套函数
内部函数可以引用外层的参数和变量
参数和变量不会被垃圾回收机制回收
闭包的好处: 能够实现封装和缓存等;
闭包的缺点就是常驻内存,会增大内存使用量,使用不当会造成内存泄漏
应用场景:
常见的防抖节流
使用闭包可以在 JavaScript 中模拟块级作用域
闭包可以用于在对象中创建私有变量
44. javascript的内存(垃圾)回收机制?
垃圾回收器会每隔一段时间找出那些不再使用的内存,然后为其释放内存
标记清除方法(mark and sweep),
这是JavaScript最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”
垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了
引用计数方法(reference counting)
在低版本IE中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个 变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变为0的时 候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。
在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,但BOM与DOM对象却是通过引用计数回收垃圾的, 也就是说只要涉及BOM及DOM就会出现循环引用问题。
45. 用js递归的方式写1到100求和?
function add(num1, num2) { const num = num1 + num2; if(num2 === 100) { return num; } else { return add(num, num2 + 1) } } var sum = add(1, 2);
46. 事件队列(宏任务微任务)
可以分为微任务(micro task)队列和宏任务(macro task)队列。
微任务一般比宏任务先执行,并且微任务队列只有一个,宏任务队列可能有多个。另外我们常见的点击和键盘等事件也属于宏任务。
下面我们看一下常见宏任务和常见微任务。
常见宏任务:
setTimeout()
setInterval()
setImmediate()
常见微任务:
promise.then()、promise.catch()
new MutaionObserver()
process.nextTick()
微任务和宏任务的本质区别。
宏任务特征:有明确的异步任务需要执行和回调;需要其他异步线程支持。
微任务特征:没有明确的异步任务需要执行,只有回调;不需要其他异步线程支持。
setTimeout(function () { console.log("1"); }, 0); async function async1() { console.log("2"); const data = await async2(); console.log("3"); return data; } async function async2() { return new Promise((resolve) => { console.log("4"); resolve("async2的结果"); }).then((data) => { console.log("5"); return data; }); } async1().then((data) => { console.log("6"); console.log(data); }); new Promise(function (resolve) { console.log("7"); resolve() }).then(function () { console.log("8"); }); // 2 4 7 5 8 3 6 async2的结果 1
43.async/await, Generator
async 是一个通过异步执行并隐式返回 Promise 作为结果的函数。是Generator函数的语法糖,并对Generator函数进行了改进。
改进:
内置执行器,无需手动执行 next() 方法。
更好的语义
更广的适用性:co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)。
返回值是 Promise,比 Generator 函数返回的 Iterator 对象方便,可以直接使用 then() 方法进行调用。
async 隐式返回 Promise 作为结果的函数,那么可以简单理解为,await后面的函数执行完毕时,await会产生一个微任务(Promise.then是微任务)。
Generator 是 ES6 引入的新概念,它允许在函数执行过程中暂停和恢复它们的状态。通过 function* 声明一个 Generator 函数,可以在函数体内使用关键字 yield 来生成一个状态,并将函数挂起,等待下一次调用。Generator 函数返回一个可迭代对象,可以通过 next() 方法获取当前生成器的状态值。使用 Generator 函数可以更简单地实现异步操作,避免回调嵌套带来的问题。
48. JavaScript 是单线程的,浏览器是多进程的
每打开一个新网页就会创建一个渲染进程
渲染进程是多线程的
负责页面渲染的 GUI 渲染线程
负责JavaScript的执行的 JavaScript 引擎线程,
负责浏览器事件循环的事件触发线程,注意这不归 JavaScript 引擎线程管
负责定时器的定时触发器线程,setTimeout 中低于 4ms 的时间间隔算为4ms
负责XMLHttpRequest的异步 http 请求线程
GUI 渲染线程与 JavaScript 引擎线程是互斥的
单线程JavaScript是因为避免 DOM 渲染的冲突,web worker 支持多线程,但是 web worker 不能访问 window 对象,document 对象等。
49.说说 Javascript 数字精度丢失的问题,如何解决?
例子:0.1+0.2===0.3 =>false 涉及IEE754标准
问题原因:
计算机存储双精度浮点数需要先把十进制数转换为二进制的科学记数法的形式,然后计算机以自己的规则{符号位+(指数位+指数偏移量的二进制)+小数部分}存储二进制的科学记数法
因为存储时有位数限制(64位),并且某些十进制的浮点数在转换为二进制数时会出现无限循环,会造成二进制的舍入操作(0舍1入),当再转换为十进制时就造成了计算误差
解决:
使用 toFixed() 方法:将浮点数转化为一个指定位数小数的字符串形式
使用第三方库,Math.js、BigDecimal.js
50.说说你对模块化方案的理解,比如 CommonJS、AMD、CMD、ES Module 分别是什么?
CommonJS加载模块同步,主要用于服务器端,它主要依靠require和exports来实现模块化,require用户加载模块,exports用于导出模块
AMD异步模块定义,他解决了在浏览器环境下文件以来管理,模块加载的问题。与commonjs不同,AMD使用异步方式加载模块
CMD通用模块定义,cmd也是为了解决浏览器端模块化出现的,与AMD不同的是它使用同步方式加载模块,主要依赖require和define来实现模块化
ES Module是es6新增的模块化方案,支持在浏览器和node.js使用,并且已经得到了嵌入式运行环境的支持,与commonjs和amd不同,ES Module是静态加载它使用import和export关键字实现模块化