本文题目来源于全网收集,答案来源于 ChatGPT 和 博主(的小部分……)
格式:题目 h3 + 回答 text + 参考大佬博客补充 text + 示例代码 code
+ 解释 quote + 补充 quote
上一篇链接:2024 前端面试题(GPT回答 + 示例代码 + 解释)No.21 - No.40
目录 No.41 - No.60
- 本文题目来源于全网收集,答案来源于 ChatGPT 和 博主(的小部分……)
- 格式:题目 h3 + 回答 text + 参考大佬博客补充 *text* + 示例代码 ```code```+ 解释 quote + 补充 quote
- 上一篇链接:[2024 前端面试题(GPT回答 + 示例代码 + 解释)No.21 - No.40](https://blog.csdn.net/m0_67023788/article/details/136104057)
- 41. 什么是高阶函数?
- 42. 描述浏览器的渲染过程?
- 43. DOM 树和渲染树的区别?
- 44. JavaScript 中实现继承的方法
- 45. eval是做什么的?
- 46. JS延迟加载的方式有哪些?
- 47. 闭包的特性和理解
- 48. 为什么 JS 是单线程, 而不是多线程
- 49. 以下结果输出什么
- 50. 防抖 和 节流
- 51. 重排 与 重绘
- 52. 以上四者关联?
- 53. call apply bind 三者的作用 与 区别
- 54. JavaScript 的严格模式
- 55. addEventListener 和 普通事件 绑定
- 56. 渐进增强 与 优雅降级
- 57. 浏览器对象
- 58. 列举 3种强制类型转换 和 2种隐式类型转换
- 59. `<input>` 元素中的 `readonly` 和 `disabled`
- 60. 什么是回调?
41. 什么是高阶函数?
满足以下条件之一的函数:
- 接受一个或多个函数作为参数。
- 返回一个新函数。
常见的高阶函数包括 map
、filter
、reduce
等,它们能够简化代码并提高代码的可读性。
42. 描述浏览器的渲染过程?
-
解析 HTML:浏览器通过网络获取到 HTML 文件,并对其进行解析,构建出 DOM(文档对象模型)树。DOM 树表示了 HTML 文档的结构和内容。
-
解析 CSS:浏览器会解析 CSS 文件,构建出 CSSOM(CSS 对象模型)树。CSSOM 树表示了 CSS 样式规则的层级关系和样式属性。
-
合并 DOM 和 CSSOM:将 DOM 树和 CSSOM 树合并成一个渲染树(Render Tree)。渲染树只包含需要显示的元素以及这些元素的样式信息。
-
布局计算:渲染树中的每个节点都会进行布局计算,确定每个节点在屏幕上的位置和大小。这个过程被称为布局(Layout)或回流(Reflow)。
-
绘制页面:浏览器使用得到的布局信息,将渲染树中的节点绘制到屏幕上。这个过程被称为绘制(Painting)或重绘(Repaint)。
-
重复布局和绘制:如果页面发生了变化(例如用户交互、JavaScript 修改了元素样式等),浏览器会重新执行布局和绘制过程,更新页面的显示。
值得注意的是,浏览器在解析 HTML 和 CSS 的过程中是逐步完成的,遇到 <script>
标签时会阻塞 HTML 解析,直至脚本执行完毕才会继续解析。这也是为什么推荐将 JavaScript 脚本放在 <body>
标签底部,以便提高页面加载速度。
另外,现代浏览器还会使用一些优化技术,如预渲染、懒加载、异步加载等,来提升页面渲染性能和用户体验。
43. DOM 树和渲染树的区别?
-
目的不同:DOM 树表示网页文档的结构,包含了所有 HTML 标签和它们的属性,可以通过 JavaScript 进行操作。而渲染树则是为了将 DOM 树上的节点进行可视化呈现而构建的,它只包含需要显示的节点和这些节点的样式信息。
-
节点不同:DOM 树上的每个节点都对应着一个 HTML 元素(标签),包括那些被隐藏、不可见或不需要显示的元素。而渲染树上只包括需要显示的元素,如可见的文本、图像、表单元素等。
-
样式计算不同:DOM 树中的节点和属性与样式规则是一一对应的,而渲染树中的节点是根据 DOM 节点和 CSS 样式规则共同计算得出的,包括继承和层叠等样式信息。
-
顺序不同:DOM 树上的节点按照它们在 HTML 文档中的出现顺序排列,而渲染树上的节点则按照它们在文档流中的位置(如盒模型)以及它们的层级关系(如 z-index)排列。
总之,DOM 树和渲染树是两个不同的树状结构,它们的目的、节点、样式计算和顺序等方面都有所不同。在进行网页开发和性能优化时,了解这两个树的区别和关系是非常重要的。
44. JavaScript 中实现继承的方法
- ES6Class继承
- 原型链实现继承:
- 将父类的实例作为子类的原型实现继承
- 这种继承方法的缺点是父类中的引用类型数据会被所有子类共享
// 父类
function Parent(name) {
this.name = name
this.foods = ['西蓝花', '西红柿']
this.sayFoods = function () {
console.log(this.foods)
}
}
// 子类
function Son() {
}
// 将父类的实例 作为子类的原型
Son.prototype = new Parent('jack')
const s1 = new Son()
s1.sayFoods()// ['西蓝花', '西红柿']
const s2 = new Son()
s2.sayFoods() // ['西蓝花', '西红柿']
s2.foods.push('西葫芦')
s2.sayFoods()// ['西蓝花', '西红柿', '西葫芦']
s1.sayFoods()// ['西蓝花', '西红柿', '西葫芦']
- 构造函数继承:
- 在子类的构造函数中通过
call
或apply
父类的构造函数 - 这种继承方法的缺点是:子类没法使用父类原型上的属性/方法
- 在子类的构造函数中通过
// 父类
function Parent(name) {
this.name = name
}
Parent.prototype.sayHi = function () {
console.log('你好,我叫:', this.name)
}
// 子类
function Son(name) {
Parent.call(this, name)
}
const s1 = new Son('lucy')
const s2 = new Son('rose')
s1.sayHi() // 报错
- 组合继承
- 组合继承的核心步骤有2步:
- 通过原型链继承公共的属性和方法
- 通过构造函数继承实例独有的属性和方法
- 组合继承的特点:调用2次父类的构造函数,浪费性能
- 组合继承的核心步骤有2步:
- 原型式继承
- 原型式继承的核心步骤是:对某个对象进行浅拷贝,可以通过内置api
Object.create
实现,不需要调用构造函数即可实现继承,主要针对于继承对象的情况 - 原型式继承的缺点是:父类中的引用数据类型,会被所有子类共享
- 原型式继承的核心步骤是:对某个对象进行浅拷贝,可以通过内置api
- 寄生式继承
- 寄生式继承的核心步骤是:基于对象创建新对象(可以使用
Object.create
),并且为新创建的对象增加新的属性和方法 - 寄生式继承和原型式继承的区别是:创建出来的新对象,会额外的增加新的属性/方法
- 寄生式继承的核心步骤是:基于对象创建新对象(可以使用
- 寄生组合式继承
- 寄生组合式继承的核心步骤是:通过构造函数来继承属性,通过原型链来继承方法
- 寄生组合式继承和组合式继承的区别是:原型链的继承并没有调用父类的构造函数,而是直接基于父类的原型创建一个新副本实现继承
45. eval是做什么的?
eval()
函数是一个 JavaScript 的全局函数,它接受一个字符串作为参数,并将这个字符串当作 JavaScript 代码来执行。eval()
函数会动态地执行传入的字符串表示的代码,并返回执行结果。
使用 eval()
函数可以动态地生成和执行 JavaScript 代码,这使得在运行时动态地构建和执行代码成为可能。一些常见的用途包括:
-
动态执行代码:可以将动态生成的 JavaScript 代码以字符串的形式传递给
eval()
函数来执行。 -
计算表达式:
eval()
可以用于计算字符串中表示的数学表达式。 -
JSON 解析:在某些情况下,可以使用
eval()
来解析 JSON 字符串(尽管更推荐使用JSON.parse()
)。
尽管 eval()
提供了灵活性和强大的功能,但也存在潜在的安全风险和性能问题。因为 eval()
可以执行任意的 JavaScript 代码,包括恶意代码,所以不建议在生产环境中频繁使用 eval()
。此外,由于 eval()
的执行会引起解析和编译,可能导致性能下降。
总的来说,eval()
是一个功能强大但应谨慎使用的函数,需要确保传入的字符串是可信任且安全的,以避免潜在的安全漏洞。在大多数情况下,最好避免使用 eval()
,而是寻找更安全和可靠的替代方案。
// 定义一个包含 JavaScript 代码的字符串
var code = "console.log('Hello, World!');";
// 使用 eval() 执行字符串中的代码
eval(code);
在这个例子中,我们定义了一个字符串 code
,其中包含了一行 JavaScript 代码,用于打印 “Hello, World!” 到控制台。然后我们使用 eval()
函数执行这个字符串中的代码,结果会在控制台上打印出 “Hello, World!”。
需要注意的是,虽然这个例子展示了 eval()
的基本用法,但在实际开发中,应该尽量避免使用 eval()
,特别是当字符串的来源不可信时,以免造成安全漏洞。如果有其他更安全的替代方案,最好选择使用那些方法来动态执行代码。
46. JS延迟加载的方式有哪些?
JavaScript 的延迟加载是一种优化网页性能的技术,可以减少页面的初始加载时间,提高用户体验。以下是几种常见的 JavaScript 延迟加载方式:
- defer 属性:在 HTML 中,可以使用 <script> 标签的 defer 属性来标记需要延迟加载的 JavaScript 文件。设置了 defer 属性的脚本将会在文档解析完成后、触发 DOMContentLoaded 事件前执行。
<script src="example.js" defer></script>
- async 属性:与 defer 类似,async 属性也用于异步加载 JavaScript 文件,但它表示脚本在下载完成后立即执行(可能无序),不会阻塞页面的解析和渲染。
<script src="example.js" async></script>
- 动态创建 <script> 元素:通过 JavaScript 动态创建 <script> 元素,并将其添加到文档中,可以实现按需加载脚本的目的。
var script = document.createElement('script');
script.src = 'example.js';
document.body.appendChild(script);
-
使用模块化加载工具:类似于 RequireJS、SystemJS、webpack 等模块化加载工具可以实现按需加载 JavaScript 文件,根据需要动态地加载模块,而不必一次性加载所有脚本。
-
Intersection Observer:利用 Intersection Observer API 可以实现当某个元素进入视口时再加载相关的 JavaScript 脚本,从而实现延迟加载。
这些是常见的 JavaScript 延迟加载方式,根据具体的使用场景和需求,选择合适的方式可以有效提升页面性能和加载速度。
47. 闭包的特性和理解
- 当一个函数内部定义了另一个函数,并且内部函数引用了外部函数的变量时,就形成了闭包。
- 内部函数可以访问并更新外部函数的变量
- 外部函数的变量不会被销毁
- 避免污染,但容易内存泄露
48. 为什么 JS 是单线程, 而不是多线程
JavaScript 是一种单线程语言,这意味着它在同一时间只能执行一个任务。这与其他一些编程语言(如Java和C++)不同,它们支持多线程并行执行。
存在以下几个原因解释了为什么 JavaScript 设计成单线程:
-
简单性:单线程模型使得编写和调试 JavaScript 代码更加简单。多线程编程会引入许多复杂的问题,例如竞态条件(race conditions)、死锁(deadlocks)等,而单线程模型可以避免这些问题,降低了编程复杂度。
-
浏览器安全性:JavaScript 最初是作为浏览器脚本语言设计的,如果允许 JavaScript 多线程运行,就会存在跨域安全问题。多线程脚本可以访问和修改来自不同域的数据,这可能导致安全漏洞。
-
同步操作:JavaScript 主要用于浏览器中进行交互操作,例如事件处理、DOM 操作等,这些操作需要访问和修改页面的状态。如果 JavaScript 是多线程的,那么不同线程之间对于页面状态的修改可能会引发不可预料的结果。
尽管 JavaScript 是单线程的,但它仍然支持异步操作,通过回调函数、Promise、async/await 等机制来处理异步任务,以避免阻塞页面和提高性能。
值得注意的是,现代浏览器通过 Web Workers 提供了一种多线程的解决方案,允许在单独的线程中执行 JavaScript 代码,来处理一些计算密集型的任务,但这些线程不能直接操作页面 DOM。
49. 以下结果输出什么
for(var i = 0; i < 5; i++) {
setTimeout(function(){
console.log(i)
}, 0)
}
上面的代码会输出以下结果:
5
5
5
5
5
这是因为在 JavaScript 中,setTimeout 函数是异步的,它会将回调函数放入事件队列中,等到当前调用栈执行完毕后再执行回调函数。而在循环中的 setTimeout 回调函数会在循环执行完毕后才被调用。
在循环结束时,变量 i 的值已经变成了 5。因此,当 setTimeout 的回调函数执行时,会打印出变量 i 的当前值,即 5。
如果想要按预期输出 0、1、2、3、4,可以
- 通过使用闭包来捕获每次循环时的 i 的值,例如:
for (var i = 0; i < 5; i++) {
(function (j) {
setTimeout(function () {
console.log(j);
}, 0);
})(i);
}
- 通过使用 let 来声明每次循环时的 i 的值,例如:
for(let i = 0; i < 5; i++) {
setTimeout(function(){
console.log(i)
}, 0)
}
这样就能够输出预期的结果。
50. 防抖 和 节流
防抖(Debouncing)
防抖就是在触发事件后,等待一定时间再执行回调函数。如果在等待期间又触发了该事件,则重新计时,直到等待时间结束才执行回调函数。简单来说,就是防止函数被频繁调用,只有在一定的空闲时间之后再执行一次。
实现方式:可以使用 setTimeout
函数实现防抖。每次触发事件时都清除原来的定时器,然后重新设置一个定时器。如果在定时器时间内再次触发事件,则会重新计时。
节流(Throttling)
节流就是在一定时间内只允许函数执行一次,也就是说,如果在等待时间内再次触发事件,则忽略该事件。节流可以有效地减少函数的执行次数,提高页面的性能。
实现方式:可以使用定时器来实现节流。当触发事件时,设置一个定时器,在定时器的时间范围内不能重新触发事件。当定时器时间结束后执行回调函数,并重新设置定时器。
防抖与节流的应用场景:
- 防抖:在输入框中连续输入时,可以使用防抖来减少请求次数;在窗口大小改变、滚动等操作时,可以使用防抖提高性能。
- 节流:在页面滚动中,可以使用节流来减少事件的触发次数;在鼠标移动、拖拽等操作时,可以使用节流来提高性能。
总之,防抖和节流是常用的前端性能优化方法,可以有效地控制函数的执行次数,减少无效操作,提高页面的响应速度。
51. 重排 与 重绘
重排(Reflow)和重绘(Repaint)是页面渲染过程中常见的操作,它们会影响页面的性能和用户体验。
重排(Reflow)
重排是指当页面中的元素发生布局变化,影响了它们的几何属性(如大小、位置等)时,浏览器需要重新计算元素的几何属性,并重新排列页面中的元素。这个过程会涉及整个页面的重新布局,因此开销较大。
引起重排的操作包括:
- 改变窗口大小
- 修改元素的位置、尺寸、内容
- 添加或删除可见的 DOM 元素
- 改变字体大小
- 改变样式表
重绘(Repaint)
重绘是指当页面中的元素样式发生改变,但没有影响其几何属性时,浏览器会重新绘制这些元素,但不会重新计算它们的位置和大小。重绘的开销相对较小,因为它不需要重新布局元素,只需要更新元素的样式。
引起重绘的操作包括:
- 修改元素的背景色、文字颜色、边框样式等
- 添加阴影或轮廓
- 修改透明度
区别与应用
重排和重绘都会影响页面性能,但重排的开销更大,因为它需要重新计算整个页面的布局。为了优化页面性能,可以采取以下措施:
- 尽量减少重排和重绘的次数:合并多次操作,或使用文档片段进行修改后再插入页面。
- 使用 CSS3 中的 transform 和 opacity 属性:它们可以在不影响布局的情况下进行动画效果,减少重排和重绘。
- 对于动画效果,使用 position: absolute 或 fixed 定位:这样可以脱离文档流,避免影响其他元素的布局。
通过理解重排和重绘的原理,可以更好地优化页面性能,提升用户体验。
52. 以上四者关联?
重排和重绘是与页面渲染相关的概念,而防抖和节流是用来优化函数执行频率的方法,它们之间并没有直接的关系。
重排和重绘会影响页面的性能,因为它们可能导致浏览器重新计算布局和重新绘制元素,从而消耗更多的计算资源。在编写前端代码时,我们应该尽量减少重排和重绘的发生,以提高页面的性能。
防抖和节流则是针对函数的频繁调用进行优化的方法。防抖可以确保在一定时间内只执行一次函数,避免函数被频繁调用;节流则是控制函数在一定时间内只能执行一次,来减少函数的执行频率。
虽然重排和重绘以及防抖和节流都与性能优化有关,但它们所针对的对象和优化方式不同。在实际开发中,我们可以结合使用这些方法,既减少页面的重排和重绘,又优化函数的执行频率,以提升整体的用户体验和页面性能。
在处理重排和重绘时,防抖和节流可以发挥一定作用:
-
防抖:如果页面中的某些操作会导致频繁的重排或重绘,可以使用防抖技术来延迟触发这些操作,等待一段时间内没有新的触发时再执行,从而减少重复的计算和页面渲染,提高性能。
-
节流:对于一些频繁触发的重排或重绘操作,可以使用节流来限制其执行频率,例如每隔一定时间执行一次,这样可以平滑处理这些操作,避免过多的计算和渲染开销。
53. call apply bind 三者的作用 与 区别
call
、apply
和 bind
是 JavaScript 中用于改变函数执行上下文(即 this
指向)的方法,它们的作用和区别如下:
-
call:
call
方法可以立即调用一个函数,并且可以指定函数内部this
的指向。- 语法:
function.call(thisArg, arg1, arg2, ...)
thisArg
:在函数执行时指定的this
的值。- 参数列表:可以传入多个参数,作为函数的参数传递给被调用的函数。
- 作用:立即调用函数,并指定函数内部的
this
指向为thisArg
。
-
apply:
apply
方法也是立即调用一个函数,并且可以指定函数内部this
的指向。- 语法:
function.apply(thisArg, [argsArray])
thisArg
:在函数执行时指定的this
的值。argsArray
:以数组形式传入的参数列表。- 作用:立即调用函数,并指定函数内部的
this
指向为thisArg
,同时将参数以数组形式传递给被调用的函数。
-
bind:
bind
方法会创建一个新的函数,并将原函数的this
指向固定为指定的值,不会立即调用原函数。- 语法:
function.bind(thisArg, arg1, arg2, ...)
thisArg
:在新函数被调用时指定的this
的值。- 参数列表:可以传入多个参数,作为调用新函数时的参数。
- 作用:创建一个新函数,固定函数内部的
this
指向为thisArg
,并可以传入参数。需要调用时再手动调用这个新函数。
区别:
call
和apply
都是立即调用原函数,而bind
是返回一个新函数。call
和apply
的区别在于参数的传递方式,call
是逐个传入参数列表,apply
是以数组形式传入参数。bind
是返回一个新函数,不会立即执行原函数,而是需要在之后手动调用。
总结:call
和 apply
是用于立即调用函数并改变函数执行上下文,bind
是用于创建一个新函数并固定函数执行上下文。
54. JavaScript 的严格模式
JavaScript 的严格模式(Strict Mode)是 ECMAScript 5 引入的一种提供更严格语法和更安全的 JavaScript 变体的方式。使用严格模式可以帮助开发者避免一些常见的编码错误,并且使得 JavaScript 引擎更加严格地执行代码。下面是一些严格模式的特点和例子:
-
变量必须声明:
在严格模式下,所有变量都必须先声明后使用,否则会报错。"use strict"; x = 10; // 报错:x 没有声明
-
禁止删除变量:
无法删除变量,只能删除属性。"use strict"; var x = 10; delete x; // 报错:不能删除变量
-
禁止重复参数名:
函数的参数名不能重复。"use strict"; function sum(a, a, c) { // 报错:参数名重复 return a + a + c; }
-
禁止使用 eval:
无法使用eval
函数。"use strict"; eval("var x = 10"); // 报错:无法使用 eval
-
禁止 this 指向全局对象:
在函数内部的this
不再指向全局对象,在严格模式下,它会保持为undefined
。"use strict"; function showThis() { return this; } console.log(showThis()); // 输出:undefined
这些只是严格模式的一部分特点和例子,严格模式还包含了其他一些特性,如禁止使用八进制字面量、禁止对只读属性赋值等。启用严格模式可以在脚本开头使用字符串 "use strict";
或者放在函数体开头,以实现更加严格的代码检查和执行。
55. addEventListener 和 普通事件 绑定
普通事件绑定和使用addEventListener
方法进行事件绑定有几点区别:
-
语法形式:
- 普通事件绑定:通过在 HTML 元素的属性中直接指定事件处理函数,例如
<button onclick="showAlert()">点击我</button>
。 addEventListener
方法:通过 JavaScript 代码动态地为元素添加事件监听器,例如element.addEventListener('click', showAlert)
。
- 普通事件绑定:通过在 HTML 元素的属性中直接指定事件处理函数,例如
-
事件处理方式:
- 普通事件绑定:事件处理函数会直接作为字符串指定在 HTML 中,可能会导致页面结构和行为混杂在一起,不利于维护和调试。
addEventListener
方法:将事件处理函数作为实际的函数对象传递给addEventListener
,更好地将行为和结构分离,易于维护和修改。
-
多事件绑定:
- 普通事件绑定:每个事件只能绑定一个处理函数,如果要为同一个事件绑定多个处理函数,会比较麻烦。
addEventListener
方法:可以为同一个元素的同一个事件添加多个不同的事件处理函数,而不会相互覆盖。
-
事件移除:
- 普通事件绑定:难以移除已经绑定的事件处理函数,通常需要将对应的属性值置为空来取消事件绑定。
addEventListener
方法:可以通过removeEventListener
方法来动态地移除事件处理函数,使得管理事件更加方便。
总的来说,使用addEventListener
方法进行事件绑定更加灵活、易于维护,并且符合现代的前端开发规范。在实际开发中,推荐尽量使用addEventListener
方法来绑定事件,避免混杂在 HTML 中直接指定事件处理函数的方式。
56. 渐进增强 与 优雅降级
渐进增强(Progressive Enhancement)和优雅降级(Graceful Degradation)是两种前端设计理念,旨在提高网站或应用程序的可用性和稳定性。虽然它们的目标是相同的,但是它们的实现方式略有不同。
渐进增强:
- 渐进增强的核心思想是从最基本、最简单的功能开始构建网站或应用程序。首先为基本浏览器提供功能和内容,随着浏览器能力的提升,逐渐添加更多的功能和内容。这种方法确保用户能够始终访问内容,并且使用更高级别的浏览器时可以获得更好的体验。
- 例如,为了满足不同的网络环境和设备,可以使用响应式设计和逐步增强技术来逐渐改进网站或应用程序的外观和功能。这样,在传统浏览器上,用户可以访问基本的网站内容;而在更高级别的设备上,用户可以获得更先进的体验和更多的交互。
优雅降级:
- 优雅降级的核心思想是从完整的、高级别的功能开始构建网站或应用程序。首先提供最先进的功能和内容,然后检查浏览器是否支持这些功能。如果不支持,就回退到基本的功能和内容,以确保网站或应用程序仍然可用。
- 例如,在最新的浏览器上,可以使用HTML5和CSS3的最新特性来增强网站或应用程序的外观和功能;如果用户使用早期版本的浏览器,则回退到使用JavaScript Polyfill等技术实现类似的功能。
总的来说,渐进增强更侧重于从简单功能开始构建应用程序,并逐步添加更先进的功能;而优雅降级更侧重于提供完整、高级别的功能,并在必要时回退到基本的功能。两种方法都旨在提高用户体验和应用程序的稳定性,但具体的实现方式取决于具体情况和开发者的偏好。
57. 浏览器对象
浏览器对象是指在 JavaScript 中可以通过全局对象访问的一组对象,用于与浏览器进行交互。以下是常见的浏览器对象:
- Window 对象:代表浏览器中打开的窗口或标签页,是其他对象的最顶层对象。
- Document 对象:代表当前窗口或标签页中加载的文档(HTML 文档),提供对页面内容的访问和操作。
- Navigator 对象:提供有关浏览器的信息,如浏览器的名称、版本、用户代理等。
- Location 对象:提供有关当前 URL 的信息,如页面的 URL、主机名、路径等,并可用于修改 URL。
- History 对象:提供对浏览器历史记录的访问和操作,可以通过前进、后退等方法控制页面导航。
- Screen 对象:提供有关用户屏幕的信息,如屏幕的宽度、高度、像素密度等。
除了上述对象外,还有其他一些特定的对象,如:
- XMLHttpRequest 对象:用于在后台与服务器进行数据交互,实现异步请求和响应。
- Storage 对象:提供对浏览器本地存储(localStorage 和 sessionStorage)的访问,可以将数据保存在客户端。
- Event 对象:代表事件的状态和行为,包含与事件相关的属性和方法。
- Math 对象:提供执行数学计算的方法和常量,如三角函数、对数函数、随机数等。
这些浏览器对象可以通过全局对象window
访问,例如window.document
表示访问Document
对象。通过这些对象,我们可以实现与浏览器交互的功能,操作页面内容、发送请求、控制导航等。
58. 列举 3种强制类型转换 和 2种隐式类型转换
强制类型转换(显示类型转换)是在编码时明确地将一个数据类型转换为另一个数据类型。以下是三种常见的强制类型转换:
- Number():将其他数据类型转换为数字类型。例如,
Number("123")
将字符串"123"转换为数字123。 - String():将其他数据类型转换为字符串类型。例如,
String(123)
将数字123转换为字符串"123"。 - Boolean():将其他数据类型转换为布尔类型。例如,
Boolean(0)
将数字0转换为布尔值false。
隐式类型转换是指在特定的操作中,JavaScript 自动将一个数据类型转换为另一个数据类型,而无需明确进行转换。以下是两种常见的隐式类型转换:
- 数值运算中的隐式转换:当使用数学运算符(如+、-、*、/)对不同类型的值进行运算时,JavaScript 会自动进行类型转换以执行运算。例如,
1 + "2"
将数字1隐式转换为字符串,并与字符串"2"拼接起来得到结果"12"。 - 逻辑运算中的隐式转换:在逻辑运算(如逻辑与&&、逻辑或||)中,JavaScript 会将非布尔类型的值转换为布尔类型进行处理。例如,
"abc" && true
中的字符串"abc"会被转换为布尔值true,因此整个表达式返回true。
需要注意的是,在进行类型转换时,应注意数据类型之间的兼容性和转换规则,以避免产生意外的结果。
59. <input>
元素中的 readonly
和 disabled
- readonly(只读):
<input readonly>
表示输入框是只读的,用户可以看到输入框中的内容,但无法修改或输入新的内容。- 可以通过 JavaScript 动态地改变
<input>
元素的值,但用户无法直接在页面上更改该值。 - 提交表单时,包含
readonly
属性的输入框的值会被提交到服务器。
- disabled(禁用):
<input disabled>
表示输入框被禁用,用户无法看到输入框内容,也无法进行任何交互操作。- 禁用状态下的输入框不会被包括在表单提交的数据中,其值不会被发送到服务器。
- 与
readonly
不同,disabled
的输入框不会接收焦点,也不会触发与输入框相关的事件。
60. 什么是回调?
回调(Callback)是指在编程中,将一个函数作为参数传递给另一个函数,并在特定事件发生或条件满足时执行这个函数。回调函数可以用来实现异步操作、事件处理、数据处理等功能。
回调函数是一种常见的编程技术,可以帮助解决异步操作和事件处理等场景下的问题,使程序能够更加灵活和高效地处理各种情况。