一、ES6新特性
ES6(ECMAScript 2015)是JavaScript的一个重要更新版本,引入了许多新特性和语法改进,下面详细说明一些主要的新特性:
1. let 和 const 声明:
使用`let`和`const`关键字可以声明块级作用域的变量,解决了`var`存在的变量提升和作用域问题。
`let`声明的变量可以被修改,`const`声明的变量是常量,不可被修改。
2. 箭头函数:
- 箭头函数提供了一种更简洁的函数定义方式。
- 箭头函数没有自己的`this`,会捕获所在上下文的`this`值。
3. 模板字符串:
- 使用反引号(``)来创建字符串模板,可以在其中插入变量和表达式。
- 提供了更方便的字符串拼接和多行字符串的支持。
4. 解构赋值:
- 可以轻松地从数组或对象中提取数据并赋值给变量。
- 提供了更便捷的数据解构和赋值操作。
5. 默认参数值:
- 可以为函数参数指定默认值,简化了函数的使用。
- 在调用函数时可以不传递参数,使用默认值。
6. 类:
- 引入了类的概念,可以更方便地定义对象的构造函数和方法。
- 提供了更符合面向对象编程的语法。
7. 模块:
- 引入了模块化的概念,可以将代码分割成独立的文件并导入导出模块。
- 提供了更好的代码组织和复用性。
8. Promise:
- 引入了Promise对象,简化了异步操作的处理,避免了回调地狱。
- 提供了更清晰和可靠的异步编程方式。
9. Generator 函数:
- Generator函数是一种可以暂停和恢复执行的函数。
- 可以通过`yield`关键字实现迭代器的功能,用于简化异步编程。
二、Promise原理
定义:
Promise 是 JavaScript 中处理异步操作的一种方式,它是一个代表了异步操作最终完成或失败的对象。Promise 有三种状态:Pending(进行中)、Fulfilled(已成功)和Rejected(已失败)。
原理:
创建 Promise 对象: 使用
new Promise()
构造函数可以创建一个 Promise 对象,该构造函数接收一个带有resolve
和reject
两个参数的执行器函数作为参数。执行器函数: 执行器函数会立即执行,其中包含异步操作。当异步操作完成时,可以调用
resolve()
方法将 Promise 状态从 Pending 变为 Fulfilled,或调用reject()
方法将 Promise 状态从 Pending 变为 Rejected。处理 Promise 状态: 可以通过
then()
方法来处理 Promise 的状态变化。then()
方法接收两个参数,第一个参数是处理 Promise Fulfilled 状态的回调函数,第二个参数是处理 Promise Rejected 状态的回调函数。Promise 链式调用: 可以通过链式调用
then()
方法来处理多个异步操作的顺序执行。每个then()
方法返回一个新的 Promise 对象,可以继续调用then()
方法或catch()
方法处理后续的状态变化。错误处理: 可以通过
catch()
方法来捕获 Promise 链中的任何错误。如果 Promise 链中的任何一个 Promise 被拒绝(Rejected),错误会被传递到最近的catch()
方法中进行处理。总结:
Promise 的原理是通过状态的变化和链式调用来处理异步操作,使得异步编程更加清晰和可控。通过 Promise,可以更好地处理异步操作的结果,避免了回调地狱和提供了更优雅的代码结构。
三、 浏览器从输入到页面渲染的过程
输入 URL: 用户在浏览器地址栏输入网址或点击链接,浏览器接收到 URL 请求。
发起请求: 浏览器向服务器发送 HTTP 请求,请求网页的资源(HTML、CSS、JavaScript、图片等)。
接收响应: 服务器接收到请求后,返回相应的资源文件给浏览器。
构建 DOM 树: 浏览器开始解析 HTML 文件,构建 DOM(文档对象模型)树,表示页面的结构。
构建 CSSOM 树: 解析 CSS 文件,构建 CSSOM(CSS 对象模型)树,表示页面的样式。
合并 DOM 和 CSSOM: 浏览器将 DOM 树和 CSSOM 树合并,生成渲染树(Render Tree),用于页面的布局和绘制。
布局(Layout): 浏览器根据渲染树计算每个节点在页面上的位置和大小,进行布局。
绘制(Paint): 浏览器根据布局信息,将页面上的内容绘制到屏幕上。
渲染页面: 浏览器渲染完页面后,显示在用户的屏幕上,用户可以看到页面内容。
交互和事件处理: 用户可以与页面进行交互,点击链接、按钮等,触发相应的事件处理函数。
**简短版:**在这个过程中,浏览器会进行网络请求、解析 HTML、构建 DOM 树、解析 CSS、计算布局、绘制页面等操作,最终将页面呈现给用户。
四、【算法】 罗马数字转整数
21.题目:
罗马数字包含以下七种字符:
I
,V
,X
,L
,C
,D
和M
。
字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000
例如, 罗马数字
2
写做II
,即为两个并列的 1 。12
写做XII
,即为X
+II
。27
写做XXVII
, 即为XX
+V
+II
。通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做
IIII
,而是IV
。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为IX
。这个特殊的规则只适用于以下六种情况:
I
可以放在V
(5) 和X
(10) 的左边,来表示 4 和 9。X
可以放在L
(50) 和C
(100) 的左边,来表示 40 和 90。C
可以放在D
(500) 和M
(1000) 的左边,来表示 400 和 900。给定一个罗马数字,将其转换成整数。
2.解题:
主要思路是遍历输入的罗马数字字符串,根据罗马数字字符对应的数值进行累加,同时根据特殊规则进行相应的减法操作。
具体步骤如下:
- 初始化结果变量result为0,前一个字符的值prev为0。
- 遍历输入的罗马数字字符串,对每个字符进行判断:
- ·根据当前字符的值current进行累加到result中。
- 如果当前字符的值current大于前一个字符的值prev,则需要减去两倍的前一个字符的值,因为当前字符是由前一个字符减去的,而prev已经在上一步中加过一次了。
更新prev为当前字符的值,继续下一次循环。
最终返回result作为转换后的整数值
int romanToInt(char* s) {
if(s == NULL || *s == '\0') {
return 0;
}int result = 0; int prev = 0; while(*s != '\0') { int current = 0; switch(*s) { case 'I': current = 1; break; case 'V': current = 5; break; case 'X': current = 10; break; case 'L': current = 50; break; case 'C': current = 100; break; case 'D': current = 500; break; case 'M': current = 1000; break; default: return 0; } result += current; if(current > prev) { result -= 2 * prev; } prev = current; s++; } return result;
}