整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

JavaScript 的 .reduce() 函数的完整指南(带有真实示例)

本指南中,我们将介绍:

.reduce() 函数是什么?

创建我们的 .reduce() 函数版本

计算电子商务购物车的商品总数和价格

为餐厅菜单创建一组独特的类别

从数组中删除重复的对象

用 .reduce() 替换 .filter().map()

按键分组对象(类似于 SQL GROUP BY 或 C# 的 .GroupBy())

乍一看似乎很混乱

如果您曾经为理解 .reduce() 函数而苦苦挣扎,那么您并不孤单。 要真正了解它的工作原理并自信地使用它,需要多花几次功夫。

大多数例子都使用一个简单的数字或字符串数组,但现实是我们通常使用很少涉及的复杂对象。

但在我们跳进去之前。

以下是如何从这些内容中获得更多信息。

打开您的代码编辑器并亲自尝试示例

修改它(更改值,向数组添加或从数组中删除元素等)

如果您发现自己迷失在其中一个示例中,请使用笔和纸或在您的代码编辑器上追踪变量的值。

让我们开始吧!

.reduce() 函数是什么?

它是一种对数组的每个元素执行回调函数的方法。

计算的返回值传递给下一个元素。

在第一次迭代中,没有“上一次计算的返回值”,如果传入,可以用一个初始值代替。

否则,数组的第一个元素被用作初始值,迭代从下一个元素开始。

简单的说,就是一个变量和一个循环。

变量保存新值

循环遍历数组,因此我们可以从每个元素中获取我们想要的内容

这个:

实现与此相同:

几乎每次需要使用变量和循环时,都可以用 reduce 函数替换它。

由于没有比实际尝试更好的学习方法,让我们构建我们的 .reduce() 方法版本,以便我们真正理解它。

构建我们自己的 .reduce()

让我们通过解决一个简单的问题来做到这一点:

我们有一个数字数组,我们想要所有数字的总和。

就像上面的变量和循环的例子一样。

我们需要三样东西:

数组

保存总值 total 的变量(通常称为累加器)

遍历数组的循环

假设你想把它变成一个函数,这样你就可以很容易地使用它,你会怎么做?

也许沿着这些路线:

我们将数组作为参数传递给我们的函数

我们最后返回总数。

这看起来不错,但是如果我们想要设置变量总计初始值的选项怎么办?

我们可以将选项添加为另一个参数并将总计设置为它的值。

像这样:

但是这个函数还有2个问题。

我们无法在循环内添加要执行的不同逻辑(它只会将当前元素添加到 sum 变量)

它仅适用于简单数组(其中每个项目都是值类型,而不是对象)

我会告诉你我的意思。

这次让我们创建一个对象数组

让我们调用传入对象数组的 myReducer 函数

它不起作用,因为我们要添加的值在对象内部而不是对象本身。

我们必须以 total += arr[i].number 的形式访问它

但是这个函数没有考虑到这一点。

但是,如果我们添加一个回调函数作为第二个参数,我们可以:

对数组的每个元素执行回调函数

创建我们需要的任何自定义逻辑

让我们修改我们的 myReducer 函数。

让我们用对象数组再次测试它。

首先,声明回调函数并调用传入它的 myReduce。

请注意,我们根据 total 的值添加了 if 和 else 条件,这是我们的 initialValue 选项。

如果未给出初始值

它不会在第一次迭代时执行回调

没有什么要补充的,initialValue 是未定义的。

只需将 total 设置为当前元素的值

如果给出初始值

它在所有迭代中执行回调

这几乎就是原始 Array.prototype.reduce() 所做的。

主要区别在于不需要将数组作为参数传递,因为原始 .reduce() 绑定到 Array.prototype,因此数组始终是调用 .reduce() 的数组。

计算电子商务购物车的总项目数和价格

假设你有一个像这样的数组:

您需要将此数组缩减为这样的对象 { totalItems: 0, totalPrice: 0 } 以便我们可以在结帐页面上显示正确的信息。

这是我们可以做到的:

为餐厅菜单创建一组独特的类别

给定这个数组:

我们需要将其缩减为一系列独特的类别,例如 ['Appetizer','Entree','Main']

这是我们可以做到的:

从数组中删除重复的对象

与上面的示例类似,但这次我们需要返回仅使用唯一对象过滤的相同对象数组。

这是具有重复对象的数组:

注意:你必须有一个类似于 id 的属性,它对每个对象都是唯一的

这就是我们如何创建另一个仅包含唯一元素的数组:

将 .filter().map() 替换为 .reduce()

过滤数组然后修改过滤后数组的元素是很常见的。

我们将使用上面菜单类别的相同数组

但是这次我们想得到一个数组,其中只有类别为“Entree”的项目的 itemName

我们可以使用 .filter() 数组,然后使用 .map() 来完成它

或者我们可以用 .reduce() 来做

使用 .reduce() 的优点是您只迭代数组一次。

按键分组对象(类似于 SQL GROUP BY 或 C# 的 .GroupBy())

这是我最喜欢的。 这是一个非常方便的函数,可能会在下一次更新时包含在 JavaScript 的数组方法中(目前处于第 3 阶段以供批准)

这个 groupBy 函数也可以用作解决更复杂问题的中间步骤。

我们将再次使用菜单类别数组:

这是我们的 groupBy 函数:

如果我们添加将密钥作为函数传递的选项,它会变得更加方便。

只需替换这一行:

有了这个:

这样我们就可以调用它并传递一个返回键的函数,而不是自己编写字符串,避免拼写错误。

结论

在这篇文章中,我们了解到:

什么是 .reduce() 函数

如何创建我们的 .reduce() 函数版本

计算电子商务购物车的总项目数和价格

为餐厅菜单创建一组独特的类别

从数组中删除重复的对象

将 .filter().map() 替换为 .reduce()

如何按键对对象进行分组(类似于 SQL GROUP BY 或 C# 的 .GroupBy())

谢谢阅读!


/下栽のke:quangneng.com/321/

JavaScript高级玩法的详细介绍

JavaScript是一种非常灵活且强大的脚本语言,广泛应用于网页开发、移动端开发、后端开发等多个领域。对于想要提升JavaScript编程能力的开发者来说,掌握一些高级玩法是非常必要的。以下是一些JavaScript的高级玩法:

1. 函数的高级特性

JavaScript中的函数不仅能够执行特定任务,还具有许多高级特性。例如,函数可以接受参数,也可以返回值;函数可以嵌套在其他函数中,形成高阶函数;函数还可以作为一等公民存在,可以被赋值给变量,也可以作为函数的参数传递。

2. 原型链和继承

JavaScript中的所有对象都有一个内部属性[[Prototype]],这个属性指向它的原型对象。通过__proto__属性或者Object.getPrototypeOf()方法,可以访问一个对象的原型。JavaScript中的继承是通过原型链实现的,子类的原型可以通过__proto__属性或者constructor.prototype属性指向父类的实例。

3. 异步编程

JavaScript中的异步编程非常复杂,但非常重要。常见的异步编程方式有回调函数、Promise、async/await等。掌握这些异步编程方式,可以帮助开发者更好地处理复杂的异步逻辑。

4. 设计模式

设计模式是一套被广泛接受的面向对象的设计原则,用于解决特定问题的最佳实践。在JavaScript中,常用的设计模式有单例模式、工厂模式、观察者模式、装饰器模式等。掌握这些设计模式,可以帮助开发者写出更加优雅、高效的代码。

5. 性能优化

JavaScript程序的性能优化是一项非常重要的任务。通过合理的算法设计、代码组织、资源管理等方式,可以显著提高JavaScript程序的运行效率。

JavaScript的函数有哪些高级特性

JavaScript的函数具有以下一些高级特性:

箭头函数:箭头函数是ES6引入的一种新的函数语法。它们更简洁,并且在处理多个返回值时更方便。箭头函数的语法如下:

(parameters) => { // code to be executed}

高阶函数:高阶函数是接受一个或多个函数作为参数,并返回一个新的函数的函数。它们在组合和抽象中非常有用。例如,map()、filter() 和 reduce() 等函数都是高阶函数的例子。

闭包:闭包是一种特殊的函数结构,它允许一个函数在其定义范围之外访问其父作用域的变量和函数。例如,你可以创建一个函数,该函数在其定义范围内定义一个局部变量,然后返回一个内部函数,该内部函数可以访问并修改这个局部变量。

函数表达式:除了函数声明外,JavaScript还支持函数表达式。函数表达式可以将函数赋值给变量,从而提供更大的灵活性。

函数柯里化:函数柯里化是一种特殊的技术,它将函数转化为一系列嵌套函数的形式。每个嵌套函数都只接受部分参数,并返回一个新的函数,等待接收剩余的参数。

函数的递归调用:函数可以调用自身,这种技术称为函数的递归调用。函数的递归调用在很多情况下都非常有用,例如计算斐波那契数列、遍历树形结构的数据等。

以上就是JavaScript的一些高级玩法,希望对你有所帮助。如果你想深入了解这些话题,可以阅读一些相关的书籍和教程,如《JavaScript高级教程》、《JavaScript权威指南》等。同时,多做一些实践项目,也是提升JavaScript编程能力的好方法。

习目标:了解JavaScript是如何与HTML结合来创建动态网页,网页中嵌入JavaScript的不同方式,JavaScript的内容类型及其与<script>的关系

<script>元素

<script>是由Netscape创造出来,后来加到HTML规范中的。

<script>有8个属性:

1、async:表示立即开始下载脚本,但不能阻止其他页面动作,比如下载资源或者等待其他脚本加载。只对外部脚本文件有效。

2、charset:使用src属性指定代码字符集。这个属性很少用,因为大多数浏览器不在乎它的值。

3、crossorigin;配置资源请求的CORS(跨源资源共享)设置。默认情况下不使用CORS。crossorigin = “anonymous”配置文件请求不用设置凭据标志。crossorigin = ”use-credentials“设置凭据标志,意味着出站请求会包含凭据。

4、defer:表示脚本可以延迟到文档全部解析和显示后再执行。新版本中只能用于外部脚本。

5、integrity:允许比对接收到的资源和指定的加密签名以验证子资源完整性(SRI,Subresource integrity),如果验证签名不匹配则脚本不会执行。这个属性可以用于确保内容分发网络(CDN,Content Delivery Network)不会提供恶意内容。

6、language:此属性已被废止。

7、src:表示包含外部要执行的代码的外部文件。

8、type:代替language,表示代码块中脚本语言的内容类型(也称为MIME类型),按照惯例这个值始终都是”text/JavaScript“,尽管”text/JavaScript“和”text/ecmascript“都已经废弃。JavaScript文件的MIME类型通常是”application/x-javascript“,不过给type属性这个值的话可能会导致脚本被忽略。在非IE的浏览器中有效的值还有”application/JavaScript“和”application/ecmascript"。如果这个值是module,则代码会被当成是ES6模块,而且只有这时候代码中才能出现import和export关键字。

使用<script>的方式有内联和外嵌两种,只要把code写入<script>code</script>中就好,code中要是包含字符串“<script>”,只要加上转义字符“\”即可。

如果要外嵌JavaScript代码只要使用src属性来链接外部文件即可如:

<script src=“example.js”></script>

XHTML 文档中,可以忽略结束标签写成<script src=“example.js”/>即可,但是这在HTML中不能使用。

标签位置

过去把JavaScript和CSS一起写在head中,但是这意味着必须下载所有code并解析和解释完成后才开始渲染页面,对于JavaScript很多的页面会导致页面渲染速度过慢,为解决这个问题,JavaScript一般写在body元素的页面内容的最后边,如下

<html>

<head></head>

<body>

message

<script>code<\script>

<\body>

</html>

推迟使用脚本

在外联JavaScript时可以使用defer属性来推迟脚本的运行。可以写成:

<html>

<head>

<script defer src = "example.js">code<\script>

</head>

<body>

message

<\body>

</html>

异步执行脚本

async属性从脚本处理方式上与defer类似,但是不同的是标记async的脚本并不能保证脚本按照他们的出现顺序执行,比如:

<html>

<head>

<script sync src = "example1.js">code<\script>

<script sync src = "example2.js">code<\script>

</head>

<body>

message

<\body>

</html>

不能保证example1比example2先执行。

动态加载脚本

除了<script>以外还可以用其他方式加载脚本。因为JavaScript可以使用DOM API,所以通过向DOM中动态地加入script元素同样可以加载指定脚本。只要创建一个script元素并将其添加到DOM即可。

let script = document.createElement('script');

script.src = 'gibberish.js';

document.head.appendChild(script);

当然,在把 HTMLElement 元素添加到 DOM 且执行到这段代码之前不会发送请求。默认情况下,以这种方式创建的<script>元素是以异步方式加载的,相当于添加了 async 属性。不过这样做可能会有问题,因为所有浏览器都支持 createElement()方法,但不是所有浏览器都支持 async 属性。因此,如果要统一动态脚本的加载行为,可以明确将其设置为同步加载:

let script = document.createElement('script');

script.src = 'gibberish.js';

script.async = false;

document.head.appendChild(script);

以这种方式获取的资源对浏览器预加载器是不可见的。这会严重影响它们在资源获取队列中的优先级。根据应用程序的工作方式以及怎么使用,这种方式可能会严重影响性能。要想让预加载器知道这些动态请求文件的存在,可以在文档头部显式声明它们:

<link rel="preload" href="gibberish.js">

XHTML中的变化

可扩展超文本标记语言(XHTML,Extensible HyperText Markup Language)是将 HTML 作为 XML的应用重新包装的结果。与 HTML 不同,在 XHTML 中使用 JavaScript 必须指定 type 属性且值为text/javascript,HTML 中则可以没有这个属性。XHTML 虽然已经退出历史舞台,但实践中偶尔可能也会遇到遗留代码,为此本节稍作介绍。在 XHTML 中编写代码的规则比 HTML 中严格,这会影响使用<script>元素嵌入 JavaScript 代码。下面的代码块虽然在 HTML 中有效,但在 XHML 中是无效的。

<script type="text/javascript">

function compare(a, b) {

if (a < b) {

console.log("A is less than B");

} else if (a > b) {

console.log("A is greater than B");

} else {

console.log("A is equal to B");

}

}

</script>

在 HTML 中,解析<script>元素会应用特殊规则。XHTML 中则没有这些规则。这意味着 a < b语句中的小于号(<)会被解释成一个标签的开始,并且由于作为标签开始的小于号后面不能有空格,这会导致语法错误。避免 XHTML 中这种语法错误的方法有两种。第一种是把所有小于号(<)都替换成对应的 HTML实体形式(<)。结果代码就是这样的:

<script type="text/javascript">

function compare(a, b) {

if (a < b) {

console.log("A is less than B");

} else if (a > b) {

console.log("A is greater than B");

} else {

console.log("A is equal to B");

}

}

</script>

这样代码就可以在 XHTML 页面中运行了。不过,缺点是会影响阅读。好在还有另一种方法。第二种方法是把所有代码都包含到一个 CDATA 块中。在 XHTML(及 XML)中,CDATA 块表示文档中可以包含任意文本的区块,其内容不作为标签来解析,因此可以在其中包含任意字符,包括小于号,并且不会引发语法错误。使用 CDATA 的格式如下:

<script type="text/javascript"><![CDATA[

function compare(a, b) {

if (a < b) {

console.log("A is less than B");

} else if (a > b) {

console.log("A is greater than B");

} else {

console.log("A is equal to B");

}

}

]]></script>

在兼容 XHTML 的浏览器中,这样能解决问题。但在不支持 CDATA 块的非 XHTML 兼容浏览器中则不行。为此,CDATA 标记必须使用 JavaScript 注释来抵消:

<script type="text/javascript">

//<![CDATA[

function compare(a, b) {

if (a < b) {

console.log("A is less than B");

} else if (a > b) {

console.log("A is greater than B");

} else {

console.log("A is equal to B");

}

}

//]]>

</script>

这种格式适用于所有现代浏览器。虽然有点黑科技的味道,但它可以通过 XHTML 验证,而且对XHTML 之前的浏览器也能优雅地降级。

废弃的语法

自 1995 年 Netscape 2 发布以来,所有浏览器都将 JavaScript 作为默认的编程语言。type 属性使用一个 MIME 类型字符串来标识<script>的内容,但 MIME 类型并没有跨浏览器标准化。即使浏览器默认使用 JavaScript,在某些情况下某个无效或无法识别的 MIME 类型也可能导致浏览器跳过(不执行)相关代码。因此,除非你使用 XHTML 或<script>标签要求或包含非 JavaScript 代码,最佳做法是不指定 type 属性。在最初采用 script 元素时,它标志着开始走向与传统 HTML 解析不同的流程。对这个元素需要应用特殊的解析规则,而这在不支持 JavaScript 的浏览器(特别是 Mosaic)中会导致问题。不支持的浏览器会把<script>元素的内容输出到页面上,从而破坏页面的外观。Netscape 联合 Mosaic 拿出了一个解决方案,对不支持 JavaScript 的浏览器隐藏嵌入的 JavaScript 代码。最终方案是把脚本代码包含在一个 HTML 注释中,像这样:

<script><!--

function sayHi(){

console.log("Hi!");

}

//--></script>

使用这种格式,Mosaic 等浏览器就可以忽略<script>标签中的内容,而支持 JavaScript 的浏览器则必须识别这种模式,将其中的内容作为 JavaScript 来解析。虽然这种格式仍然可以被所有浏览器识别和解析,但已经不再必要,而且不应该再使用了。在XHTML 模式下,这种格式也会导致脚本被忽略,因为代码处于有效的 XML 注释当中。

行内代码与外部文件

虽然可以直接在 HTML 文件中嵌入 JavaScript 代码,但通常认为最佳实践是尽可能将 JavaScript 代码放在外部文件中。不过这个最佳实践并不是明确的强制性规则。推荐使用外部文件的理由如下。

 可维护性。JavaScript 代码如果分散到很多 HTML 页面,会导致维护困难。而用一个目录保存所有 JavaScript 文件,则更容易维护,这样开发者就可以独立于使用它们的 HTML 页面来编辑代码。

 缓存。浏览器会根据特定的设置缓存所有外部链接的 JavaScript 文件,这意味着如果两个页面都用到同一个文件,则该文件只需下载一次。这最终意味着页面加载更快。

 适应未来。通过把 JavaScript 放到外部文件中,就不必考虑用 XHTML 或前面提到的注释黑科技。包含外部 JavaScript 文件的语法在 HTML 和 XHTML 中是一样的。在配置浏览器请求外部文件时,要重点考虑的一点是它们会占用多少带宽。在 SPDY/HTTP2 中,预请求的消耗已显著降低,以轻量、独立 JavaScript 组件形式向客户端送达脚本更具优势。比如,第一个页面包含如下脚本:

<script src="mainA.js"></script>

<script src="component1.js"></script>

<script src="component2.js"></script>

<script src="component3.js"></script>

...

后续页面可能包含如下脚本:

<script src="mainB.js"></script>

<script src="component3.js"></script>

<script src="component4.js"></script>

<script src="component5.js"></script>

...

在初次请求时,如果浏览器支持 SPDY/HTTP2,就可以从同一个地方取得一批文件,并将它们逐个放到浏览器缓存中。从浏览器角度看,通过 SPDY/HTTP2 获取所有这些独立的资源与获取一个大JavaScript 文件的延迟差不多。在第二个页面请求时,由于你已经把应用程序切割成了轻量可缓存的文件,第二个页面也依赖的某些组件此时已经存在于浏览器缓存中了。当然,这里假设浏览器支持 SPDY/HTTP2,只有比较新的浏览器才满足。如果你还想支持那些比较老的浏览器,可能还是用一个大文件更合适。

文档模式

IE5.5 发明了文档模式的概念,即可以使用 doctype 切换文档模式。最初的文档模式有两种:混杂模式(quirks mode)和标准模式(standards mode)。前者让 IE 像 IE5 一样(支持一些非标准的特性),后者让 IE 具有兼容标准的行为。虽然这两种模式的主要区别只体现在通过 CSS 渲染的内容方面,但对JavaScript 也有一些关联影响,或称为副作用。本书会经常提到这些副作用。

IE 初次支持文档模式切换以后,其他浏览器也跟着实现了。随着浏览器的普遍实现,又出现了第三种文档模式:准标准模式(almost standards mode)。这种模式下的浏览器支持很多标准的特性,但是没有标准规定得那么严格。主要区别在于如何对待图片元素周围的空白(在表格中使用图片时最明显)。

混杂模式在所有浏览器中都以省略文档开头的 doctype 声明作为开关。这种约定并不合理,因为混杂模式在不同浏览器中的差异非常大,不使用黑科技基本上就没有浏览器一致性可言。标准模式通过下列几种文档类型声明开启:

<!-- HTML 4.01 Strict -->

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"

"http://www.w3.org/TR/html4/strict.dtd">

<!-- XHTML 1.0 Strict -->

<!DOCTYPE html PUBLIC

"-//W3C//DTD XHTML 1.0 Strict//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<!-- HTML5 -->

<!DOCTYPE html>

准标准模式通过过渡性文档类型(Transitional)和框架集文档类型(Frameset)来触发:

<!-- HTML 4.01 Transitional -->

<!DOCTYPE HTML PUBLIC

"-//W3C//DTD HTML 4.01 Transitional//EN"

"http://www.w3.org/TR/html4/loose.dtd">

<!-- HTML 4.01 Frameset -->

<!DOCTYPE HTML PUBLIC

"-//W3C//DTD HTML 4.01 Frameset//EN"

"http://www.w3.org/TR/html4/frameset.dtd">

<!-- XHTML 1.0 Transitional -->

<!DOCTYPE html PUBLIC

"-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<!-- XHTML 1.0 Frameset -->

<!DOCTYPE html PUBLIC

"-//W3C//DTD XHTML 1.0 Frameset//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">

准标准模式与标准模式非常接近,很少需要区分。人们在说到“标准模式”时,可能指其中任何一个。而对文档模式的检测(本书后面会讨论)也不会区分它们。本书后面所说的标准模式,指的就是除混杂模式以外的模式。

<noscript>元素

针对早期浏览器不支持 JavaScript 的问题,需要一个页面优雅降级的处理方案。最终,<noscript>元素出现,被用于给不支持 JavaScript 的浏览器提供替代内容。虽然如今的浏览器已经 100%支持JavaScript,但对于禁用 JavaScript 的浏览器来说,这个元素仍然有它的用处。<noscript>元素可以包含任何可以出现在<body>中的 HTML 元素,<script>除外。在下列两种情况下,浏览器将显示包含在<noscript>中的内容:

 浏览器不支持脚本;

 浏览器对脚本的支持被关闭。任何一个条件被满足,包含在<noscript>中的内容就会被渲染。否则,浏览器不会渲染<noscript>中的内容。

下面是一个例子:

<!DOCTYPE html>

<html>

<head>

<title>Example HTML Page</title>

<script defer="defer" src="example1.js"></script>

<script defer="defer" src="example2.js"></script>

</head>

<body>

<noscript>

<p>This page requires a JavaScript-enabled browser.</p>

</noscript>

</body>

</html>

这个例子是在脚本不可用时让浏览器显示一段话。如果浏览器支持脚本,则用户永远不会看到它。

小结

JavaScript 是通过<script>元素插入到 HTML 页面中的。这个元素可用于把 JavaScript 代码嵌入到HTML 页面中,跟其他标记混合在一起,也可用于引入保存在外部文件中的 JavaScript。本章的重点可以总结如下。

 要包含外部 JavaScript 文件,必须将 src 属性设置为要包含文件的 URL。文件可以跟网页在同一台服务器上,也可以位于完全不同的域。

 所有<script>元素会依照它们在网页中出现的次序被解释。在不使用 defer 和 async 属性的情况下,包含在<script>元素中的代码必须严格按次序解释。

 对不推迟执行的脚本,浏览器必须解释完位于<script>元素中的代码,然后才能继续渲染页面的剩余部分。为此,通常应该把<script>元素放到页面末尾,介于主内容之后及</body>标签之前。

 可以使用 defer 属性把脚本推迟到文档渲染完毕后再执行。推迟的脚本原则上按照它们被列出的次序执行。

 可以使用 async 属性表示脚本不需要等待其他脚本,同时也不阻塞文档渲染,即异步加载。异步脚本不能保证按照它们在页面中出现的次序执行。

 通过使用<noscript>元素,可以指定在浏览器不支持脚本时显示的内容。如果浏览器支持并启用脚本,则<noscript>元素中的任何内容都不会被渲染。