2021 春季 前端最新面试题,js基础到js高阶 从容回答

2021最新面试题,从js基础到js高阶 从容回答

1. JavaScript垃圾回收机制的了解

在JavaScript中的字符串,对象,数组是没有固定大小的,只有当对他们进行动态分配存储时,解释器就会分配内存来存储这些数据,当JavaScript的解释器消耗完系统中所有可用的内存时,就会造成系统崩溃。

内存泄漏,在某些情况下,不再使用到的变量所占用内存没有及时释放,导致程序运行中,内存越占越大,极端情况下可以导致系统崩溃,服务器宕机。

so,JavaScript有自己的一套垃圾回收机制,JavaScript的解释器可以检测到什么时候程序不再使用这个对象了(数据),就会把它所占用的内存释放掉。

针对JavaScript的来及回收机制有以下两种方法(常用):标记清除引用计数

标记清除

当变量进入到执行环境时,垃圾回收器就会将其标记为“进入环境”,当变量离开环境时,就会将其标记为“离开环境”。

垃圾回收器在运行时会给存储在内存中的所有变量都加上标记,接着去掉环境环境中的变量,和被环境中的变量所引用的变量的标记,在此之后再被加上标记的变量将被视为准备删除的变量,就是要删除的变量,垃圾收集器完成内存清除工作,销毁这些带有的标记的值,回收它们所占用的内存空间。

引用计数

说到引用计数,部分人是不知道是啥的,引用计数作为垃圾回收策略的一种,含义是跟踪记录每个值被引用的次数。

当声明了一个变量并将一个引用类型赋值给该变量时,则这个值的引用次数就是为1。

相反的,如果该变量的值变成了另外一个,则这个值的引用次数减一。(当这个值的引用次数变为0的时候,说明没有变量在使用,则这个值没法被访问。)—因而就可以将它占用的空间回收起来,这样垃圾回收器就会在运行的时候清理引用次数为0的值占用的空间。

但是引用计数存在如果相互引用大量的存在会导致大量的内存泄漏;同时如果出现循环引用问题也会导致内存泄漏的问题。

所以,要减少JavaScript中的垃圾回收,在初始化的时候新建对象,然后在后续过程中尽量多的重用这些创建好的对象。我们可以:1. 数组array优化;2. 对象尽量优化;3. 循环优化。

如下内存分配方式:

{} 创建一个新对象
[] 创建一个新数组
funtion(){...} 创建一个新的方法
new Foo() new 关键字,一次内存的分配

重复利用:对对象object的优化,遍历此对象的所有属性,逐个删除属性,最终将对象清空为一个空对象。

2. 说说有几种类型的DOM节点

嗯,好的,DOM节点类型有:Document节点,整个文档是一个文档节点;Element节点,每个HTML标签是一个元素节点;Attribute节点,每一个HTML属性是一个属性节点;Text节点,包含在HTML元素中的文本是文本节点。

3.在script标签中defer和async属性的区别

一般情况下,脚本的下载和执行将会按照文档的先后顺序同步执行,当 脚本下载和执行 的时候,文档解析会被阻塞,在 脚本下载和执行 完成之后文档才会往下继续进行解析。

如果script标签中没有defer或async属性,浏览器在渲染过程中遇到script标签时,会停止渲染来下载执行js代码,等待js执行完毕后,浏览器再从中断的地方恢复渲染。

你会知道这样浏览器会造成阻塞,如果你想要你的项目首屏渲染很快的话,就尽量不要在首屏加载js文件,所以学习的时候会建议将script标签放在body标签底部。

说到defer(延迟执行)和async(异步加载)属性的区别,下面展示使用script标签有以下三种情况:

<script src="dadaqianduan.js"></script> // 浏览器会立即加载并执行相应的脚本

<script async src="dadaqianduan.js"></script> // 后续文档的加载和渲染与js脚本的加载和执行是并行进行的

<script defer src="dadaqianduan.js"></script> // 加载后续文档的过程和js脚本的加载是并行进行的,js脚本的执行需要等到文档所有元素解析完成之后,DOMContentLoaded事件触发执行之前

当加载的js脚本有多个的时候,async是无顺序的加载,而defer是有顺序的加载,defer属性表示延迟执行引入的JavaScript,这段JavaScript加载时HTML并未停止解析,so,defer是不会阻塞html解析的,它是等Dom加载完后再去执行JavaScript代码的。(当html解析过程中,遇到defer属性,就会异步加载该js文件,不会中断HTML文档的解析,当整个HTML解析完成后,回头再来解析该js文件)

  1. 当有defer属性时,脚本的加载过程 和 文档加载 是 异步发生的,等到 文档解析 完脚本才开始执行。
  2. 当有async属性时,脚本的加载过程 和 文档加载 也是异步发生的,这里注意的是 脚本下载完成后,会停止HTML解析先执行脚本脚本解析完继续HTML解析
  3. 同时有async和defer属性时,执行效果与async一致。

defer属性-是否延迟执行脚本,直到页面加载为止;async属性-脚本一旦可用,就异步执行。defer属性并行加载JavaScript文件,会按照页面上的script标签顺序执行,而async并行加载,下载完成就立即执行,不会按照页面上的顺序执行。

4. 说说你对闭包的了解

面试前端,当面试官问你,谈谈你对闭包的理解的时候,该怎么回答呢?

简单说就是 定义在一个函数内部的函数,内部函数持有 外部函数 内的变量 或 参数的引用。内部函数依赖外部函数, 外部函数参数和变量 不会被垃圾回收机制回收,这些变量会始终存在于内存中。

好处可以读取函数内部的变量,可以避免全局变量的污染,坏处会增加内存的使用量,容易导致内存泄漏,解决方法就是退出函数前,将不适用的局部变量全部删除。在JavaScript中,函数即是闭包,只有函数才会产生作用域。

闭包特性,函数嵌套函数,在函数内部可以引用外部的参数和变量,参数和变量不会被垃圾回收机制回收。

由于在js中,变量的作用域属于函数作用域,在函数执行后,作用域就会被清理,内存也会被回收,但是由于闭包是建立在一个函数内部的 子函数,由于子函数可以访问上级作用域的原因,即使上级函数执行完,作用域也不会随之销毁。

在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

代码闭包表现形式:

// 作为函数参数传递
var a = 1;
function foo() {
   
 var a = 2;
 function dada() {
   
  console.log(a);
 }
 da(dada);
}

function da(fn) {
   
 // 闭包
 fn();
}

foo(); // 输出2

5. 解释一下unshift()的方法

unshift()方法可以想数组开头添加一个或多个元素,并返回新的长度。

arrayObject.unshift(newelement1,newelement2,....,newelementX)
newelement1 必需。向数组添加的第一个元素。
newelement2 可选。向数组添加的第二个元素。
newelementX 可选。可添加若干个元素。

返回值- arrayObject 的新长度。

unshift() 方法将把它的参数插入 arrayObject 的头部,并将已经存在的元素顺次地移到较高的下标处,以便留出空间。该方法的第一个参数将成为数组的新元素 0,如果还有第二个参数,它将成为新的元素 1,以此类推。

请注意,unshift() 方法不创建新的创建,而是直接修改原有的数组。该方法会改变数组的长度。

6. 说说encodeURI()和decodeURI()的作用是什么

1.encodeURl( )用于将URL转换为十六进制编码。2.decodeURI( )用于将编码的URL转换回正常URL。

7. 为什么不建议在JavaScript中使用innerHTML

innerHTML内容每次刷新,因此很慢。在innerHTML中没有验证的余地,因此,更容易在文档中插入错误代码,从而使网页不稳定。

8. 在DOM操作中怎样创建,添加,移除,替换,插入,查找节点

DOM节点操作方法:

  1. 访问、获取节点
document.getElementById(id);
// 返回对拥有指定id的第一个对象进行访问

document.getElementsByName(name);
// 返回带有指定名称的节点集合

document.getElementsByTagName(tagName);
// 返回带有指定标签名的对象集合

document.getElementsByClassName(className);
// 返回带有指定class名称的对象集合
  1. 创建节点/属性
createDocumentFragment() //创建一个DOM片段
document.createElement(eName); // 创建一个节点
document.createAttribute(attrName); // 对某个节点创建属性
document.createTextNode(text); // 创建文本节点
  1. 添加节点
document.insertBefore(newNode, referenceNode); // 在某个节点前插入节点
parentNode.appendChild(newNode); // 给某个节点添加子节点
  1. 复制节点
cloneNode(true | false); // 复制某个节点
  1. 删除节点
parentNode.removeChild(node); // 删除某个节点的子节点node是要删除的节点
  1. 属性操作
getAttribute(name) // 通过属性名称获取某个节点属性的值
setAttribute(name,value); // 通过某个节点属性的值
removeAttribute(name); // 删除某个属性
  1. 获取相邻的节点
curtNode.previousSibling; // 获取已知节点的相邻的上一个节点
curtNode.nextSibling; // 获取已知节点的下一个节点

9. 如何实现浏览器内多个标签页之间的通信

使用localStorage,使用localStorage.setItem(key,value);添加内容

使用storage事件监听添加、修改、删除的动作

window.addEventListener("storage",function(event){
    $("#name").val(event.key+"="+event.newValue);});
$(function(){
   
$("#btn").click(function(){
   
 var name = $("#name").val();
 localStorage.setItem("name", name);
 });
});

10. null和undefined的区别是什么

console.log(null==undefined)//true

console.log(null===undefined)//false

null:Null类型,代表“空值”,代表一个空对象指针 (null是javascript的关键字,可以认为是对象类型,它是一个空对象指针,和其它语言一样都是代表“空值”,不过 undefined 却是javascript才有的。)

undefined:Undefined类型,当一个声明了一个变量未初始化时,得到的是undefined。(undefined是访问一个未初始化的变量时返回的值,而null是访问一个尚未存在的对象时所返回的值。因此,可以把undefined看作是空的变量,而null看作是空的对象。)

undefined表示“缺少值”,此处应该有一个值,但是还没有定义。
在这里插入图片描述
null表示“没有对象”,该处不应该有值。
在这里插入图片描述

11. new操作符的作用是什么

new操作符首先,创建了一个空对象:

var obj = new Object();

设置原型链:

obj._proto_ = Object.prototype

在这里插入图片描述
示例代码了解new的作用:

function da(name) { 
	this.name = name;
}
da.prototype.sayName = function() { 
	console.log(this.name);
}
const jeskson = new da('dada');
console.log(jeskson.name); // dadajeskson.sayName(); // dada

由例子得出:

new 通过构造函数 da 创建出来的实例可以访问到构造函数中的属性

new 通过构造函数 da 创建出来的实例可以访问到构造函数原型链中的属性,(通过new操作符,实例与构造函数通过原型链连接了起来)

如果给构造函数一个return返回值,(没有显式的return任何值,默认返回undefined)

function da(name) {
    
	this.name = name; return 1;
}
const jeskson = new da('dada');
console.log(jeskson.name); // dada

这个返回值没有任何的用处,构造函数如果返回原始值,这个返回值没有意义。

function da(name) {
    
	this.name = name; 
	console.log(this); // da {name: 'dada'} 
	return {
   age:1}
}
const jeskson = new da('dada');
console.log(jeskson); // {age:1}
console.log(jeskson.name); // undefined

构造函数如果返回值为对象,那么这个返回值就会被正常使用。

  1. new 操作符会返回一个对象
  2. 这个对象,也就是构造函数中的this,可以访问到挂载在this上的任意属性
  3. 这个对象可以访问到构造函数原型上的属性
  4. 返回原始值会忽略,返回对象会正常处理

12. JavaScript延迟加载的方式有哪些

js的延迟加载有助于提高页面的加载速度

延迟有:defer属性,async属性,动态创建DOM方式,使用JQuery的getScript方法,使用setTimeout延迟方法,让JS最后加载。

使用setTimeout延迟方法

<script type="text/javascript" >
  function A(){
   
    $.post("/lord/login",{
   name:username,pwd:password},function(){
   
      alert("Hello");
    });
  }
  $(function (){
   
    setTimeout('A()', 1000); //延迟1秒
  })
</script>

13. call()和apply()的区别和作用是什么

call(), applay() 都属于Function.prototype的一个方法,它是JavaScript引擎内实现的,属于Function.prototype,所以每个Function对象实例,每个方法都有call,apply属性。

call()和apply() ,它们的作用都是相同的,不同的在于,它们的参数不同。

call(this, arg1, arg2, arg3);
apply(this, arguments);
function add(a,b){
    
	console.log(a+b);
}
function sub(a,b){
   
	console.log(a-b);
}
 add.call(sub, 2, 1);
 add.apply(sub, [2,1]);

对于A.applay(B)或A.call(B),简单地说,B先执行,执行后根据结果去执行A,用A去执行B的内容代码,再执行自己的代码。

var f1 = function(a,b) {
   
 console.log(a+b);
}
var f2 = function(a,b,c) {
   
 console.log(a,b,c);
}
f2.apply(f1,[1,2]) // 1 2 undefined

解析一下就是,先执行f1,f1执行后,这里注意f1是f1,不是f1()执行方法,所以里面的console.log等内容代码并没有执行,相等于,初始化了代码f1,由于没有返回值,结果是undefined,f2执行的时候this指向window。参数中为[1,2],解析后参数为1,2,undefined;执行f2方法后,打印出结果值为:1 2 undefined

A.call(B, 1,2,3) 后面的参数都是独立的参数对象,会被自动解析为A的参数:

var f1 = function(a,b) {
   
 console.log(a+b);
}
var f2 = function(a,b,c) {
   
 console.log(a,b,c);
}
f2.call(f1,[1,2]); // [1,2] undefined undefined
f2.call(f1, 1, 2); // 1 2 undefined

解析一下就是,参数中的[1,2],因为传入了一个数组,相当于只传入了第一个参数,b和c参数没有传。

使用apply()和call():

 //apply用法 
 var arr = new Array(1,2,3) 
 var arr1 = new Array(11,21,31) 
 Array.prototype.push.apply(arr,arr1)
 console.log(arr)//[1, 2, 3, 11, 21, 31]  
 
 //call用法 
 var arr = new Array(1,2,3) 
 var arr1 = new Array(11,21,31) 
 Array.prototype.push.call(arr,arr1[0],arr1[1],arr1[2<
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端酱紫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值