前端面试总结七

1.JS的事件冒泡和事件捕获
事件
事件是文档和浏览器窗口中发生的特定的交互瞬间。事件是javascript应用跳动的心脏,也是把所有东西黏在一起的胶水,当我们与浏览器中web页面进行某些类型的交互时,事件就发生了。
事件可能是用户在某些内容上的点击,鼠标经过某个特定元素或按下键盘上的某些按键,事件还可能是web浏览器中发生的事情,比如说某个web页面加载完成,或者是用户滚动窗口或改变窗口大小。

事件流:
事件流描述的是从页面中接受事件的顺序,但有意思的是,微软(IE)和网景(Netscape)开发团队居然提出了两个截然相反的事件流概念,IE的事件流是事件冒泡流(event bubbling),而Netscape的事件流是事件捕获流(event capturing)。

事件冒泡
IE提出的事件流叫做事件冒泡,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点,看一下以下示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body onclick="bodyClick()">

    <div onclick="divClick()">
        <button onclick="btn()">
            <p onclick="p()">点击冒泡</p>
        </button>
    </div>
    <script>
       
       function p(){
    
          console.log('p标签被点击')
       }
        function btn(){
    
            console.log("button被点击")
        }
         function divClick(event){
    
             console.log('div被点击');
         }
        function bodyClick(){
    
            console.log('body被点击')
        }

    </script>

</body>
</html>

接下来我们点击一下页面上的p元素,看看会发生什么:
在这里插入图片描述
正如上面我们所说的,它会从一个最具体的的元素接收,然后逐级向上传播, p=>button=>div=>body…事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。

事件捕获
网景公司提出的事件流叫事件捕获流。
事件捕获流的思想是不太具体的DOM节点应该更早接收到事件,而最具体的节点应该最后接收到事件,针对上面同样的例子,点击按钮,那么此时click事件会按照这样传播:(下面我们就借用addEventListener的第三个参数来模拟事件捕获流)。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div>
    <button>
        <p>点击捕获</p>
    </button>
</div>
<script>
    var oP=document.querySelector('p');
    var oB=document.querySelector('button');
    var oD=document.querySelector('div');
    var oBody=document.querySelector('body');

    oP.addEventListener('click',function(){
    
        console.log('p标签被点击')
    },true);

    oB.addEventListener('click',function(){
    
        console.log("button被点击")
    },true);

    oD.addEventListener('click',  function(){
    
        console.log('div被点击')
    },true);

    oBody.addEventListener('click',function(){
    
        console.log('body被点击')
    },true);

</script>



</body>
</html>

同样我们看一下后台的打印结果:
在这里插入图片描述
正如我们看到的,和冒泡流万全相反,从最不具体的元素接收到最具体的元素接收事件 body=>div=>button=>p

DOM事件流:
‘DOM2级事件’规定的事件流包含3个阶段,事件捕获阶段、处于目标阶段、事件冒泡阶段。首先发生的事件捕获为截获事件提供机会,然后是实际的目标接收事件,最后一个阶段是事件冒泡阶段,可以在这个阶段对事件做出响应。
   在DOM事件流中,事件的目标在捕获阶段不会接收到事件,这意味着在捕获阶段事件从document到

就停止了,下个阶段是处于目标阶段,于是事件在

上发生,并在事件处理中被看成冒泡阶段的一部分,然后,冒泡阶段发生,事件又传播回document。
下面是我们模拟它的示例:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button id="btn">DOM事件流</button>
<script>
var btn=document.getElementById("btn");
btn.onclick=function(event){
    
console.log("div 处于目标阶段");
};
document.body.addEventListener("click",function(event){
    
console.log("event bubble 事件冒泡");
},false);
document.body.addEventListener("click",function(event){
    
console.log("event catch 事件捕获");
},true);
</script>


</body>
</html>

看看后台给出什么结果:
在这里插入图片描述
在这里插入图片描述
就是这样一个流程,先捕获,然后处理,然后再冒泡出去。

2.JavaScript中var、let和const的区别
在ES6(ES2015)出现之前,JavaScript中声明变量就只有通过 var 关键字,函数声明是通过 function 关键字,而在ES6之后,声明的方式有 var 、 let 、 const 、 function 、 class ,本文主要讨论 var 、 let 和 const 之间的区别。

var
如果使用关键字 var 声明一个变量,那么这个变量就属于当前的函数作用域,如果声明是发生在任何函数外的顶层声明,那么这个变量就属于全局作用域。举例说明:

var a = 1; //此处声明的变量a为全局变量
function foo(){
   
   var a = 2;//此处声明的变量a为函数foo的局部变量
   console.log(a);//2
}
foo();
console.log(a);//1

如果在声明变量时,省略 var 的话,该变量就会变成全局变量,如全局作用域中存在该变量,就会更新其值。如:

var a = 1; //此处声明的变量a为全局变量
function foo(){
   
   a = 2;//此处的变量a也是全局变量
   console.log(a);//2
}
foo();
console.log(a);//2

注意:var 声明的变量存在提升(hoisting)。
提升是指无论 var 出现在一个作用域的哪个位置,这个声明都属于当前的整个作用域,在其中到处都可以访问到。注意只有变量声明才会提升,对变量赋值并不会提升。如下例所示:

console.log(a);//undefined
var a = 1;

该代码段跟下列代码段是一样的逻辑:

var a;
console.log(a);//undefined
a = 1;

而如果对未声明过的变量进行操作,就会报错

console.log(b);//假设b未声明过,Uncaught ReferenceError: b is not defined

let
let 声明的变量,具有如下几个特点:
(1)let 声明的变量具有块作用域的特征。
(2)在同一个块级作用域,不能重复声明变量。
(3)let 声明的变量不存在变量提升,换一种说法,就是 let 声明存在暂时性死区(TDZ)。
如下面几个例子所示

let a = 1;
console.log(a);//1
console.log(b);//Uncaught ReferenceError: b is not defined
let b = 2;
function foo(){
   
    let a = 1;
    let a = 2;//Uncaught SyntaxError: Identifier 'a' has already been declared
}

以下是一个经典的关于 var 和 let 的一个例子:

 for (var i = 0; i < 10; i++) {
   
    setTimeout(function(){
   
        console.log(i);
    },100)
};

该代码运行后,会在控制台打印出10个10.若修改为:

for (let i = 0; i < 10; i++) {
   
    setTimeout(function(){
   
        console.log(i);
    },100)
};

则该代码运行后,就会在控制台打印出0-9.

const
const 声明方式,除了具有 let 的上述特点外,其还具备一个特点,即 const 定义的变量,一旦定义后,就不能修改,即 const 声明的为常量。
例如:

const a = 1;
console.log(a);//1
a = 2;
console.log(a);//Uncaught TypeError: Assignment to constant variable.

但是,并不是说 const 声明的变量其内部内容不可变,如:

const obj = {
   a:1,b:2};
console.log(obj.a);//1
obj.a = 3;
console.log(obj.a);//3

所以准确的说,是 const 声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。

总结
(1)var 声明的变量属于函数作用域,let 和 const 声明的变量属于块级作用域;
(2)var 存在变量提升现象,而 let 和 const 没有此类现象;
(3)var 变量可以重复声明,而在同一个块级作用域,let 变量不能重新声明,const 变量不能修改。

3.线程和进程
线程是什么?进程是什么?二者有什么区别和联系?
(1)线程是CPU独立运行和独立调度的基本单位;
(2)进程是资源分配的基本单位;
两者的联系:进程和线程都是操作系统所运行的程序运行的基本单元。
区别:
(1)进程具有独立的空间地址,一个进程崩溃后,在保护模式下不会对其它进程产生影响。
(2)线程只是一个进程的不同执行路径,线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉。

什么是堆栈?有什么区别?
堆栈都是一种数据项按序排列的数据结构,只能在一端对数据项进行插入和删除。在单片机应用中,堆栈是个特殊的存储区,主要功能是暂时存放数据和地址,通常用来保护断点和现场。要点:堆,队列优先,先进先出(FIFO—first in first out)。栈,先进后出(FILO—First-In/Last-Out)。

内存的分区:常量区,静态区(全局区),堆,栈,代码区
(1)管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生内存泄露。
(2)申请大小:如果栈申请的空间超过栈的剩余空间时,将提示内存溢出(8M)。因此,能从栈获得的空间较小。堆是由于系统是用链表来存储的空闲内存地址的,不是连续的堆获的空间比较灵活,也比较大。
(3)碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎 片,使程序效率降低对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出
(4)分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
(5)分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的

多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差写,对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

什么是多线程࿱

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
2021前端面试真题pdf是一个面向前端开发人员的面试准备资料,里面包含了一系列与前端开发相关的问题和答案。该pdf的目的是帮助前端开发人员更好地准备和应对面试,提高面试成功的机会。 该pdf的内容通常包括以下几个方面: 1. HTML、CSS和JavaScript基础知识:这些问题涉及到HTML标签的用法、CSS属性的应用和JavaScript语法等基础知识点,考察面试者对于前端基础的掌握程度。 2. 前端框架和工具:这些问题涉及到常见的前端框架,例如React、Vue等,以及前端开发常用的工具,例如Webpack和Babel等,考察面试者对于一些流行的前端框架和工具的了解和应用能力。 3. 前端性能优化和安全:这些问题涉及到前端性能优化的技巧和策略,例如减少HTTP请求、缓存、懒加载等,以及前端安全的相关知识,例如跨站脚本攻击(XSS)和跨站请求伪造(CSRF)等,考察面试者对于前端性能优化和安全的了解和实践经验。 4. 前端面试题和项目经验:该pdf中可能包含一些真实的前端面试题目,以及要求面试者提供自己在前端开发领域的项目经验和解决问题的能力,目的是评估面试者的实际应用能力和解决问题的思路。 通过研究和回答该pdf中的问题,前端开发人员可以对自己的前端知识进行系统的总结和复习,为面试做好准备。此外,该pdf还可以帮助面试者了解当前前端开发领域的热点和趋势,更好地适应行业的发展要求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值