javascript面试重点
![9a0b71283336eed5c4df059b29200880.png](https://i-blog.csdnimg.cn/blog_migrate/825a7cefb3b589d41e2c52ab10034c28.jpeg)
什么是执行上下文
执行上下文就是当前 JavaScript 代码被解析和执行时所在环境的抽象概念, JavaScript 中运行任何的代码都是在执行上下文中运行
![1921879165a5cd05c5e4ad9a3d63c8fa.png](https://i-blog.csdnimg.cn/blog_migrate/dfd44888b41cfbb4e05b878da7354c28.jpeg)
这是因为当函数执行的时候,首先会形成一个新的私有的作用域,然后依次按照如下的步骤执行
- 如果有形参,先给形参赋值
- 进行私有作用域中的预解释,函数声明优先级比变量声明高,最后后者会被前者覆盖,但是可以重新赋值
- 私有作用域中的代码从上到下执行
闭包是什么
个人理解为,闭包就是函数中的函数,里面的函数可以访问外面函数的变量,外面的变量是这个内部函数的一部分
闭包的作用
- 使用闭包可以访问函数中的变量
- 可以长期保存在内存中,声明周期比较长
- 注意:闭包不能乱用,否则会导致内存泄露,影响网页的性能。闭包使用完之后,要立即释放资源,将引用的变量指向null
闭包的主要应用
- 函数作为参数传递
- 函数作为返回值
异步和单线程
JS 需要异步的根本原因是 JS 是单线程运行的,即在同一时间只能做一件事,不能“一心二用”。为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。
一个 Ajax 请求由于网络比较慢,请求需要 5 秒钟。如果是同步,这 5 秒钟页面就卡死在这里啥也干不了了。异步的话,就好很多了,5 秒等待就等待了,其他事情不耽误做,至于那 5 秒钟等待是网速太慢,不是因为 JS 的原因
前端使用异步的场景
- setTimeout setInterval
- 网络请求ajax,动态加载
- 事件绑定
原型和原型链
原型:在JavaScript中原型是一个prototype对象,用于表示类型之间的关系。
原型链:JavaScript万物都是对象,对象和对象之间也有关系,并不是孤立存在的。对象之间的继承关系,在JavaScript中是通过prototype对象指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的链条,专业术语称之为原型链。
var Person = function(){ this.name = '匿名', this.age = 18 } var Student = function(){} Student.prototype = new Person(); var s1 = new Student();
DOM操作
- 新增节点和移动节点
var div1 = document.getElementById('div1');var p1 = document.creatElement('p'); //添加新节点p1.innerHTML = "this is p1"; div1.appendChild(p1); //添加新创建的元素var p2 = document.getElementById('p2');div1.appendChild(p2); //移动元素,这里的p2不加引号
- 获取父元素
var div1 = document.getElementById('div1');var par = div1.parentElement;
- 获取子元素
var p2 = document.getElementById('p2');var child = p2.childNodes; //返回子元素的标签数组
DOM时间模型和事件流
DOM事件模型氛围捕获和冒泡。 一个事件发生后,会在子元素和父元素之间传播,这种传播分成三个阶段
- 捕获阶段 事件从window对象自上而下向目标节点传播的阶段
- 目标阶段 真正的目标节点正在处理事件的阶段
- 冒泡阶段 事件从目标节点自下而上向window对象传播的阶段
捕获是从上到下,事件先从window对象,然后再到document对象,然后是html标签,(通过document.documentElement获取html标签),然后是body标签,(通过document.body获取body标签),然后按照普通的html结构一层一层往下传,最后到达目标元素
阻止冒泡
ev.stopPropagation()
![dfb1fe7e659f3b775d1563105ce52679.png](https://i-blog.csdnimg.cn/blog_migrate/22622e14888efc1926a982fc7f46ba37.jpeg)
事件代理(事件委托)
由于事件会在冒泡的阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件,这种方式叫做事件的代理
我们设定一种场景,一个div包含若干个a,而且还能继续增加,那如何快捷方便的为所有a绑定事件呢
![a0537a39a86b64699bc0f504f8ccc527.png](https://i-blog.csdnimg.cn/blog_migrate/39e7151587d28ba5fef15f08d8f38f5f.jpeg)
如果给每个a标签都绑定一个事件,那对内存的消耗是非常巨大的,借助事件代理,我们只需要给父容器div绑定方法即可,
这样不管是点击的哪一个后代元素,都会根据冒泡传播的传递机制,把父容器的click事件触发,然后把对应的方法执行,根据事件源,
我们可以知道点击的是谁,从而完成不同的事情
a标签的各种属性都可以获取到,取需要的数据就可以了
使用代理的优点
- 代码简洁
- 减少浏览器的内存占用
BOM操作
BOM(浏览器对象模型)是浏览器本身的一些信息的设置和获取,例如获取浏览器的宽度、高度、设置让浏览器跳转哪个地址
- window.screen 对象,包含有关屏幕的信息
- window.location对象,用户获取当前地址的url,并把浏览器定向到新的页面
- window.history对象,浏览历史的前进后退
- window.navigator对象,常常用来获取浏览器信息,是否移动端访问
获取屏幕的宽高
window.widthwindow.height
获取网址,协议,path,参数,hash等
// 例如当前网址是 https://juejin.im/timeline/frontend?a=10&b=10#someconsole.log(location.href) // https://juejin.im/timeline/frontend?a=10&b=10#someconsole.log(location.protocol) // https:consloe.log(location.pathname) //timeline/frontendconsloe.log(location.search) //?a=10&b=10consloe.log(location.hash) // #some
浏览器的前进后退
history.back()history.forward()
获取浏览器的特性,然后识别客户端,例如判断是不是chrom浏览器
var ua = navigator.userAgentvar isChrom = ua.indexOf('Chrom')console.log(isChrom)
![62fc1a777f3416daba65962a1fda3321.png](https://i-blog.csdnimg.cn/blog_migrate/8dc1398beaea250d8e3c5a25656417d3.jpeg)