一、ES6
1.1 var、let、const之间的区别?
-
var
:在函数作用域或全局作用域内声明变量。var
变量存在变量提升(hoisting)的特性,即变量在声明之前可以被访问到,但其值为undefined
。var
变量可以被重复声明,并且可以在声明后重新赋值。 -
let
:在块级作用域(例如,if语句块、循环语句块、函数内部)内声明变量。与var
不同,let
变量不存在变量提升,而是在声明语句处创建。let
变量只在声明的块级作用域内有效,并且不能重复声明。同一个作用域内,可以对let
变量进行重新赋值。function example() { if (true) { let x = 10; console.log(x); // 10 } console.log(x); // Error: x is not defined }
-
const
:也用于声明块级作用域内的,但与let
不同的是,const
声明的是一个常量,其值在声明后不能被修改。const
声明时必须初始化,并且不能重新赋值。const pi = 3.14; pi = 3.14159; // Error: Assignment to constant variable. const person = { name: 'John', age: 30 }; person.age = 31; // 可以修改对象的属性 person = {}; // Error: Assignment to constant variable.
1.2 使用箭头函数应注意什么?
- 箭头函数没有自己的
this
值:箭头函数没有自己的this
绑定,它会捕获所在上下文的this
值。这意味着,在箭头函数内部使用this
时,它指向的是定义箭头函数时的上下文,而不是调用箭头函数的上下文。这与普通函数的行为不同,因此需要注意使用箭头函数时的上下文问题。 - 箭头函数没有自己的
arguments
对象:箭头函数也没有自己的arguments
对象,它会捕获所在上下文的arguments
对象。如果需要使用函数的参数列表,可以使用剩余参数(...args
)语法。 - 箭头函数不能用作构造函数:箭头函数没有
[[Construct]]
方法,因此不能使用new
关键字调用,也不能用作构造函数创建对象实例。 - 箭头函数没有
prototype
属性:箭头函数没有自己的prototype
属性,因此无法使用new
关键字创建的对象无法访问原型链上的方法和属性。 - 箭头函数的简写语法:当箭头函数只有一个参数时,可以省略参数周围的圆括号;当箭头函数只有一条返回语句时,可以省略花括号和
return
关键字。 - 注意
this
的指向:由于箭头函数没有自己的this
绑定,它会继承外部作用域的this
。这可能导致在某些情况下,this
的指向不符合预期。需要特别注意箭头函数的使用场景和上下文。
1.3 ES6的模板字符串有哪些新特性?
-
嵌入变量:使用
${}
语法可以方便地在模板字符串中嵌入变量。变量会被替换为其对应的值。 -
多行字符串:使用模板字符串可以直接表示多行字符串,而无需使用
\n
进行换行。 -
嵌套模板字符串:模板字符串可以嵌套在其他模板字符串中,以实现更复杂的字符串拼接。
const innerTemplate = `inner template`; const outerTemplate = `Outer template with ${innerTemplate}`; console.log(outerTemplate); // Outer template with inner template
1.4 Promise状态,构造函数是同步执行还是异步执行,那么 then 方法呢?
-
构造函数执行:Promise的构造函数是同步执行的。当创建一个Promise实例时,构造函数会立即执行,并且传入的执行器函数(executor function)也会立即执行。在执行器函数中,可以进行异步操作,但Promise的状态不会受到异步操作的影响。
const promise = new Promise((resolve, reject) => { console.log('Promise constructor execution'); // 异步操作 }); console.log('Promise created'); //在上述代码中,"Promise constructor execution"会首先打印,然后才会打印"Promise created"。
-
then方法执行:Promise的
then
方法是异步执行的。当Promise状态变为已完成或已拒绝时,会触发相应的then
回调函数的执行。但这些回调函数不会立即执行,而是会进入事件队列,等待当前执行栈为空时才会执行。promise.then(() => { console.log('Promise fulfilled'); }); console.log('After promise.then'); //在上述代码中,"After promise.then"会先打印,然后才会在事件队列中执行"Promise fulfilled"。
1.5 同步和异步指什么?
-
同步(Synchronous):同步任务按照其出现的顺序依次执行,每个任务必须等待上一个任务完成后才能开始执行。在同步任务执行期间,程序会阻塞,即程序会等待当前任务完成后再继续执行下一个任务。
-
异步(Asynchronous):异步任务不会阻塞程序的执行,而是在后台进行,允许程序在执行异步任务的同时继续执行后续的任务。异步任务通常会在后台进行一些耗时的操作,如网络请求、文件读写、定时器等。
console.log('Task 1'); setTimeout(() => { console.log('Task 2'); }, 2000); console.log('Task 3'); //在上述代码中,任务1会先执行,然后是任务3。而任务2是一个异步任务,通过setTimeout函数进行延迟执行,延迟时间为2秒。在等待2秒的期间,程序不会阻塞,会继续执行后续的任务。当延迟时间结束后,任务2会被执行。
1.6 forEach、for in、for of等常用指令
-
forEach
:forEach
方法用于遍历数组的每个元素,并对每个元素执行指定的回调函数。const arr = [1, 2, 3]; arr.forEach((item) => { console.log(item); });
2.
二、JSP
2.1 JSP 和 servlet 有什么区别?
- JSP(JavaServer Pages):
- 角色:JSP是用于创建动态Web页面的技术,充当了视图层的角色。它允许将Java代码嵌入到HTML页面中,以实现动态内容的生成和展示。
- 语法:JSP使用类似HTML的标签和注释,通过特殊的标签(
<% ... %>
,<%= ... %>
,<%! ... %>
等)插入Java代码。 - 部署:JSP文件在Web应用部署时会被转换为Java Servlet,并在服务器上执行。
- 动态内容:JSP用于处理动态内容生成,可以通过Java代码访问和操作后端数据,然后将结果呈现在HTML页面中。
- Servlet:
- 角色:Servlet是Java编写的服务器端程序,充当了控制器层的角色。它接收和处理来自客户端的请求,并生成相应的响应。
- 语法:Servlet是纯Java代码,没有HTML标签,通常通过继承
javax.servlet.http.HttpServlet
类来实现自定义Servlet。 - 部署:Servlet作为独立的Java类在Web应用部署时被编译并部署到服务器上,然后根据请求执行相应的逻辑。
- 请求处理:Servlet负责处理各种类型的HTTP请求(GET、POST等),并根据请求参数执行相应的业务逻辑,然后生成HTTP响应。
2.2 JSP 有哪些内置对象? 作用分别是什么?
request
(请求对象): 表示客户端发出的HTTP请求。通过该对象,可以获取来自客户端的参数、表单数据、HTTP头信息等。response
(响应对象): 表示将要发送回客户端的HTTP响应。通过该对象,可以设置响应的内容类型、状态码、重定向等。session
(会话对象): 表示用户会话信息,用于在多个请求之间共享数据。通过该对象,可以存储和检索与特定用户相关的数据。application
(应用程序对象): 表示整个Web应用程序的上下文信息。通过该对象,可以在应用程序范围内共享数据。out
(输出对象): 表示输出流,用于将文本发送回客户端。通过该对象,可以将内容直接输出到浏览器。page
(页面对象): 表示当前JSP页面本身。通过该对象,可以调用当前页面的方法和属性。config
(配置对象): 表示当前JSP页面的配置信息。通过该对象,可以获取JSP页面的初始化参数。pageContext
(页面上下文对象): 表示JSP页面的上下文信息。通过该对象,可以访问其他内置对象,如请求、会话和应用程序对象。exception
(异常对象): 表示在JSP页面中发生的异常信息。通过该对象,可以捕获和处理异常。
2.3 说一下 JSP 的 4 种作用域?
- page(页面作用域):
- 作用范围:仅在当前JSP页面中有效。
- 生命周期:与当前请求的响应周期相同。
- 存储方式:使用
<% ... %>
标签中的变量或通过<%! ... %>
标签中的声明语句创建的变量。 - 访问方式:在当前JSP页面的任何地方都可以直接访问。
- request(请求作用域):
- 作用范围:在同一次请求中的所有资源(JSP、Servlet)之间共享。
- 生命周期:从请求开始到响应结束。
- 存储方式:通过
request
对象的setAttribute
方法设置的属性。 - 访问方式:在当前请求的所有资源中都可以通过
request
对象获取。
- session(会话作用域):
- 作用范围:在同一用户的多次请求之间共享。
- 生命周期:从会话开始到会话结束(用户关闭浏览器或会话超时)。
- 存储方式:通过
session
对象的setAttribute
方法设置的属性。 - 访问方式:在同一用户的多个请求中都可以通过
session
对象获取。
- application(应用程序作用域):
- 作用范围:在整个Web应用程序中共享。
- 生命周期:从Web应用启动到Web应用关闭。
- 存储方式:通过
application
对象的setAttribute
方法设置的属性。 - 访问方式:在整个Web应用程序中的任何地方都可以通过
application
对象获取。
2.4 session 和 cookie 有什么区别?
- 存储位置:
- Cookie:Cookie是存储在客户端(通常是浏览器)中的小型文本文件。每次请求发送到服务器时,Cookie会被自动附加到请求头中。
- Session:Session是存储在服务器端的用户数据结构,通常以键值对的形式存储。服务器在每个会话期间为每个用户创建一个唯一的Session对象,并将其与用户关联。
- 安全性:
- Cookie:Cookie存储在客户端,可以设置过期时间和域名。Cookie可以被客户端修改、删除或禁用,因此不太安全。为了增加安全性,可以对Cookie进行加密或使用安全标志(Secure Flag)和仅限HTTP标志(HTTP Only Flag)。
- Session:Session存储在服务器端,只有Session ID 在Cookie或URL参数中传输给客户端。实际的会话数据在服务器上进行存储,因此相对更安全。
- 数据传输:
- Cookie:Cookie会在每个HTTP请求的请求头中自动发送到服务器,无需手动处理。由于Cookie会随着每个请求被发送到服务器,因此对于每个请求,都会增加一些额外的数据传输量。
- Session:Session ID 通常通过Cookie传输到服务器,但也可以通过URL参数传输。服务器使用Session ID 来查找和恢复与特定用户相关的会话数据。Session 数据不会在每个请求中传输,只有Session ID 会传输,因此相对节省数据传输量。
- 存储容量:
- Cookie:Cookie的存储容量通常较小,每个Cookie的大小限制为4KB。因此,Cookie通常用于存储较小的数据,如用户偏好设置或身份验证凭据。
- Session:Session的存储容量可以更大,取决于服务器的配置和可用资源。因此,Session通常用于存储较大的数据,如购物车信息或用户会话状态。
2.5 session 的工作原理?
- 客户端发起请求:当用户访问一个使用Session的Web应用程序时,客户端(通常是浏览器)会发送一个HTTP请求到服务器。
- 服务器创建Session:服务器接收到请求后,会为该用户创建一个唯一的Session对象。通常,服务器会生成一个唯一的Session ID,并将其与用户关联。
- Session ID 的传递:服务器会将Session ID 发送回客户端,通常通过设置一个名为"JSESSIONID"的Cookie。该Cookie包含了Session ID。
- 客户端发送Session ID:在随后的请求中,客户端会自动将包含Session ID 的Cookie附加到请求头中,并发送给服务器。这使得服务器能够识别请求来源的用户。
- 服务器检索Session:服务器接收到请求后,会根据请求中的Session ID 查找对应的Session对象。通过Session ID,服务器能够从存储在服务器端的Session数据结构中找到与该用户关联的会话数据。
- 会话数据处理:服务器可以根据需要从Session对象中读取和修改会话数据。这使得服务器能够跟踪和管理用户的状态,存储用户相关的信息。
- 响应发送到客户端:服务器处理完请求后,将生成的响应发送回客户端。响应中可能包含新的或更新的Session ID。
- 重复步骤 4-7:在用户继续与Web应用程序交互的过程中,重复步骤4至7,以保持会话的持续状态。每次请求中都会包含Session ID,服务器通过Session ID 来关联请求与相应的Session对象。
- 会话过期和销毁:会话可以在一定的时间内保持活动状态,这通常由服务器的配置和应用程序的需求决定。当会话过期或用户主动注销时,服务器会销毁Session对象,并释放与该会话相关的资源。
三、jQuery
3.1 有哪些选择器?
-
元素选择器:通过元素名称选取元素。例如,
$('div')
选取所有<div>
元素。 -
类选择器:通过类名选取元素。例如,
$('.class-name')
选取具有特定类名的元素。 -
ID选择器:通过ID选取元素。例如,
$('#element-id')
选取具有特定ID的元素。 -
属性选择器:通过元素的属性选取元素。例如,
$('[attribute-name="value"]')
选取具有特定属性和值的元素。 -
后代选择器:选取特定元素的后代元素。例如,
$('parent-element descendant-element')
选取指定父元素内的后代元素。// 选取所有 <p> 元素内的 <span> 元素 $('p span')
-
子元素选择器:选取特定元素的直接子元素。例如,
$('parent-element > child-element')
选取指定父元素的直接子元素。// 选取所有 <ul> 元素的直接子元素 <li> 元素 $('ul > li')
-
相邻元素选择器:选取紧邻在另一个元素之后的元素。例如,
$('target-element + adjacent-element')
选取紧邻在目标元素后面的相邻元素。// 选取紧邻在 <h2> 元素之后的下一个 <p> 元素 $('h2 + p')
-
兄弟元素选择器:选取与另一个元素拥有相同父元素的元素。例如,
$('target-element ~ sibling-element')
选取与目标元素具有相同父元素的兄弟元素。// 选取与 <h2> 元素具有相同父元素的兄弟元素 <p> 元素 $('h2 ~ p')
-
过滤选择器:通过不同的条件进行元素过滤和筛选。例如,
:first
选取第一个元素,:last
选取最后一个元素,:even
选取偶数位置的元素,:odd
选取奇数位置的元素等。// 选取第一个 <li> 元素 $('li:first')
3.2 ID 选择器和 class 选择器有何不同?
- 选择器语法:
- ID选择器:以
#
字符开头,后跟ID名称。例如,$('#myId')
选取具有特定ID的元素。 - 类选择器:以
.
字符开头,后跟类名。例如,$('.myClass')
选取具有特定类名的元素。
- ID选择器:以
- 元素匹配:
- ID选择器:ID在HTML文档中应该是唯一的,因此ID选择器在整个文档中只匹配一个元素,即匹配具有指定ID的单个元素。
- 类选择器:类可以在HTML文档中多次使用,因此类选择器可以匹配多个元素,即匹配具有指定类名的所有元素。
- 选择器优先级:
- ID选择器:ID具有更高的优先级,当使用ID选择器时,它会覆盖其他选择器,即如果一个元素同时匹配ID选择器和类选择器,ID选择器会优先匹配。
- 类选择器:类选择器的优先级相对较低,如果一个元素同时匹配多个选择器,其他选择器可能会覆盖类选择器的匹配。
- 选择器用途:
- ID选择器:适合用于选取具有唯一标识的特定元素,例如页面上的特定表单元素、特定标题等。
- 类选择器:适合用于选取具有相似样式或功能的一组元素,例如一组按钮、一组相似的导航菜单等。
3.3 如何使用 jQuery 隐藏一个图片?
-
用css隐藏图片
// 通过设置CSS属性"display"为"none"来隐藏图片 $('#imageId').css('display', 'none');
-
用hide方法隐藏
// 使用hide()方法隐藏图片 $('#imageId').hide();
3.4 $(document).ready0 是个什么函数?为什么要用它?
函数$(document).ready()
是jQuery中的一个特殊函数,用于在文档加载完毕后执行特定的代码。正 确的写法是$(document).ready(function() { ... })
,其中函数体中可以包含需要在文档加载完毕后执行的JavaScript代码。
为什么要使用$(document).ready()
函数呢?
在HTML文档加载时,浏览器会按照从上到下的顺序逐行解析和执行代码。如果在执行JavaScript代码时,尝试访问尚未加载的HTML元素,可能会导致代码执行失败或出现错误。这种情况尤其在代码位于<head>
标签中时常见,因为此时HTML文档的主体内容尚未完全加载。
为了解决这个问题,jQuery提供了$(document).ready()
函数,它的作用是等待整个HTML文档完全加载后再执行函数内的代码。这样可以确保代码执行时,所有的HTML元素已经加载完毕,可以安全地进行元素选择、操作和事件绑定等操作。
使用$(document).ready()
函数的好处是可以确保代码执行的时机,而不必依赖于代码在HTML文档中的位置或加载速度。无论代码放在<head>
标签中还是放在<body>
标签中的任何位置,只要将其放在$(document).ready()
函数中,都能保证代码在文档加载完成后执行。
3.5 jQuery 里的 each()是什么函数? 你是如何使用它的?
在jQuery中,each()
函数是用于迭代遍历一个集合(如数组或对象)的方法。它允许你对集合中的每个元素执行相同的操作或回调函数。
正确的写法是$.each(collection, callback)
,其中collection
是要迭代的集合,可以是数组、类数组对象或普通对象,而callback
是每个元素的回调函数。
-
遍历数组:
var arr = [1, 2, 3, 4, 5]; $.each(arr, function(index, value) { console.log('Index:', index, 'Value:', value); });
-
遍历对象:
var obj = { name: 'John', age: 25, city: 'New York' }; $.each(obj, function(key, value) { console.log('Key:', key, 'Value:', value); });
3.6 如何将一个 HTML 元素添加到 DOM 树中的?
-
append()
:将指定的元素添加为目标元素的子元素的最后一个子节点。// 将一个 <div> 元素添加为 <body> 元素的最后一个子节点 $('<div>New div element</div>').append('body');
-
prepend()
:将指定的元素添加为目标元素的子元素的第一个子节点。// 将一个 <div> 元素添加为 <body> 元素的第一个子节点 $('<div>New div element</div>').prepend('body');
-
appendTo()
:将指定的元素添加到目标元素作为子元素的最后一个子节点。// 将一个 <div> 元素添加到 <body> 元素中作为最后一个子节点 $('<div>New div element</div>').appendTo('body');
-
prependTo()
:将指定的元素添加到目标元素作为子元素的第一个子节点。// 将一个 <div> 元素添加到 <body> 元素中作为第一个子节点 $('<div>New div element</div>').prependTo('body');
3.7 jQuery.get0和 jQuery.ajax0 方法之间的区别是什么?
jQuery.get()
方法:
-
语法结构:
jQuery.get(url [, data] [, success] [, dataType])
。 -
功能:发送一个GET请求到指定的URL,并可选择性地传递数据、处理成功回调和指定数据类型。
// 发送GET请求,获取数据并处理成功回调 $.get('example.com/data', function(response) { // 处理响应数据 });
jQuery.ajax()
方法:
-
语法结构:
jQuery.ajax(settings)
。 -
功能:发送一个AJAX请求,并提供更多的灵活性和定制选项。
// 发送AJAX请求,通过设置选项定制请求 $.ajax({ url: 'example.com/data', method: 'GET', data: { key: 'value' }, success: function(response) { // 处理响应数据 }, dataType: 'json' });
主要区别如下:
- 简洁性:
jQuery.get()
方法是jQuery.ajax()
方法的一种简化形式,用于发送GET请求,语法更为简单,不需要设置很多选项,适合简单的GET请求。 - 定制性:
jQuery.ajax()
方法提供了更多的选项和灵活性,可以通过设置settings
对象来定制请求的各种细节,包括请求类型、URL、数据、请求头、成功回调、错误回调等。 - 功能扩展:
jQuery.ajax()
方法支持除GET请求外的其他请求类型,如POST、PUT、DELETE等,可以发送不同类型的请求。 - 复杂性:由于
jQuery.ajax()
方法提供了更多的选项,因此在处理复杂的AJAX请求时更为适用。对于简单的GET请求,可以使用jQuery.get()
方法来简化代码。
3.8 哪种方式更高效:document.getElementbyId(“myId”) 还是 $(“#myId”)?
在性能方面,document.getElementById("myId")
比$("#myId")
更高效。
document.getElementById("myId")
是原生JavaScript方法,用于获取具有特定ID的元素。它直接通过浏览器的原生实现来查找元素,速度较快。
而$("#myId")
是jQuery的选择器,它基于CSS选择器的语法,并通过jQuery库来执行选择和操作。相比于原生方法,它需要更多的处理和额外的函数调用,因此比较起来会稍微慢一些。
选项,因此在处理复杂的AJAX请求时更为适用。对于简单的GET请求,可以使用jQuery.get()
方法来简化代码。
3.8 哪种方式更高效:document.getElementbyId(“myId”) 还是 $(“#myId”)?
在性能方面,document.getElementById("myId")
比$("#myId")
更高效。
document.getElementById("myId")
是原生JavaScript方法,用于获取具有特定ID的元素。它直接通过浏览器的原生实现来查找元素,速度较快。
而$("#myId")
是jQuery的选择器,它基于CSS选择器的语法,并通过jQuery库来执行选择和操作。相比于原生方法,它需要更多的处理和额外的函数调用,因此比较起来会稍微慢一些。