1、获取DOM元素有哪些方法
方法 | 描述 |
document.getElementById(id) | 通过id获取dom |
document.getElementsBy(TagName) | 通过标签名获取dom |
document.getElementsByClassName(class) | 通过classe获取dom |
document.getElementsByName(name) | 通过标签的属性name获取dom |
document.querySelector(selector) | 通过选择器获取dom |
document.querySelectorAll(selector) | 通过选择器获取dom |
2、操作DOM元素有哪些方法
方法 | 描述 |
document.createElement() | 创建标签节点 |
createTextNode() | 创建文本节点 |
cloneNode(deep) | 复制节点标签及标签属性。deep为true(深复制:包括后代节点) |
createDocumentFragment() | 创建文档碎片节点 |
appendChild() | 追加子元素在后面 |
insertBefore() | 将元素插入前面 |
removeChild() | 删除子元素 |
replaceChild() | 替换子元素 |
getAttribute() | 获取节点的属性 |
createAttribute() | 创建属性 |
setAttribute() | 设置节点属性 |
removeAttribute() | 删除节点属性 |
element.attributes() | 将属性生成类数组对象 |
3、DOM的类型有哪几种
文本节点 | Node.TEXT_NODE |
元素节点 | Node.ELEMENT_NODE |
属性节点 | Node.ATTRIBUTE_NODE |
CDATA节点 | Node.CDATA_SECTION_NODE |
实体引用名称节点 | Node.ENTRY_REFERENCE_NODE |
实体名称节点 | Node.ENTITY_NODE |
处理指令节点 | Node.PROCESSING_INSTRUCTION_NODE |
注释节点 | Node.COMMENT_NODE |
文档节点 | Node.DOCUMENT_NODE |
文档类型节点 | Node.DOCUMENT_TYPE_NODE |
文档片段节点 | Node.DOCUMENT_FRAGMENT_NODE |
DTD声明节点 | Node.NOTATION_NODE |
4、JS延迟加载的方法有哪些
- 给script标签加async属性,则加载和渲染后续文档元素的过程将和script.js的加载与执行并行进行(异步)
- 给script标签加defer属性,加载后续文档元素的过程将和script.js的加载并行进行(异步),但是script.js的执行要在所有元素解析完成之后,DOMContentLoaded事件触发之前完成
- 动态创建script标签:等到DOMContentLoaded事件触发时,生成一个script标签,渲染到页面上
- setTimeout定时器延迟代码执行
5、new操作符为什么能创建一个实例对象
- 分析一下new的整个过程:
- 创建一个空对象
- 继承构造函数的原型
- this指向obj,并调用构造函数
- 返回对象
- 简单实现一下new
function myNew(fn, ...args){
//第一步:创建一个空对象
const obj = {}
//第二步:继承构造函数的原型
obj._proto_ = fn.prototype
//第三步:this指向obj,并调用构造函数
fn.apply(obj, args)
//第四步:返回对象
return obj
}
6、includes比indexOf好在哪
- includes可以检测NaN,indexOf不能检测NaN
- includes内部使用了Number.isNaN对NaN进行了匹配
7、什么是async/await?解决了什么问题?
- async/await是es7里面的新语法、它的作用就是async用于申明function是异步的,而await用于等待一个异步方法执行完成。它可以很好的代替Promise中的then
- async函数返回一个Promise对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
async function timeout(ms){
await new Promise((resolve) => {
setTimeout(resolve,ms);
console.log(1);
});
}
async function asyncPrite(value, ms){
await timeout(ms);
console.log(value)
}
asyncPrint('Hello',100) //1 Hello
8、Object.defineProperty(target,key,options),options可传什么参数
- value:给target[key]设置初始值
- writable:默认false,为true时此属性才能被赋值运算符修改
- enumerable:默认fasle,为true时此属性才能被枚举
- configurable:默认为false,为true时此属性的描述符才能被修改,才能被删除
- get:调用target[key]时触发
- set:设置target[key]时触发
9、什么是文档碎片
文档碎片是一个容器,用于暂时存放创建的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);
10、什么是防抖
频繁去触发一个事件,只触发最后一次,以最后一次为准
- 应用场景
- 电脑息屏时间,每动一次电脑又重新计算时间
- input框变化频繁触发事件可加防抖
- 频繁点击按钮提交表单可加防抖
11、什么是节流
频繁去触发一个事件,每隔一段时间触发一次
- 应用场景
- 滚动频繁请求列表可加节流
- 游戏里长按鼠标,但是动作都是每隔一段时间做一次
12、什么是高阶函数?简单实现一个
- JavaScript的函数其实都指向某个变量。既然变量可以指向函数,函数的参数能接收变量
- 那么一个函数就可以接收另外一个函数作为参数,这种函数就称之为高阶函数
- 像数组的map、reduce、filter这些都是高阶函数
//简单的高阶函数
function add(x, y, f){
return f(x) + f(y);
}
//代码验证
add(-9, 6, Math.abs) //15
13、箭头函数与普通函数的区别
- 箭头函数 没有自己的this
- 箭头函数 没有arguments对象
- 箭头函数 不具有prototype原型对象
- 箭头函数 不能作为构造函数,不能new
- 箭头函数 不能Generator函数,不能使用yeild关键字
- 箭头函数 不具有super
- 箭头函数 不具有new.target
14、函数的length是多少
- length是函数对象的一个属性值,指该函数有多少个必须要传入的参数,即形参的个数
- 形参的数量不包括剩余参数个数,仅包括第一个具有默认值之前的参数个数
15、深度遍历/广度遍历的区别
对于算法来说,无非就是时间换空间,空间换时间
- 深度优先不需要记住所有的节点,所以占用空间小,而广度优先需要先记录所有的节点占用空间大
- 深度优先有回溯的操作(没有路走了需要回头看)所以相对而言时间会长一些
- 深度优先采用的是堆栈的形式,即先进后出
- 广度优先采用的是队列的形式,即先进先出
16、JS中的设计模式有哪些
- 创建模式:该模式抽象了对象实例化过程
- 结构型模式:这些模式处理不同的类和对象以提供新功能
- 行为模式:也称发布-订阅模式,定义了一个被观察者和多个观察者的、一对多的对象关系
- 并行设计模式:这些模式处理多线程编程范例
- 架构设计模式:这些模式用于处理架构设计
17、JS中如何将页面重定向到另一个页面
- 使用 location.href:window.location.href=("http://www.baidu.com/")
- 使用 location.replace:window.location.replace("http://www.baidu.com/")
18、JS中鼠标事件的各个坐标
- offsetX offsetY 以当前的目标元素左上角为原点,定位x,y轴坐标
- clientX clientY 以浏览器可视窗口左上角为原点,定位x,y轴坐标
- pageX pageY 以doument对象左上角为原点,定位x,y轴坐标
- screenX screenY 以计算机屏幕左上顶角为原点,定位x,y轴坐标(多屏幕会影响)
- layerX layerY 最近的绝对定位的父元素(如没有则为document),左上顶角为元素,定位x,y轴坐标
19、JS中元素视图的各个尺寸
- offsetWidth / offsetHeight 获取当前元素width / Height + padding + border-width
- clientWidth / clientHeight 获取当前元素width / Height + padding
- scrollWidth / scrollHeight 当前元素内容真实宽/高,内容不超出盒子宽/高时为盒子的clientWidth
20、Window视图的各个尺寸
- innerWidth // innerWidth 浏览器窗口可视区宽度(不包括浏览器控制台、菜单栏、工具栏)
- innerHeight // innerHeight浏览器窗口可视区高度(不包括浏览器控制台、菜单栏、工具栏)
21、监听ajax上传进度
xhr.upload.onprogress = progressFunction
22、深拷贝和浅拷贝的区别
- 浅拷贝:只拷贝第一层,深层的依然是引用,改变深层会影响原对象
- 深拷贝:每一层都拷贝了,改变数据不会影响元对象
23、symbol的应用场景
Symbol是ES6中新增的一种数据类型,被划分到了基本数据类型中
基本数据类型:字符串、数值、布尔、undefined、null、Symbol
引用数据类型:Object
- 使用Symbol充当属性名
- 使用Symbol充当变量
- 使用Symbol实现私有属性
24、Commonjs和ES6 Module的区别
- Commonjs是拷贝输出,ES6 Module是引用输出
- Commonjs可修改引入值,ES6 Module只读
- Commonjs是运行时,ES6 Module是编译时
25、为什么Commonjs不适用于浏览器
- var math = require('math');
- math.add(2,3);
第二行math.add(2,3),在第一行require('math')之后运行,因此必须等math.js加载完成。也就是说,如果加载时间很长,整个应用就会停在那里等。这对服务器端不是一个问题,因为所有的模块都存放在本地硬盘,可以同步加载完成,等待时间就是硬盘读取的时间。
但是,对于浏览器,这却是一个大问题,因为模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长的时间,浏览器处于“假死”状态。因此,浏览器端的模块,不能采用“同步加载”(synchronous),只能采用“异步加载”(asynchronous)。这就是AMD规范诞生的背景。
26、什么是原型链,constructor的指向是
- 原型链是一条引用的链,实例的隐式原型_proto_指向构造函数的显示原型prototype,
- 可以使用A instanceof B来判断B是否在A 的原型链上
- constructor指向构造函数
27、什么是闭包
- 闭包是一个函数,闭包是访问其他函数内部变量的函数,也就是函数 + 上下文代码组合
- 优点:使外部能访问内部,延长内部变量的寿命,解决变量污染
- 缺点:滥用闭包造成内存泄露
28、isNaN与Number.isNaN的区别
- isNaN:除了判断NaN为true外,还会把不能转成数字判断为true,例如‘dasd’
- Number.isNaN:只会判断NaN为true
29、解决遍历对象时,把原型上的属性遍历出来了咋办?
使用hasOwnProperty判断
function Person(name){
this.name = name
}
Person.prototype.age = 23
const person = new Person('Sunshine_lin')
for(const key in person){ console.log(key)} //name age
//使用 hasOwnProperty
for (const key in person){
person.hasOwnProperty(key) && console.log(key)
} //name
30、valueOf与toString?
- valueOf比较偏向于计算,toString偏向于显示
- 对象转换时,优先调用toString
- 强转字符串时优先调用toString,强转数字时优先调用valueOf
- 正常情况下,优先调用toString
- 运算操作符情况下优先调用valueOf
31、JavaScript变量在内存中具体存储形式
- 基本数据类型:存在栈内存中
- 引用数据类型:指针存在栈内存里,指向堆内存中一块地址,内容存在堆内存中
32、null和undefined的异同点有哪些
- 相同点
- 都是空类型
- 转布尔值都是false,都是假值
- null == undefined 为 true
- 不同点
- typeof,前者为object,后者为undefined
- null转数字为0,undefined转数字为NaN
- null == undefined为false
33、如何判断数据类型
- typeof:能判断string、number、undefined、boolean、function、object(null是object)
- Object.prototype.toString.call():能判断大部分数据类型
- instanceOf 判断引用数据类型
34、为什么typeof null是object?
- 不同数据类型底层都是用二进制来表示的,二进制前三位为000则会被判断为object
- 而null二进制全是0,所以被判断成object
35、== 与 === 的区别
- ==:比较过程会进行隐式转换
- ===:值相同,类型相同才会为true
36、NaN是什么?有什么特点?
NaN是Not a Number(不是一个数值的缩写),它表示储存数据的数据类型。
- typeof NaN为 number
- NaN不等于自身,不大于自身,不小于自身
- NaN可以使用Number.isNaN判断
- NaN是假值,转布尔值为false
37、JavaScript的隐式转换规则?
- 转string类型:+ (字符串连接符)
- 转number类型:++/--(自增自减运算符) +-*/%(算术运算符) > < >= <= == != === !==(关系运算符)
- 转boolean:!(逻辑非运算符)
38、双等号左右两边的转换规则
- null == undefined 为 true
- 如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值==>false转换为0,而true转换为1
- 如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值
- 一个操作数是对象,另一个操作数不是,则调用对象的toString()方法,用得到的基本类型值按照前面的规则进行比较
39、undefined >= undefined 为什么是false
隐式转换,变成NaN >= NaN,NaN不等于自身也不大于自身
40、null >= null 为什么是true
隐式转换,变成 0>=0,为true
41、[] == ![] 为什么是true?
- 第一步:转为[] == false
- 第二步:转为[] == 0
- 第三步:转为'' == 0
- 第四步:转为 0 == 0
42、0.1+0.2 === 0.3,对吗?
- 不对,JavaScripe存在精度丢失的问题,由于有些小数无法用二进制表示,所以只能取近似值
- 解决方法有:先转大数,再变小数 使用toFixed
43、绑定点击事件有几种方式
2种,加行内事件绑定的话是3种
- btn.onclick = function(){}
- btn.addEventListener('click',function(){},false)
44、addEventListener的第三个参数是干嘛的?
DOM方法 addEventListener() 和 removeEventListener() 是用来分配和删除事件的函数。这两个方法都需要三个参数,分别为:
事件名称(String)、要触发的事件处理函数(Function)、指定事件处理函数的时期或阶段(boolean)
DOM事件流如图:
由图可知捕获过程要先于冒泡过程
当第三个参数设置为true就在捕获过程中执行,反之就在冒泡过程中执行处理函数。
45、函数声明和函数表达式的区别
- 函数声明:享受函数提升
- 函数表达式:归类于变量声明,享受变量提升
- 函数提升优先级 > 变量提升优先级
46、JavaScript的事件流模型有哪些?
- 事件冒泡:由最具体的元素接收,并往上传播
- 事件捕获:由最不具体的元素接收,并往下传播
- DOM事件流:事件捕获 -> 目标阶段 -> 事件冒泡
47、Ajax、Axios、Fetch有啥区别
- Ajax:是对于XMLHttpRequest(XHR)的封装
- Axios:是基于Promise对XHR对象的封装
- Fetch:是window的一个方法,基于Promise,与XHR无关,不兼容IE
48、什么是事件委托
当元素都需要绑定相同的事件时,可以将事件绑在父元素上,优点有:
- 绑定在父元素,则只需绑定一次,节省性能
- 后续新增的子元素可以触发父元素绑定的事件
49、Set与Array的区别是什么?
- Set使用has判断有无元素,数组使用索引
- Set添加元素使用方法add,数组用push、unshift
- Set长度为size,数组为length
- Set会自动把同样的基础数据类型去重,数组不能
- Set删除元素用delete,数组用splice、pop、shift
- Set可以使用clear清空,数组需要重新赋值
- 数组可以传入new Set(array),实现数组转Set
- Set可以使用keys,value,转数组
- Set自带forEach方法进行遍历
50、Map与Object的区别是什么
- Map使用set设置属性,对象使用obj[key] = value
- Map使用get获取属性,对象使用obj[key]
- Map使用has判断属性存在与否,对象只能obj[key]
- Map删除元素使用delete方法,对象使用delete关键字
- Map使用clear进行清空,对象需要重新赋值
- Map和对象都可以使用entries方法转数组键值对
- Map自带forEach方法进行遍历