js面试题(进阶)梳理

1、undeclared 与 undefined的区别?

undefined:声明了变量,但是没有赋值 undecalared:没有声明变量就直接使用var a; //undefined b; // b is not defined

2、let & const与 var 的区别?
var存在变量提升,可重复声明同一变量,声明的变量均可改 let没有变量提升,不可重复声明同一变量,声明的变量均可改 const没有变量提升,不可重复声明同一变量,声明的基本数据类型不可改,引用类型可改属性,不可只声明变量而不赋值

3、获取DOM元素有哪些方法?
方法 描述
document.getElementById(id) 通过id获取dom
document.getElementsByTagName(tagName) 通过标签名获取dom
document.getElementsByClassName(class) 通过class获取dom
document.getElementsByName(name) 通过标签的属性name获取dom
document.querySelector(选择器) 通过选择器获取dom
document.querySelectorAll(选择器) 通过选择器获取dom
4、操作DOM元素有哪些方法
方法 描述
createElement 创建一个标签节点
createTextNode 创建一个文本节点
cloneNode(deep) 复制一个节点,连同属性与值都复制,deep为true时,连同后代节点一起复制,不传或者传false,则只复制当前节点
createDocumentFragment 创建一个文档碎片节点
appendChild 追加子元素
insertBefore 将元素插入前面
removeChild 删除子元素
replaceChild 替换子元素
getAttribute 获取节点的属性
createAttribute 创建属性
setAttribute 设置节点属性
romoveAttribute 删除节点属性
element.attributes 将属性生成类数组对象
5、DOM的类型有哪几种?
元素节点Node.ELEMENT_NODE(1) 属性节点Node.ATTRIBUTE_NODE(2) 文本节点Node.TEXT_NODE(3) CDATA节点Node.CDATA_SECTION_NODE(4) 实体引用名称节点Node.ENTRY_REFERENCE_NODE(5) 实体名称节点Node.ENTITY_NODE(6) 处理指令节点Node.PROCESSING_INSTRUCTION_NODE(7) 注释节点Node.COMMENT_NODE(8) 文档节点Node.DOCUMENT_NODE(9) 文档类型节点Node.DOCUMENT_TYPE_NODE(10) 文档片段节点Node.DOCUMENT_FRAGMENT_NODE(11) DTD声明节点Node.NOTATION_NODE(12)

6、JS的作用域及作用域链
什么是作用域呢?
在 Javascript 中,作用域分为 全局作用域 和 函数作用域全局作用域:代码在程序任何地方都能访问,window对象的内置属性都属于全局作用域 函数作用域:在固定的代码片段才能被访问

什么是作用域链?
一般情况下,变量取值到 创建 这个变量 的函数的作用域中取值但是如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链var x = 10; function fn(){ console.log(x); }function show(f){ var x = 20; f(); // 10 }show(fn);

7、数组的splice 与 slice 的区别?
方法 参数
splice splice(start, num, item1, item2, ...)
slice slice(start, end)
【js面试题(进阶)梳理】8、substr 和 substring 的区别?
方法 参数
substr substr(start,length)
substring substring(start,end)
9、includes 比 indexOf好在哪?
includes可以检测NaN,indexOf不能检测NaN,includes内部使用了Number.isNaN对NaN进行了匹配

10、下面代码输出的结果?
for(var i = 0; i < 3; i++){ setTimeout(function(){ console.log(i); },0); };

答案:3,3,3
解决方法
for(let i = 0; i < 3; i++){ setTimeout(function(){ console.log(i); },0); }; // 0 1 2

for (var i = 0; i < 3; i++) { (function(i) { setTimeout(function () { console.log(i); }, 0, i) })(i) }; // 0 1 2

11、什么是async/await?解决了什么问题?
是generator + Promise的语法糖,主要的作用是用同步方式执行异步操作,await只能在async函数中使用,async函数执行会返回一个Promise,值由函数的return值所决定

12、JS延迟加载的方法有哪些?
1、:给script标签加async属性,则加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步) 2、:给script标签加defer属性,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成 3、动态创建script标签:等到DOMContentLoaded 事件触发时,生成一个script标签,渲染到页面上上 4、setTimeout定时器延迟代码执行

13、new操作符为什么能创建一个实例对象?
分析一下new的整个过程:1、创建一个空对象 2、继承构造函数的原型 3、this指向obj,并调用构造函数 4、返回对象简单实现一下new: function myNew (fn, ...args) { // 第一步:创建一个空对象 const obj = {}// 第二步:继承构造函数的原型 obj.__proto__ =fn.prototype// 第三步:this指向obj,并调用构造函数 fn.apply(obj, args)// 第四步:返回对象 return obj }

14、什么是文档碎片?
是什么:一个容器,用于暂时存放创建的dom元素,使用document.createDocumentFragment()创建
有什么用:将需要添加的大量元素先添加到文档碎片中,再将文档碎片添加到需要插入的位置,大大减少dom操作,提高性能
var oFragmeng = document.createDocumentFragment(); for(var i=0; i<10000; i++) { var op = document.createElement("span"); var oText = document.createTextNode(i); op.appendChild(oText); //先附加在文档碎片中oFragmeng.appendChild(op); } //最后一次性添加到document中 document.body.appendChild(oFragmeng);

15、宏任务与微任务有哪些?
宏任务
# 浏览器 Node
I/O ? ?
setTimeout ? ?
setInterval ? ?
setImmediate ? ?
requestAnimationFrame ? ?
微任务
# 浏览器 Node
Promise.prototype.then catch finally ? ?
process.nextTick ? ?
MutationObserver ? ?
16、Object.defineProperty(target, key, options),options可传什么参数?
value:给target[key]设置初始值 get:调用target[key]时触发 set:设置target[key]时触发 writable:默认false,为true时此属性才能被赋值运算符修改 enumerable:默认false,为true时此属性才能被枚举 configurable:默认为false,为true时此属性的描述符才能被修改,才能被删除

17、什么是防抖?什么是节流?
操作 描述 场景
防抖 频繁去触发一个事件,但是只触发最后一次。以最后一次为准 1、电脑息屏时间,每动一次电脑又重新计算时间 2、input框变化频繁触发事件可加防抖 3、频繁点击按钮提交表单可加防抖
节流 频繁去触发一个事件,但是只能每隔一段时间触发一次 1、滚动频繁请求列表可加节流 2、游戏里长按鼠标,但是动作都是每隔一段时间做一次
18、什么是高阶函数?简单实现一个?
高阶函数:JavaScript的函数其实都指向某个变量。既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。// 简单的高阶函数 function add(x, y, f) { return f(x) + f(y); }//用代码验证一下: add(-5, 6, Math.abs); // 11像数组的map、reduce、filter这些都是高阶函数

19、什么是函数柯里化?简单实现一个?
柯里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。// 普通的add函数 function add(x, y) { return x + y }// Currying后 function curryingAdd(x) { return function (y) { return x + y } }add(1, 2)// 3 curryingAdd(1)(2)// 3

好处
1、参数复用
// 正常正则验证字符串 reg.test(txt)// 普通情况 function check(reg, txt) { return reg.test(txt) }check(/\d+/g, 'test')//false check(/[a-z]+/g, 'test')//true// Currying后 function curryingCheck(reg) { return function(txt) { return reg.test(txt) } }var hasNumber = curryingCheck(/\d+/g) var hasLetter = curryingCheck(/[a-z]+/g)hasNumber('test1')// true hasNumber('testtest')// false hasLetter('21212')// false

2、延迟执行 其实Function.prototype.bind就是科里化的实现例子
function sayKey(key) { console.log(this[key]) } const person = { name: 'Sunshine_Lin', age: 23 } // call不是科里化 sayKey.call(person, 'name') // 立即输出 Sunshine_Lin sayKey.call(person, 'age') // 立即输出 23// bind是科里化 const say = sayKey.bind(person) // 不执行 // 想执行再执行 say('name') // Sunshine_Lin say('age') // 23

20、箭头函数与普通函数的区别?
1、箭头函数不能作为构造函数,不能new 2、箭头函数没有自己的this 3、箭头函数没有arguments对象 4、箭头函数没有原型对象

21、Symbol的应用场景?
使用Symbol充当属性名 使用Symbol充当变量 使用Symbol实现私有属性

22、AMD 和 CMD 的区别?
模块化 代表应用 特点
AMD require.js 1、AMD的api默认一个当多个用 2、依赖前置,异步执行
CMD sea.js 1、CMD的api严格区分,推崇职责单一 2、依赖就近,按需加载,同步执行
23、Commonjs 和 ES6 Module的区别?
1、前者是拷贝输出,后者是引用输出 2、前者可修改引入值,后者只读 3、前者是运行时,后者是编译时

24、为什么Commonjs不适用于浏览器
var math = require('math'); math.add(2, 3); 第二行math.add(2, 3),在第一行require('math')之后运行,因此必须等math.js加载完成。也就是说,如果加载时间很长,整个应用就会停在那里等。这对服务器端不是一个问题,因为所有的模块都存放在本地硬盘,可以同步加载完成,等待时间就是硬盘的读取时间。但是,对于浏览器,这却是一个大问题,因为模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于"假死"状态。因此,浏览器端的模块,不能采用"同步加载"(synchronous),只能采用"异步加载"(asynchronous)。这就是AMD规范诞生的背景。

25、函数的length是多少?
length 是函数对象的一个属性值,指该函数有多少个必须要传入的参数,即形参的个数。形参的数量不包括剩余参数个数,仅包括第一个具有默认值之前的参数个数

26、深度遍历广度遍历的区别?
对于算法来说 无非就是时间换空间 空间换时间1、深度优先不需要记住所有的节点, 所以占用空间小, 而广度优先需要先记录所有的节点占用空间大 2、深度优先有回溯的操作(没有路走了需要回头)所以相对而言时间会长一点 3、深度优先采用的是堆栈的形式, 即先进后出 4、广度优先则采用的是队列的形式, 即先进先出

27、JS中的设计模式有哪些?
创建模式:该模式抽象了对象实例化过程。 结构型模式:这些模式处理不同的类和对象以提供新功能。 行为模式:也称发布-订阅模式,定义了一个被观察者和多个观察者的、一对多的对象关系。 并行设计模式:这些模式处理多线程编程范例。 架构设计模式:这些模式用于处理架构设计

28、JS中如何将页面重定向到另一个页面?
1、使用 location.href:window.location.href =https://www.it610.com/article/“https://www.baidu.com/”) 2、使用 location.replace:window.location.replace(" https://www.baidu.com/; ")

29、JS中鼠标事件的各个坐标?
属性 说明 兼容性
offsetX 以当前的目标元素左上角为原点,定位x轴坐标 除Mozilla外都兼容
offsetY 以当前的目标元素左上角为原点,定位y轴坐标 除Mozilla外都兼容
clientX 以浏览器可视窗口左上角为原点,定位x轴坐标 都兼容
clientY 以浏览器可视窗口左上角为原点,定位y轴坐标 都兼容
pageX 以doument对象左上角为原点,定位x轴坐标 除IE外都兼容
pageY 以doument对象左上角为原点,定位y轴坐标 除IE外都兼容
screenX 以计算机屏幕左上顶角为原点,定位x轴坐标(多屏幕会影响) 全兼容
screenY 以计算机屏幕左上顶角为原点,定位y轴坐标 全兼容
layerX 最近的绝对定位的父元素(如果没有,则为 document 对象)左上顶角为元素,定位 x 轴坐标 Mozilla 和 Safari
layerY 最近的绝对定位的父元素(如果没有,则为 document 对象)左上顶角为元素,定位 y 轴坐标 Mozilla 和 Safari
30、JS中元素视图的各个尺寸?
属性 说明
offsetLeft 获取当前元素到定位父节点的left方向的距离
offsetTop 获取当前元素到定位父节点的top方向的距离
offsetWidth 获取当前元素 width + 左右padding + 左右border-width
offsetHeight 获取当前元素 height + 上下padding + 上下border-width
clientWidth 获取当前元素 width + 左右padding
clientHeight 获取当前元素 height + 上下padding
scrollWidth 当前元素内容真实的宽度,内容不超出盒子宽度时为盒子的clientWidth
scrollHeight 当前元素内容真实的高度,内容不超出盒子高度时为盒子的clientHeight
31、Window视图的各个尺寸?
属性 说明
innerWidth innerWidth 浏览器窗口可视区宽度(不包括浏览器控制台、菜单栏、工具栏)
innerHeight innerHeight 浏览器窗口可视区高度(不包括浏览器控制台、菜单栏、工具栏)
32、Document文档视图的各个尺寸?
属性 说明
document.documentElement.clientWidth 浏览器窗口可视区宽度(不包括浏览器控制台、菜单栏、工具栏、滚动条)
document.documentElement.clientHeight 浏览器窗口可视区高度(不包括浏览器控制台、菜单栏、工具栏、滚动条)
document.documentElement.offsetHeight 获取整个文档的高度(包含body的margin)
document.body.offsetHeight 获取整个文档的高度(不包含body的margin)
document.documentElement.scrollTop 返回文档的滚动top方向的距离(当窗口发生滚动时值改变)
document.documentElement.scrollLeft 返回文档的滚动left方向的距离(当窗口发生滚动时值改变)
33、监听ajax上传进度
//【上传进度调用方法实现】 xhr.upload.onprogress = progressFunction

    推荐阅读