2023.06.06 - 2023.06.09 更新前端面试问题总结(18道题)
获取更多面试相关问题可以访问
github 地址: https://github.com/pro-collection/interview-question/issues
gitee 地址: https://gitee.com/yanleweb/interview-question/issues
目录:
- 初级开发者相关问题【共计 6 道题】
- 424.src和href的区别是什么?【热度: 1,601】【浏览器】
- 427. 标签有何作用?【浏览器】
- 431.判断数组的方式有哪些【热度: 509】【JavaScript】【出题公司: 网易】
- 433.js 函数有默认值的时候, 如果传递的参数是 undefined 那么会被默认值赋值吗?【JavaScript】
- 434.Object.is() 与比较操作符 “===”、“==” 有什么区别【热度: 1,425】【JavaScript】【出题公司: 京东】
- 440.use strict是什么? 它有什么用?【热度: 758】【JavaScript】【出题公司: PDD】
- 中级开发者相关问题【共计 11 道题】
- 425.iframe 标签有那些优点和缺点?【热度: 411】【浏览器】
- 426.HTML5 drag(拖拽) API 了解多少【热度: 324】【浏览器】
- 429.html 中前缀为 data- 开头的元素属性是什么?【热度:903】【web应用场景】【出题公司: Shopee】
- 432.typeof null 的结果是什么,为什么?【JavaScript】
- 435.什么是伪数组、什么是类数组【热度: 1,510】【JavaScript】【出题公司: 美团】
- 437.类数组转换成数组的方法有哪些【热度: 1,094】【JavaScript】【出题公司: 百度】
- 438.为什么函数的 arguments 参数是类数组而不是数组?如何遍历类数组?【热度: 669】【JavaScript】【出题公司: 腾讯】
- 439.escape、encodeURI、encodeURIComponent 区别【热度: 367】【JavaScript】【出题公司: 阿里巴巴】
- 441.解释性语言和编译型语言的区别【热度: 858】【JavaScript】【出题公司: 快手】
- 442.ajax、axios、fetch的区别【热度: 855】【网络】【出题公司: Shopee】
- 443.深度遍历广度遍历的区别?【热度: 867】【JavaScript】【出题公司: 快手】
- 高级开发者相关问题【共计 1 道题】
- 428.web 应用中如何对静态资源加载失败的场景做降级处理【热度: 1,093】【web应用场景】
初级开发者相关问题【共计 6 道题】
424.src和href的区别是什么?【热度: 1,601】【浏览器】
关键词:src和href的区别
src 和 href 是两个在 HTML 中常用的属性,它们具有不同的作用和用途,主要区别如下:
- 用途:
- src 属性用于指定嵌入资源的 URL,如图片、音频、视频等。
- href 属性用于创建超链接,定义链接到的目标 URL 地址。
- 资源加载:
- src 属性用于指定需要加载的资源,浏览器会根据 src 属性的值去请求资源,并将其嵌入到文档中。例如,<img>、<script>、<iframe> 等标签使用 src 属性加载外部资源。
- href 属性用于指定链接的目标 URL,通过点击链接,浏览器会导航到指定的 URL 地址。例如,<a>、<link>、<link rel="stylesheet"> 等标签使用 href 属性创建超链接或引入外部样式表。
- 标签使用:
- src 属性主要用于嵌入资源的标签,如 <img>、<script>、<audio>、<video> 等。
- href 属性主要用于超链接标签,如 <a>,以及用于引入外部资源的标签,如 <link>。
- 加载顺序:
- src 属性的资源会按照标签在文档中的顺序依次加载,其中某些标签可能会阻塞页面的渲染,比如 <script> 标签会阻塞页面的解析和渲染。
- href 属性的资源加载不会阻塞页面的解析和渲染,通常用于引入外部样式表或字体等。
总结:
- src 属性用于嵌入资源的标签,指定需要加载的资源。
- href 属性用于创建超链接的标签,指定链接的目标 URL 或引入外部资源的 URL。
需要根据具体的使用场景和标签来选择使用 src 还是 href 属性。
427. 标签有何作用?【浏览器】
<!DOCTYPE html> 是 HTML5 的文档类型声明(Document Type Declaration),它的作用是告诉浏览器当前文档使用的是 HTML5 规范。
具体来说,<!DOCTYPE html> 的作用有以下几个方面:
- 指定文档类型:文档类型声明告诉浏览器当前文档所使用的 HTML 版本,即 HTML5。这样浏览器就可以按照 HTML5 的规范来解析和渲染文档。
- 规范浏览器行为:文档类型声明还可以影响浏览器的行为。HTML5 的文档类型声明告诉浏览器以标准模式(standards mode)来解析文档,以确保一致的行为和渲染结果。
- 提供更好的兼容性:使用 <!DOCTYPE html> 可以确保文档在不同浏览器中具有一致的处理方式。不同的浏览器对不同版本的 HTML 有不同的处理方式,而使用 HTML5 的文档类型声明可以使浏览器以最新的标准模式来解析文档,提供更好的兼容性和一致性。
总结来说,<!DOCTYPE html> 是 HTML5 的文档类型声明,它告诉浏览器当前文档使用的是 HTML5 规范,以规范浏览器的行为,并提供更好的兼容性和一致性。在编写 HTML5 文档时,通常将 <!DOCTYPE html> 放置在文档的开头作为文档类型声明。
431.判断数组的方式有哪些【热度: 509】【JavaScript】【出题公司: 网易】
关键词:js判断数组方法
在 JavaScript 中,判断一个值是否为数组有多种方式,以下是几种常见的方法:
- Array.isArray(): 使用 Array.isArray() 方法可以判断一个值是否为数组。它是 ES5 中新增的方法,返回一个布尔值。
const arr = [1, 2, 3];
console.log(Array.isArray(arr)); // true
const obj = { a: 1, b: 2 };
console.log(Array.isArray(obj)); // false
- instanceof 操作符:可以使用 instanceof 操作符检查一个对象是否是特定类的实例。对于数组,可以使用 instanceof Array 判断。
const arr = [1, 2, 3];
console.log(arr instanceof Array); // true
const obj = { a: 1, b: 2 };
console.log(obj instanceof Array); // false
- Array.prototype.isArray():可以通过 Array.prototype.isArray.call() 方法来判断一个值是否为数组。这种方式在某些特定情况下使用较多。
const arr = [1, 2, 3];
console.log(Array.prototype.isArray.call(arr)); // true
const obj = { a: 1, b: 2 };
console.log(Array.prototype.isArray.call(obj)); // false
- Object.prototype.toString():可以使用 Object.prototype.toString.call() 方法来获取一个值的类型信息,进而判断是否为数组。返回的结果是一个包含类型信息的字符串,例如 "[object Array]"。
const arr = [1, 2, 3];
console.log(Object.prototype.toString.call(arr) === "[object Array]"); // true
const obj = { a: 1, b: 2 };
console.log(Object.prototype.toString.call(obj) === "[object Array]"); // false
这些方法各有特点,根据实际需求选择合适的方法进行判断。通常推荐使用 Array.isArray() 方法来判断一个值是否为数组,因为它是专门用于判断数组的标准方法,并且在大多数现代浏览器中得到广泛支持。
433.js 函数有默认值的时候, 如果传递的参数是 undefined 那么会被默认值赋值吗?【JavaScript】
是的,如果函数在调用时某个参数被传递为 undefined,那么它会被默认值赋值。
当为函数的参数设置默认值时,只有当参数的值为 undefined 时才会生效。如果传递的参数为 null、空字符串 '' 或者未提供参数,则默认值不会被应用。
以下是一个示例:
function greet(name = 'Guest') {
console.log(`Hello, ${name}!`);
}
greet('John'); // 输出: Hello, John!
greet(undefined); // 输出: Hello, Guest!
greet(); // 输出: Hello, Guest!
在上面的例子中,当参数 name 被传递为 undefined 或者未提供时,它会被默认值 'Guest' 赋值,从而在函数内部输出 'Hello, Guest!'。
如果传递的参数为 null,默认值不会被应用。当函数的参数被显式传递为 null 时,它将被视为有效的值,不会触发默认值的赋值。
以下是一个示例:
function greet(name = 'Guest') {
console.log(`Hello, ${name}!`);
}
greet(null); // 输出: Hello, null!
在上面的例子中,参数 name 被显式传递为 null,因此默认值 'Guest' 不会被应用,而是使用了传递的 null 值。所以输出结果为 'Hello, null!'。
434.Object.is() 与比较操作符 “===”、“==” 有什么区别【热度: 1,425】【JavaScript】【出题公司: 京东】
关键词:Object.is()、js 相等比较
Object.is() 方法和比较操作符 "==="、"==" 用于比较两个值的相等性,但它们在比较方式和行为上有一些区别。
- Object.is() 方法是严格相等比较,而 "===" 操作符也是严格相等比较,但 "==" 操作符是相等比较。
- 严格相等比较(===)要求比较的两个值在类型和值上完全相同才会返回 true。
- 相等比较(==)会进行类型转换,将两个值转换为相同类型后再进行比较。
- Object.is() 方法对于一些特殊的值比较更准确:
- 对于 NaN 和 NaN 的比较,Object.is(NaN, NaN) 返回 true,而 NaN === NaN 返回 false。
- 对于 +0 和 -0 的比较,Object.is(+0, -0) 返回 false,而 +0 === -0 返回 true。
下面是一些示例:
console.log(Object.is(1, 1)); // true
console.log(Object.is('foo', 'foo')); // true
console.log(Object.is(true, true)); // true
console.log(Object.is(null, null)); // true
console.log(Object.is(undefined, undefined)); // true
console.log(Object.is(NaN, NaN)); // true
console.log(NaN === NaN); // false
console.log(Object.is(+0, -0)); // false
console.log(+0 === -0); // true
console.log(Object.is({}, {})); // false
console.log({} === {}); // false
Object.is() 方法更精确地比较两个值的相等性,尤其是在处理一些特殊的值时,而 "===" 操作符和 "==" 操作符则具有不同的类型转换行为和比较规则。
440.use strict是什么? 它有什么用?【热度: 758】【JavaScript】【出题公司: PDD】
关键词:JS 编译指示、JS 严格模式
"use strict" 是 JavaScript 中的一个编译指示(directive),用于启用严格模式(strict mode)。
严格模式是 JavaScript 的一种执行模式,它增强了代码的健壮性、可维护性和安全性,并减少了一些常见的错误。启用严格模式后,JavaScript 引擎会执行更严格的语法检查,提供更好的错误检测和提示。
使用 "use strict" 有以下几个特点和用途:
- 严格模式禁止使用一些不安全或不推荐的语法和行为,例如使用未声明的变量、删除变量或函数、对只读属性赋值等。它会抛出更多的错误,帮助开发者发现并修复潜在的问题。
- 严格模式禁止使用一些不严谨的语法解析和错误容忍行为,例如不允许在全局作用域中定义变量时省略 var 关键字。
- 严格模式对函数的处理更加严格,要求函数内部的 this 值为 undefined,而非在非严格模式下默认指向全局对象。
- 严格模式禁止使用一些具有歧义性的特性,例如禁止使用八进制字面量、重复的函数参数名。
使用严格模式可以提高代码的质量和可靠性,并避免一些常见的错误。为了启用严格模式,只需在 JavaScript 文件或函数的顶部添加 "use strict" 即可。严格模式默认不启用,需要显式地指定。例如:
"use strict";
// 严格模式下的代码
需要注意的是,严格模式不兼容一些旧版本的 JavaScript 代码,可能会导致一些旧有的代码产生错误。因此,在使用严格模式之前,需要确保代码中不会出现与严格模式不兼容的语法和行为。
中级开发者相关问题【共计 11 道题】
425.iframe 标签有那些优点和缺点?【热度: 411】【浏览器】
关键词:iframe优点、iframe缺点、iframe应用
<iframe> 标签是 HTML 中的内嵌框架元素,它具有一些优点和缺点,如下所示:
优点:
- 分隔内容:<iframe> 允许将不同的 HTML 文档嵌入到当前文档中,实现内容的分隔和独立。每个 <iframe> 都有自己的文档上下文,可以在不同的 <iframe> 中加载和操作不同的内容。
- 并行加载:每个 <iframe> 是独立的,可以并行加载,这样可以提高页面加载速度和性能。
- 代码隔离:<iframe> 中的内容与主页面的内容相互隔离,可以避免一些 CSS 样式或 JavaScript 代码的冲突,提高代码的可维护性和可靠性。
- 安全性:由于 <iframe> 是独立的文档上下文,可以用于实现一些安全隔离的措施,例如加载来自不可信源的内容,可以将其放置在 <iframe> 中,以保护主页面的安全性。
缺点:
- SEO 不友好:搜索引擎对 <iframe> 中的内容索引能力较弱,可能影响页面的搜索引擎优化。
- 高度难以控制:<iframe> 的高度默认会根据内容的高度自动调整,如果内容高度动态变化,可能导致页面布局出现问题。
- 页面性能:每个 <iframe> 都会增加页面的请求量和渲染成本,特别是当页面中存在大量的 <iframe> 时,会影响页面的性能。
- 安全性风险:如果在 <iframe> 中加载来自不受信任的源的内容,可能存在安全风险,例如跨域脚本攻击(XSS)。
应用场景
<iframe> 元素在以下场景中常被使用:
- 嵌入其他网页:通过 <iframe> 可以将其他网页嵌入到当前页面中。这在一些需要展示其他网页内容的情况下非常有用,例如嵌入地图、视频、社交媒体小部件等。
- 广告展示:广告平台通常会提供 <iframe> 代码片段,用于在页面上嵌入广告内容。这样可以实现广告与页面的分离,保持页面结构简洁,并且提供安全隔离,防止广告脚本对页面产生负面影响。
- 安全隔离:通过将不受信任的内容放置在 <iframe> 中,可以实现安全隔离,防止不受信任的内容对主页面进行攻击。这在加载来自第三方或不可信任源的内容时非常有用。
- 无刷新文件上传:在需要实现文件上传的场景中,可以使用 <iframe> 创建一个隐藏的表单,并通过该表单实现文件上传操作。由于 <iframe> 的独立上下文,可以实现无刷新上传,同时避免页面刷新带来的不良用户体验。
- 跨域通信:通过使用 <iframe> 和窗口通信 API(如 postMessage),可以实现跨域的安全通信。这在需要在不同域之间进行数据交互或嵌入第三方内容时非常有用。
请注意,尽管 <iframe> 在上述场景中有用,但也要注意潜在的性能问题、安全风险以及对 SEO 的影响。因此,在使用 <iframe> 时需要谨慎权衡利弊,并根据具体需求选择适当的解决方案。
426.HTML5 drag(拖拽) API 了解多少【热度: 324】【浏览器】
关键词:drag 拖拽 api、拖拽 api
api
HTML5 Drag API 提供了一组用于实现拖放操作的接口和事件。以下是 HTML5 Drag API 中常用的一些接口和事件:
- draggable 属性:将元素设置为可拖动。可以通过设置元素的 draggable 属性为 true 或 false 来控制元素是否可以被拖动。
- ondragstart 事件:拖动操作开始时触发的事件,通常在此事件中设置被拖动的数据类型和数据内容。
- ondrag 事件:拖动过程中持续触发的事件,可以在此事件中进行一些自定义的操作,如实时更新拖动元素的位置。
- ondragend 事件:拖动操作结束时触发的事件,通常在此事件中执行一些清理操作,如移除拖动时设置的样式。
- ondragenter 事件:拖动元素进入目标元素时触发的事件,可以在此事件中进行一些针对目标元素的操作,如改变目标元素的样式。
- ondragleave 事件:拖动元素离开目标元素时触发的事件,可以在此事件中进行一些清除或还原目标元素的操作。
- ondragover 事件:在目标元素上拖动时持续触发的事件,可以在此事件中阻止默认的拖放行为或执行一些自定义操作。
- ondrop 事件:在目标元素上释放拖动元素时触发的事件,通常在此事件中处理拖放操作,如获取拖放数据并执行相应的操作。
以上是 HTML5 Drag API 中常用的接口和事件。通过使用这些接口和事件,可以实现灵活的拖拽功能并与其他元素进行交互。需要注意的是,拖放操作的实现还涉及到一些其他的 DOM 操作和事件处理。
应用举例
下面是一个使用 HTML5 Drag API 的简单示例,展示了如何实现拖拽功能:
<!DOCTYPE html>
<html>
<head>
<style>
.draggable {
width: 100px;
height: 100px;
background-color: red;
cursor: move;
}
.droppable {
width: 200px;
height: 200px;
background-color: blue;
}
</style>
</head>
<body>
<div class="draggable" draggable="true">Drag Me</div>
<div class="droppable">Drop Here</div>
<script>
const draggableElement = document.querySelector('.draggable');
const droppableElement = document.querySelector('.droppable');
draggableElement.addEventListener('dragstart', (event) => {
// 设置拖动数据
event.dataTransfer.setData('text/plain', 'Draggable Element');
});
droppableElement.addEventListener('dragover', (event) => {
// 阻止默认的拖放行为
event.preventDefault();
});
droppableElement.addEventListener('drop', (event) => {
// 获取拖放数据
const data = event.dataTransfer.getData('text/plain');
// 在目标元素上执行操作
droppableElement.textContent = data;
});
</script>
</body>
</html>
在上面的示例中,.draggable 类的元素被设置为可拖动(draggable="true"),当开始拖动时,触发了 dragstart 事件,并设置了拖动数据。
.droppable 类的元素作为目标元素,它监听了 dragover 事件以阻止默认的拖放行为,并在 drop 事件中获取拖放数据并执行相应的操作。
通过以上代码,你可以在浏览器中看到一个红色的可拖动元素和一个蓝色的目标元素。你可以尝试将可拖动元素拖放到目标元素上,拖放完成后,目标元素的内容将会被设置为拖放的数据。
429.html 中前缀为 data- 开头的元素属性是什么?【热度:903】【web应用场景】【出题公司: Shopee】
HTML 中前缀为 data- 开头的元素属性被称为自定义数据属性(Custom Data Attributes)或者数据属性(Data Attributes)。
这些属性的命名以 data- 开头,后面可以跟上任意自定义的名称。这样的属性可以用来存储与元素相关的自定义数据,以便在 JavaScript 或 CSS 中进行访问和操作。
自定义数据属性的命名应该遵循以下规则:
- 属性名必须以 data- 开头。
- 属性名可以包含任意字母、数字、连字符(-)、下划线(_)和小数点(.)。
- 属性名不应该包含大写字母,因为 HTML 属性名是不区分大小写的。
通过自定义数据属性,我们可以在 HTML 元素中嵌入自定义的数据,然后在 JavaScript 中使用 getAttribute() 方法或直接通过元素对象的 dataset 属性来访问这些数据。
例如,在 HTML 中定义了一个自定义数据属性 data-color="red":
<div id="myDiv" data-color="red"></div>
在 JavaScript 中可以通过以下方式获取该自定义数据属性的值:
const myDiv = document.getElementById('myDiv');
const color = myDiv.getAttribute('data-color'); // 获取属性值为 "red"
const dataset = myDiv.dataset; // 获取包含所有自定义数据属性的对象 { color: "red" }
const colorValue = dataset.color; // 获取属性值为 "red"
通过自定义数据属性,我们可以将相关的数据绑定到 HTML 元素上,方便在 JavaScript 中进行处理和操作,增强了 HTML 和 JavaScript 之间的交互性。
432.typeof null 的结果是什么,为什么?【JavaScript】
typeof null 的结果是 "object"。
这是 JavaScript 中的一个历史遗留问题。在 JavaScript 最初的实现中,将 JavaScript 的值分为了几种类型,其中 null 被当作一个空对象指针。为了与其他对象类型区分开,typeof null 返回了 "object"。
实际上,null 是一个表示空值的特殊值,它不是对象,也不是任何对象的实例。虽然 typeof null 返回了 "object",但这并不表示 null 是对象的一种类型。
由于这个历史遗留问题,判断一个值是否为 null 通常需要使用 value === null 进行比较,而不是依赖 typeof 运算符的结果。
435.什么是伪数组、什么是类数组【热度: 1,510】【JavaScript】【出题公司: 美团】
关键词:伪数组、类数组
伪数组(Array-like)和类数组(Array-like Object)都是描述一种类似数组的对象结构,它们在外观和行为上类似于数组,但实际上不是真正的数组。
伪数组(Array-like):
- 伪数组是指具有类似数组的结构,但不具备数组的方法和属性的对象。
- 伪数组对象通常拥有一个 length 属性,用于表示其元素的个数。
- 伪数组对象可以通过索引访问元素,类似于数组的下标访问。
- 伪数组对象不具备数组的方法,如 push、pop、slice 等。
类数组(Array-like Object):
- 类数组是指具有类似数组的结构,但不是由 Array 构造函数创建的对象。
- 类数组对象通常拥有一个 length 属性,用于表示其元素的个数。
- 类数组对象可以通过索引访问元素,类似于数组的下标访问。
- 类数组对象不具备数组的方法,如 push、pop、slice 等。
示例:
// 伪数组
const arrayLike = { 0: 'apple', 1: 'banana', length: 2 };
console.log(arrayLike[0]); // 'apple'
console.log(arrayLike.length); // 2
console.log(arrayLike.push); // undefined
// 类数组
const arrayLikeObject = document.querySelectorAll('div');
console.log(arrayLikeObject[0]); // DOM元素
console.log(arrayLikeObject.length); // 元素数量
console.log(arrayLikeObject.push); // undefined
需要注意的是,伪数组和类数组虽然具有类似数组的结构,但它们没有继承自 Array 的方法和属性,因此无法直接使用数组的方法。如果需要使用数组的方法,可以将伪数组或类数组对象转换为真正的数组,例如通过 Array.from() 、Array.prototype.slice.call() 或展开运算符 ... 等方法进行转换。
437.类数组转换成数组的方法有哪些【热度: 1,094】【JavaScript】【出题公司: 百度】
关键词:类数组对象转换为真正的数组
有几种常见的方法可以将类数组对象转换为真正的数组:
- Array.from():使用 Array.from() 方法可以将可迭代对象或类数组对象转换为数组。
const arrayLike = { 0: 'apple', 1: 'banana', length: 2 };
const array = Array.from(arrayLike);
console.log(array); // ['apple', 'banana']
- Array.prototype.slice.call():通过调用 Array.prototype.slice() 方法,并将类数组对象作为参数传入,可以将其转换为数组。
const arrayLike = { 0: 'apple', 1: 'banana', length: 2 };
const array = Array.prototype.slice.call(arrayLike);
console.log(array); // ['apple', 'banana']
- Spread Operator(展开运算符):使用展开运算符 ... 可以将可迭代对象或类数组对象展开为数组。
const arrayLike = { 0: 'apple', 1: 'banana', length: 2 };
const array = [...arrayLike];
console.log(array); // ['apple', 'banana']
这些方法都可以将类数组对象转换为真正的数组,使其具备数组的方法和属性。需要注意的是,类数组对象必须具有 length 属性和通过索引访问元素的能力才能成功转换为数组。
438.为什么函数的 arguments 参数是类数组而不是数组?如何遍历类数组?【热度: 669】【JavaScript】【出题公司: 腾讯】
关键词:arguments 参数、arguments 参数遍历
在 JavaScript 中,函数的 arguments 参数被设计为类数组对象,而不是真正的数组。这是因为 arguments 对象包含了函数调用时传入的所有参数,包括未命名的参数。它提供了一种方便的方式来访问和操作这些参数。
要遍历类数组对象,可以使用以下方法:
- 使用 for 循环和索引:通过使用普通的 for 循环和索引来遍历类数组对象。
function sum() {
for (let i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
sum(1, 2, 3); // 输出:1 2 3
- 使用 for...of 循环:从 ES6 开始,可以使用 for...of 循环来遍历可迭代对象,包括类数组对象。
function sum() {
for (let arg of arguments) {
console.log(arg);
}
}
sum(1, 2, 3); // 输出:1 2 3
- 将类数组对象转换为真正的数组后遍历:可以使用上述提到的类数组转换方法将类数组对象转换为真正的数组,然后使用数组的遍历方法进行遍历,如 forEach()、map() 等。
function sum() {
const args = Array.from(arguments);
args.forEach(arg => {
console.log(arg);
});
}
sum(1, 2, 3); // 输出:1 2 3
这些方法都可以用于遍历类数组对象,根据需求选择适合的方式进行操作。
439.escape、encodeURI、encodeURIComponent 区别【热度: 367】【JavaScript】【出题公司: 阿里巴巴】
关键词:js URL 编码解码
在 JavaScript 中,escape()、encodeURI() 和 encodeURIComponent() 都是用于编码 URL 或字符串的函数,但它们有一些区别:
- escape() 函数用于编码字符串中的特殊字符,使其能够安全地传输。它对字符进行编码,包括非 ASCII 字符和特殊字符。但需要注意的是,escape() 不会编码 URL 中的保留字符(例如 :/?#[]@!'()*+,;=),它只会编码其他字符。
// 输出:%48%65%6c%6c%6f%20%57%6f%72%6c%64%21
console.log(escape("Hello World!"));
- encodeURI() 函数用于对整个 URL 进行编码,用于将 URL 中的特殊字符转换为可传输的形式。它不会编码 URL 中的保留字符和一些特殊字符(例如 :/?#[]@!'()*+,;=)。它主要用于编码整个 URL,而不是编码 URL 的参数值。
// 输出:http://example.com/page.php?id=123
console.log(encodeURI("http://example.com/page.php?id=123"));
- encodeURIComponent() 函数用于编码 URL 的参数值,它会对所有特殊字符进行编码,包括 URL 中的保留字符和其他特殊字符。它用于编码 URL 参数中的特殊字符,以确保它们在 URL 中的传输和解析过程中不会被误解。
// 输出:Hello%20World%21
console.log(encodeURIComponent("Hello World!"));
需要注意的是,escape() 函数已被废弃,不推荐使用。在大多数情况下,建议使用 encodeURI() 或 encodeURIComponent() 函数进行 URL 编码。选择使用哪个函数取决于具体的需求,是否需要编码整个 URL 或只是其中的一部分(如参数值)。
441.解释性语言和编译型语言的区别【热度: 858】【JavaScript】【出题公司: 快手】
关键词:解释性语言和编译型语言
解释性语言和编译型语言是两种不同的编程语言类型,它们在代码的执行方式和运行过程中的一些特点上存在区别。
- 编译型语言:
- 编译型语言的代码在运行之前需要经过编译器的处理,将源代码一次性地转换成机器语言的可执行文件(通常是二进制文件)。
- 编译器将源代码转换为目标代码的过程包括词法分析、语法分析、语义分析、优化和代码生成等步骤。
- 在运行时,编译型语言的可执行文件直接在计算机上执行,无需再次进行翻译或解释。
- 典型的编译型语言包括 C、C++、Java(虚拟机字节码编译)、Go等。
- 解释性语言:
- 解释性语言的代码在运行时逐行被解释器解释执行,无需预先编译为可执行文件。
- 解释器逐行读取源代码,将其解析并直接执行,将源代码翻译为机器指令并逐行执行。
- 解释性语言的执行过程通常边解释边执行,每次运行都需要经过解释器的处理。
- 典型的解释性语言包括 JavaScript、Python、Ruby、PHP等。
区别:
- 编译型语言在运行之前需要将代码转换为可执行文件,而解释性语言在运行时逐行解释执行。
- 编译型语言的执行速度通常较快,因为代码已经被预先编译成机器语言,无需再进行解释。解释性语言的执行速度较慢,因为每次运行都需要经过解释器的处理。
- 编译型语言一般需要根据目标平台进行编译,可执行文件通常与特定的操作系统和硬件相关。解释性语言通常是跨平台的,只需要相应的解释器即可运行。
- 编译型语言在代码运行之前会进行全面的语法和类型检查,可以在编译过程中发现一些潜在的错误。解释性语言在运行时进行解释,错误可能会在运行过程中被发现。
需要注意的是,实际上很多语言不是严格的编译型语言或解释性语言,而是在两者之间存在折中的方式。例如,Java 语言将源代码编译为字节码(中间形式),然后在虚拟机中解释执行。因此,这些概念并不是绝对的,语言的执行方式可能有所不同。
442.ajax、axios、fetch的区别【热度: 855】【网络】【出题公司: Shopee】
关键词:ajax、axios、fetch、前端网络请求库
Ajax、Axios和Fetch都是用于进行HTTP请求的工具或技术,但它们在实现细节和功能方面有所不同。
- Ajax(Asynchronous JavaScript and XML):
- Ajax是一种用于在后台与服务器进行异步通信的技术。
- Ajax使用XMLHttpRequest对象发送和接收数据,可以通过JavaScript来更新页面的局部内容,而无需刷新整个页面。
- Ajax可以通过原生JavaScript编写,或者使用库如jQuery等来简化操作。
- Axios:
- Axios是一个基于Promise的HTTP客户端,可以在浏览器和Node.js环境中使用。
- Axios提供了更简洁、易用的API,支持请求和响应拦截、请求取消、全局配置等功能。
- Axios可以处理请求的错误,并提供了更方便的错误处理机制。
- Axios支持在浏览器中自动转换JSON数据,可以方便地发送JSON格式的请求和接收JSON格式的响应。
- Fetch:
- Fetch是Web API提供的一种用于发送HTTP请求的新特性,主要用于替代XMLHttpRequest。
- Fetch使用Promise来处理异步操作,提供了更简洁、灵活的API。
- Fetch基于Promise设计,可以更好地处理请求和响应,并支持链式调用和异步操作。
- Fetch支持跨域请求和对请求和响应进行拦截、转换等处理。
区别:
- Ajax是一种技术概念,而Axios和Fetch是具体的工具或技术实现。
- Axios相比Ajax和Fetch具有更多的功能和便捷的API,支持更多的扩展和配置。
- Fetch是基于Promise的新API,相对于Ajax和Axios更为现代化,并且支持更多的特性如跨域请求、拦截器等。
- Ajax可以通过原生JavaScript或库来实现,Axios和Fetch是专门的库。
- Axios和Fetch提供了更好的错误处理机制,而Ajax在错误处理方面相对简单。
选择使用哪种工具或技术取决于具体的需求和项目情况。如果需要较低级别的控制和自定义配置,可以选择原生的Ajax或Fetch。而如果需要更丰富的功能和更方便的API,可以选择使用Axios或其他类似的库。
443.深度遍历广度遍历的区别?【热度: 867】【JavaScript】【出题公司: 快手】
关键词:深度遍历广度遍历
深度遍历(Depth-First Search,DFS)和广度遍历(Breadth-First Search,BFS)是两种常用的图遍历算法,用于访问和搜索图或树中的节点。它们在遍历顺序和搜索策略上有所不同。
深度遍历(DFS):
- 深度遍历从一个节点开始,递归地访问该节点的子节点,直到达到最深的节点,然后回溯到上一级节点,继续访问其未访问的子节点。
- 在深度遍历中,我们首先访问根节点,然后依次访问每个子节点。对于每个子节点,再依次访问其子节点,直到到达叶子节点。
- 深度遍历可以通过递归或使用栈来实现。
广度遍历(BFS):
- 广度遍历从一个节点开始,首先访问该节点的所有相邻节点,然后逐层访问其他节点,直到访问完所有节点。
- 在广度遍历中,我们首先访问根节点,然后依次访问与根节点相邻的节点。然后,再依次访问与这些节点相邻的节点,以此类推,直到遍历完所有节点。
- 广度遍历可以通过使用队列来实现,即先进先出(FIFO)的数据结构。
区别:
- 深度遍历优先访问节点的子节点,然后再访问子节点的子节点,以此类推,直到到达最深的节点。而广度遍历优先访问当前层级的所有节点,然后再访问下一层级的节点。
- 在树或图结构中,深度遍历更适合查找目标节点在较深层级的情况,而广度遍历更适合查找目标节点在较浅层级的情况。
- 深度遍历可能会在较深层级上陷入递归或栈的调用,而广度遍历则需要使用队列来存储和访问节点,因此占用的内存空间较大。
- 深度遍历通常使用递归实现,而广度遍历通常使用迭代和队列实现。
选择使用深度遍历还是广度遍历取决于具体的应用场景和需求。如果需要快速到达目标节点且目标节点位于较浅的层级,可以选择广度遍历。如果需要深度探索并处理树或图中的节点,可以选择深度遍历。
高级开发者相关问题【共计 1 道题】
428.web 应用中如何对静态资源加载失败的场景做降级处理【热度: 1,093】【web应用场景】
关键词:静态资源降级、静态资源加载失败
在 Web 应用中,可以使用以下方法对静态资源加载进行降级处理,即在某个资源加载失败时使用备用的静态资源链接:
- 使用多个 CDN 链接:在 HTML 中使用多个静态资源链接,按照优先级顺序加载,如果其中一个链接加载失败,则尝试加载下一个链接。
<script src="https://cdn1.example.com/script.js"></script>
<script src="https://cdn2.example.com/script.js"></script>
<script src="https://cdn3.example.com/script.js"></script>
在加载 JavaScript 脚本时,浏览器会按照给定的顺序尝试加载各个链接,如果某个链接加载失败,浏览器会自动尝试加载下一个链接。
- 使用备用资源路径:在 JavaScript 中使用备用的资源路径,当主要的资源路径加载失败时,切换到备用路径。
var script = document.createElement('script');
script.src = 'https://cdn.example.com/script.js';
script.onerror = function() {
// 主要资源加载失败,切换到备用资源路径
script.src = 'https://backup.example.com/script.js';
};
document.head.appendChild(script);
在加载 JavaScript 脚本时,可以通过监听 onerror 事件,在主要资源加载失败时切换到备用资源路径,保证资源的可靠加载。
- 使用动态加载和错误处理:使用 JavaScript 动态加载静态资源,并处理加载失败的情况。
function loadScript(src, backupSrc) {
return new Promise(function(resolve, reject) {
var script = document.createElement('script');
script.src = src;
script.onload = resolve;
script.onerror = function() {
if (backupSrc) {
// 主要资源加载失败,切换到备用资源路径
script.src = backupSrc;
} else {
reject(new Error('Failed to load script: ' + src));
}
};
document.head.appendChild(script);
});
}
// 使用示例
loadScript('https://cdn.example.com/script.js', 'https://backup.example.com/script.js')
.then(function() {
// 资源加载成功
})
.catch(function(error) {
// 资源加载失败
console.error(error);
});
通过动态加载脚本的方式,可以在资源加载失败时切换到备用资源路径或处理加载错误。
除了前面提到的方法外,还有以下一些降级处理的方法:
- 本地备份资源:在 Web 应用的服务器上存储备份的静态资源文件,并在主要资源加载失败时,从本地服务器上加载备份资源。这种方法需要在服务器上维护备份资源的更新和一致性。
- 使用浏览器缓存:如果静态资源被浏览器缓存,则在资源加载失败时,浏览器可以使用缓存中的资源。可以通过设置合适的缓存策略,例如设置资源的 Cache-Control 头字段,让浏览器缓存资源并在需要时从缓存中加载。
- 使用 Service Worker:使用 Service Worker 技术可以在浏览器中拦截网络请求,从而实现更高级的降级处理。当主要资源加载失败时,可以使用 Service Worker 拦截请求并返回备用资源,或者动态生成代替资源。
- 使用资源加载管理工具:使用像 Webpack 这样的资源加载管理工具,可以通过配置多个资源入口点和插件来实现资源加载的灵活控制。在资源加载失败时,可以通过配置自动切换到备用资源或通过插件实现自定义的降级逻辑。
这些方法可以根据具体的需求和场景选择适合的降级处理策略。降级处理的目的是确保网页应用的正常运行,提高用户体验,并减少对单一资源的依赖性。