- 1. JavaScript 垃圾回收机制的了解
- 2.说说有几种类型的 DOM 节点
- 3.在 script 标签中 defer 和 async 属性的区别
- 4.说说你对闭包的了解
- 5. 解释一下 unshift()的方法
- 6. 说说 encodeURI()和 decodeURI()的作用是什么
- 7. 为什么不建议在 JavaScript 中使用 innerHTML
- 8. 在 DOM 操作中怎样创建,添加,移除,替换,插入,查找节点
- 9. 如何实现浏览器内多个标签页之间的通信
- 10. null 和 undefined 的区别是什么
- 11. new 操作符的作用是什么
- 12. JavaScript 延迟加载的方式有哪些
- 13. call()和 apply()的区别和作用是什么
- 14. 哪些操作会造成内存泄漏
- 15. 说说 JavaScript 对象的几种创建方式
- 16. 如何实现异步编程
- 17.说说 JavaScript 的同源策略
- 18.说一下为啥要有同源限制
- 19.在 JavaScript 中,为啥说函数是第一类对象
- 20.函数声明与函数表达式的区别
- 21. 如何删除一个 cookie
- 22. 写一下一个方法,求字符串的长度
- 23.attribute 和 property 的区别是什么
- 24.延迟脚本在 JavaScript 中有什么作用
- 25.说说什么是闭包,闭包的优缺点是什么
- 26. 判断一个对象是否属于某个类
- 27. 你知道有个函数,执行直接对象查找时,它始终不会查找原型,这是什么函数
- 28. document.write 和 innerHTML 的区别
- 29.在 JavaScript 中读取文件的方法是什么
- 30. 如何分配对象属性
- 31. 常用的 JavaScript 语句基本规范
- 32. eval 的功能是什么
- 33. 如下执行结果:
- 34.说说 this 对象的理解
- 35. 在 JavaScript 中什么是类(伪)数组,如何将类(伪)数组转换为标准数组
- 36. JavaScript 中的 callee 和 caller 的作用是什么
- 37. 统计字符串中字母的个数或统计最多的字母:
- 38. 写一个函数,清除字符串前后的空格
- 39. 写一个函数实现一个数组合并的方法
- 40. 工作中,常用的逻辑运算符有哪些
- 41. 什么是事件代理(事件委托)
- 42. 什么是未声明和未定义的变量
- 43. 什么是全局变量,这些变量如何声明,使用全局变量有哪些问题
- 44. 常用的定时器工作说明,使用定时器的缺点
- 45. 说说 ViewState 和 SessionState 有什么区别
- 46. 什么是===运算符
- 47. JavaScript 中的循环结构有哪些
- 48.在 JavaScript 中的 null 表示什么
- 49.delete 操作符的功能有什么
- 50.在 JavaScript 中有哪些类型的弹出框
- 51.常见的 void(0)的作用是什么
- 52.什么是 JavaScript cookie
- 53. 解释 JavaScript 中的 pop()方法
- 54. 在 JavaScript 中,datatypes 的两个基本组是什么
- 55. typeof 是用来做什么的
- 56. 在 JavaScript 中,push 方法的作用是什么
- 57. 在 JavaScript 中,unshift 方法的作用是什么
- 58. 如何为对象添加属性
- 59. 说说 window.onload 和 onDocumentReady
- 60. 说说 for-in 循环
- 61. 说说 JavaScript 中的匿名函数
- 62. 说说一下事件冒泡
- 63. JavaScript 里函数参数 arguments 是数组吗
- 64. 什么是构造函数,它与普通函数有什么区别
- 65. 说说 split()与 join()函数的区别
- 66. 说说你对原型链, prototype 的理解
- 67. typeof 与 instanceof 的区别是什么
- 68. 说说事件流吧
- 69. 说说事件捕获
- 70. 说说什么是回调函数
- 71. 什么是自执行函数,它有哪些应用场景,有什么好处
- 72. 什么是事件委托,有什么好处
- 73. 什么是强制类型转换,什么是隐式类型转换
- 74. NaN 是什么,它的类型是什么,如何可靠地判断一个值是否等于 NaN
- 75. 什么是跨域
- 76. 以 YYYY-MM-DD 的方式,输出当天的日期,比如当天是 2020 年 1 月 1 日,则输出 2020-01-01
- 77. 用 JavaScript 随机选取 10 到 100 之间的 10 个数字,把它们存入一个数组中并排序
- 78. 为了实现一个函数 clonoe,可以对 JavaScript 中 5 种主要的数据类型(Number,String,Object,Array,Boolean)进行值(深)复制。
- 79. 如何消除数组中重复的元素
- 80. 说明 DOM 对象的 3 中查询方式
- 81. 用面向对象的 JavaScript 代码介绍一下自己
- 82. 什么是变量作用域
- 83. 在 JavaScript 中的继承是如何工作的
- 84. 说说你对作用域链的理解
- 85. 说说 JavaScript 中的原型链
- 86. 说说函数的三种定义方式
- 87. JavaScript 里的全局对象是什么,如何调用
- 88. 说说几个常见的 JavaScript 内置对象,并指出它们的优点
- 89. 什么是 DOM,DOM 分为哪三种
- 90. 说说 cookie 的兼容性,缺点等
- 91. 说说栈和队列的区别
- 92. 说说 cookie 和 session 的区别
今天是我 2021 年分享的第一篇文章,是关于 JavaScript 面试题的,毕竟年底了有很多小伙伴蠢蠢欲动,哈哈。所以真心希望可以通过这篇文章,能够给你得到帮助。
1. JavaScript 垃圾回收机制的了解
对于在 JavaScript 中的字符串,对象,数组是没有固定大小的,只有当对他们进行动态分配存储时,解释器就会分配内存来存储这些数据,当 JavaScript 的解释器消耗完系统中所有可用的内存时,就会造成系统崩溃。
内存泄漏,在某些情况下,不再使用到的变量所占用内存没有及时释放,导致程序运行中,内存越占越大,极端情况下可以导致系统崩溃,服务器宕机。
因此,JavaScript 有自己的一套垃圾回收机制,JavaScript 的解释器可以检测到什么时候程序不再使用这个对象了(数据),就会把它所占用的内存释放掉。
针对 JavaScript 的来及回收机制有以下两种方法(常用):标记清除,引用计数。
标记清除
当变量进入到执行环境时,垃圾回收器就会将其标记为“进入环境”,当变量离开环境时,就会将其标记为“离开环境”。
垃圾回收器在运行时会给存储在内存中的所有变量都加上标记,接着去掉环境环境中的变量,和被环境中的变量所引用的变量的标记,在此之后再被加上标记的变量将被视为准备删除的变量,就是要删除的变量,垃圾收集器完成内存清除工作,销毁这些带有的标记的值,回收它们所占用的内存空间。
引用计数
说到引用计数,部分人是不知道是啥的,引用计数作为垃圾回收策略的一种,含义是跟踪记录每个值被引用的次数。
当声明了一个变量并将一个引用类型赋值给该变量时,则这个值的引用次数就是为 1。
相反的,如果该变量的值变成了另外一个,则这个值的引用次数减一。(当这个值的引用次数变为 0 的时候,说明没有变量在使用,则这个值没法被访问。)—因而就可以将它占用的空间回收起来,这样垃圾回收器就会在运行的时候清理引用次数为 0 的值占用的空间。
但是引用计数存在如果相互引用大量的存在会导致大量的内存泄漏;同时如果出现循环引用问题也会导致内存泄漏的问题。
所以,要减少 JavaScript 中的垃圾回收,在初始化的时候新建对象,然后在后续过程中尽量多的重用这些创建好的对象。我们可以:
- 数组
array优化; - 对象尽量优化;
- 循环优化
如下内存分配方式:
{} 创建一个新对象
[] 创建一个新数组
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="mybj.js"></script> // 后续文档的加载和渲染与 js 脚本的加载和执行是并行进行的 <script async src="mybj.js"></script> // 加载后续文档的过程和 js 脚本的加载是并行进行的,js 脚本的执行需要等到文档所有元素解析完成之后,DOMContentLoaded 事件触发执行之前 <script defer src="mybj.js"></script>
当加载的 js 脚本有多个的时候,async是无顺序的加载,而defer是有顺序的加载,defer属性表示延迟执行引入的 JavaScript,这段 JavaScript 加载时 HTML 并未停止解析,因此,defer是不会阻塞 html 解析的,它是等Dom加载完后再去执行JavaScript代码的。(当 html 解析过程中,遇到defer属性,就会异步加载该 js 文件,不会中断HTML文档的解析,当整个 HTML 解析完成后,回头再来解析该 js 文件)
- 当有 defer 属性时,脚本的加载过程 和 文档加载 是 异步发生的,等到 文档解析 完脚本才开始执行。
- 当有 async 属性时,脚本的加载过程 和 文档加载 也是异步发生的,这里注意的是 脚本下载完成后,会停止 HTML 解析,先执行脚本,脚本解析完 后继续 HTML 解析。
- 同时有 async 和 defer 属性时,执行效果与 async 一致。
defer 属性-是否延迟执行脚本,直到页面加载为止;async 属性-脚本一旦可用,就异步执行。defer 属性并行加载 JavaScript 文件,会按照页面上的 script 标签顺序执行,而 async 并行加载,下载完成就立即执行,不会按照页面上的顺序执行。
4.说说你对闭包的了解
面试前端,当面试官问你,谈谈你对闭包的理解的时候,该怎么回答呢?
简单说就是定义在一个函数内部的函数,内部函数持有外部函数内的变量或参数的引用。内部函数依赖外部函数,外部函数参数和变量不会被垃圾回收机制回收,这些变量会始终存在于内存中。
好处可以读取函数内部的变量,可以避免全局变量的污染,坏处会增加内存的使用量,容易导致内存泄漏,解决方法就是退出函数前,将不适用的局部变量全部删除。在 JavaScript 中,函数即是闭包,只有函数才会产生作用域。
闭包特性,函数嵌套函数,在函数内部可以引用外部的参数和变量,参数和变量不会被垃圾回收机制回收。
由于在 js 中,变量的作用域属于函数作用域,在函数执行后,作用域就会被清理,内存也会被回收,但是由于闭包是建立在一个函数内部的 子函数,由于子函数可以访问上级作用域的原因,即使上级函数执行完,作用域也不会随之销毁。
在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
代码闭包表现形式:
// 作为函数参数传递
var a = 1;
function foo() {
var a = 2;
function mybj123() {
console.log(a);
}
mybj(mybj123);
}
function mybj(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 节点操作方法:
- 访问、获取节点
// 返回对拥有指定 id 的第一个对象进行访问 document.getElementById(id); // 返回带有指定名称的节点集合 document.getElementsByName(name); // 返回带有指定标签名的对象集合 document.getElementsByTagName(tagName); // 返回带有指定 class 名称的对象集合 document.getElementsByClassName(className);
- 创建节点/属性
createDocumentFragment() //创建一个 DOM 片段 document.createElement(eName); // 创建一个节点 document.createAttribute(attrName); // 对某个节点创建属性 document.createTextNode(text); // 创建文本节点
- 添加节点
document.insertBefore(newNode, referenceNode); // 在某个节点前插入节点 parentNode.appendChild(newNode); // 给某个节点添加子节点
- 复制节点
cloneNode(true | false); // 复制某个节点
- 删除节点
parentNode.removeChild(node); // 删除某个节点的子节点 node 是要删除的节点
- 属性操作
getAttribute(name) // 通过属性名称获取某个节点属性的值 setAttribute(name,value); // 通过某个节点属性的值 removeAttribute(name); // 删除某个属性
- 获取相邻的节点
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 类型,代表“空值”,代表一个空对象指针。
undefined: Undefined 类型,当一个声明了一个变量未初始化时,得到的是 undefined。
undefined 表示“缺少值”,此处应该有一个值,但是还没有定义。

__proto__是在查找链中用于解析方法的实际对象等,prototype使用以下命令__proto__创建对象时用于构建的对象new:
(new Foo).__proto__ === Foo.prototype; (new Foo).prototype === undefined;
prototype是Function对象的属性,它是由该功能构造的对象的原型。
__proto__是对象的内部属性,指向其原型。当前提供了Object.getPrototypeOf(o)方法,尽管事实上的标准__proto__更快。
可以使用instanceof通过将函数prototype与对象的__proto__链进行比较来找到关系,也可以通过更改来打破这些关系。
function Point(x, y) {
this.x = x;
this.y = y;
}
var myPoint = new Point();
// the following are all true
myPoint.__proto__ == Point.prototype myPoint.__proto__.__proto__ == Object.prototype myPoint instanceof Point;
myPoint instanceof Object;
86. 说说函数的三种定义方式
- 有参函数
- 无参函数
- 空函数
1、 函数式声明
2、 函数表达式(函数字面量)
3、 函数构造法,参数必须加引号
4、 对象直接量
5、 原型继承
6、 工厂模式
// 通过函数字面量
function da() {}
// 函数表达式
var da = function() {}
// 通过构造函数
var da = new Function();
87. JavaScript 里的全局对象是什么,如何调用
全局属性和函数可用于所有内建的 JavaScript 对象。默认的this指向window,默认全局对象的属性和方法不用在前面加window,可以直接调用。
顶层函数(全局函数):
decodeURI() 解码某个编码的 URI。 decodeURIComponent() 解码一个编码的 URI 组件。 encodeURI() 把字符串编码为 URI。 encodeURIComponent() 把字符串编码为 URI 组件。 escape() 对字符串进行编码。 eval() 计算 JavaScript 字符串,并把它作为脚本代码来执行。 getClass() 返回一个 JavaObject 的 JavaClass。 isFinite() 检查某个值是否为有穷大的数。 isNaN() 检查某个值是否是数字。 Number() 把对象的值转换为数字。 parseFloat() 解析一个字符串并返回一个浮点数。 parseInt() 解析一个字符串并返回一个整数。 String() 把对象的值转换为字符串。 unescape() 对由 escape() 编码的字符串进行解码。
顶层属性(全局属性)
Infinity 代表正的无穷大的数值。 java 代表 java.* 包层级的一个 JavaPackage。 NaN 指示某个值是不是数字值。 Packages 根 JavaPackage 对象。 undefined 指示未定义的值。
88. 说说几个常见的 JavaScript 内置对象,并指出它们的优点
常用的是Array对象、Date对象、正则表达式对象、string对象、Global对象
Concat():表示把几个数组合并成一个数组。 Join():返回字符串值,其中包含了连接到一起的数组的所有元素,元素由指定的分隔符分隔开来。 Pop():移除数组最后一个元素。 Shift():移除数组中第一个元素。 Slice(start, end):返回数组中的一段。 Push():往数组中新添加一个元素,返回最新长度。 Sort():对数组进行排序。 Reverse():反转数组的排序。 toLocaleString();返回当前系统时间。 ceil():向上取整。 floor():向下取整。 round():四舍五入。 random():取随机数。 get/setDate():返回或设置日期。 get/setFullYear():返回或设置年份,用四位数表示。 get/setYear():返回或设置年份。 get/setMonth():返回或设置月份。0 为一月 get/setHours():返回或设置小时,24 小时制 get/setMinutes():返回或设置分钟数。 get/setSeconds():返回或设置秒钟数。 get/setTime():返回或设置时间(毫秒为单位)。
89. 什么是 DOM,DOM 分为哪三种
DOM,文档对象模型(Document Object Model)。DOM 是 W3C(万维网联盟)的标准,DOM 定义了访问 HTML 和 XML 文档的标准。在 W3C 的标准中,DOM 是独于平台和语言的接口,它允许程序和脚本动态地访问和更新文档的内容、结构和样式。
分三种:
- 核心 DOM,针对任何结构化文档的标准模型
- xml Dom,针对 xml 文档的标准模型
- html Dom,针对 HTML 文档的标准模型
90. 说说 cookie 的兼容性,缺点等
兼容性:
- IE6 或更低版本最多 20 个 cookie
- IE7 和之后的版本最后可以有 50 个 cookie
- Firefox 最多 50 个 cookie
- chrome 和 Safari 没有做硬性限制
优缺点:
- 通过良好的编程,控制保存在 cookie 中的 session 对象的大小。
- 通过加密和安全传输技术(SSL),减少 cookie 被破解的可能性。
- 只在 cookie 中存放不敏感数据,即使被盗也不会有重大损失。
- 控制 cookie 的生命周期,使之不会永远有效,偷盗者很可能拿到一个过期的 cookie。
- 每个 domain 最多只能有 20 条 cookie,每个 cookie 长度不能超过 4KB,否则会被截掉。数量和长度的限制
- 如果 cookie 被人限制了,那人就可以取得所有的 session 信息。即使加密也于事无补,因为拦截者并不需要知道 cookie 的意义,他只要原样转发 cookie 就可以达到目的了。安全性问题。
- 为了防止重复提交表单,我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端,那么它起不到任何作用。有些状态不可能保存在客户端。
91. 说说栈和队列的区别
- 队列是先进先出的,栈是先进后出的
- 栈和队列都是线性表,都是限制了插入删除点的线性表,都是只能在线性表的端点插入和删除
92. 说说 cookie 和 session 的区别
- cookie 数据存放在客户的浏览器上,session 数据存放在服务器上
- cookie 不是很安全
- session 会在一定时间内保持在服务器上,当访问多时,会影响服务器的性能。
- 用户验证这种场合一般会用 session
- session 可以放在 文件、数据库、或内存中都可以
- Cookie 和 Session 都是会话技术
- Cookie 有大小限制以及浏览器在存 cookie 的个数也有限制,Session 是没有大小限制和服务器的内存大小有关