-
2021-06-04 08:00:48
目录
#SPL基本使用
#示例
如何将 json 文件中的数据以二维表形式保存到 csv 文件
怎么用Java读txt文件,根据其中的条件,输出一个csv文件
http://c.raqsoft.com.cn/article/1557735569563
http://c.raqsoft.com.cn/article/1557735385195
http://c.raqsoft.com.cn/article/1562548410162
http://c.raqsoft.com.cn/article/1562309644899
http://c.raqsoft.com.cn/article/1562030831309
http://c.raqsoft.com.cn/article/1561347398311
http://c.raqsoft.com.cn/article/1561346789061
http://c.raqsoft.com.cn/article/1561342831552
http://c.raqsoft.com.cn/article/1561342515672
http://c.raqsoft.com.cn/article/1561342268127
http://c.raqsoft.com.cn/article/1560930483934
http://c.raqsoft.com.cn/article/1560929916140
http://c.raqsoft.com.cn/article/1560821489186
http://c.raqsoft.com.cn/article/1560821130235
http://c.raqsoft.com.cn/article/1560513336852
http://c.raqsoft.com.cn/article/1560513030892
http://c.raqsoft.com.cn/article/1560333686767
http://c.raqsoft.com.cn/article/1560157346514
http://c.raqsoft.com.cn/article/1560155494531
http://c.raqsoft.com.cn/article/1560155198118
http://c.raqsoft.com.cn/article/1560150403616
http://c.raqsoft.com.cn/article/1560136525981
http://c.raqsoft.com.cn/article/1560136198453
http://c.raqsoft.com.cn/article/1560135147191
http://c.raqsoft.com.cn/article/1560134906319
http://c.raqsoft.com.cn/article/1560134625011
http://c.raqsoft.com.cn/article/1560134492293
http://c.raqsoft.com.cn/article/1564993615927
http://c.raqsoft.com.cn/article/1564715970872
http://c.raqsoft.com.cn/article/1564715777915
http://c.raqsoft.com.cn/article/1564715556679
http://c.raqsoft.com.cn/article/1564536674798
http://c.raqsoft.com.cn/article/1564536500811
http://c.raqsoft.com.cn/article/1564536368392
http://c.raqsoft.com.cn/article/1564401373191
http://c.raqsoft.com.cn/article/1564401293438
http://c.raqsoft.com.cn/article/1564401231068
http://c.raqsoft.com.cn/article/1564390841545
http://c.raqsoft.com.cn/article/1564390013298
http://c.raqsoft.com.cn/article/1564140882710
http://c.raqsoft.com.cn/article/1564140190710
http://c.raqsoft.com.cn/article/1564019567072
http://c.raqsoft.com.cn/article/1564019484302
http://c.raqsoft.com.cn/article/1564019293282
http://c.raqsoft.com.cn/article/1563933451677
http://c.raqsoft.com.cn/article/1563525223358
http://c.raqsoft.com.cn/article/1563524877754
http://c.raqsoft.com.cn/article/1563288925569
http://c.raqsoft.com.cn/article/1562814836756
http://c.raqsoft.com.cn/article/1562814541326
http://c.raqsoft.com.cn/article/1562814231763
http://c.raqsoft.com.cn/article/1562721972652
http://c.raqsoft.com.cn/article/1567166971621
http://c.raqsoft.com.cn/article/1567166725899
http://c.raqsoft.com.cn/article/1567166530024
http://c.raqsoft.com.cn/article/1566890371878
http://c.raqsoft.com.cn/article/1566890007993
http://c.raqsoft.com.cn/article/1566889711204
http://c.raqsoft.com.cn/article/1566528409541
http://c.raqsoft.com.cn/article/1566525290036
http://c.raqsoft.com.cn/article/1566266428862
http://c.raqsoft.com.cn/article/1566139113019
http://c.raqsoft.com.cn/article/1566138829990
http://c.raqsoft.com.cn/article/1565937964500
http://c.raqsoft.com.cn/article/1565937330320
http://c.raqsoft.com.cn/article/1565935223588
http://c.raqsoft.com.cn/article/1565935007017
http://c.raqsoft.com.cn/article/1565767893909
http://c.raqsoft.com.cn/article/1565682198743
http://c.raqsoft.com.cn/article/1565681738323
http://c.raqsoft.com.cn/article/1565317484857
http://c.raqsoft.com.cn/article/1565315916461
http://c.raqsoft.com.cn/article/1565056195085
http://c.raqsoft.com.cn/article/1565056082306
http://c.raqsoft.com.cn/article/1565055879976
http://c.raqsoft.com.cn/article/1565001930933
http://c.raqsoft.com.cn/article/1565001665970
http://c.raqsoft.com.cn/article/1568968423997
http://c.raqsoft.com.cn/article/1568968283557
http://c.raqsoft.com.cn/article/1568729522057
http://c.raqsoft.com.cn/article/1568729349360
http://c.raqsoft.com.cn/article/1568729118292
http://c.raqsoft.com.cn/article/1568622090265
http://c.raqsoft.com.cn/article/1568621660089
http://c.raqsoft.com.cn/article/1568601654858
http://c.raqsoft.com.cn/article/1568601535601
http://c.raqsoft.com.cn/article/1568600091325
http://c.raqsoft.com.cn/article/1568269258307
http://c.raqsoft.com.cn/article/1568269036272
http://c.raqsoft.com.cn/article/1568268820851
http://c.raqsoft.com.cn/article/1568078956052
http://c.raqsoft.com.cn/article/1568078265556
http://c.raqsoft.com.cn/article/1568025499093
http://c.raqsoft.com.cn/article/1568023652824
http://c.raqsoft.com.cn/article/1568023516939
http://c.raqsoft.com.cn/article/1567990279614
http://c.raqsoft.com.cn/article/1567417313027
http://c.raqsoft.com.cn/article/1567417094820
http://c.raqsoft.com.cn/article/1567408011949
http://c.raqsoft.com.cn/article/1567407851920
http://c.raqsoft.com.cn/article/1567407775685
http://c.raqsoft.com.cn/article/1567407409760
http://c.raqsoft.com.cn/article/1572245777329
http://c.raqsoft.com.cn/article/1572229747334
http://c.raqsoft.com.cn/article/1572224318205
http://c.raqsoft.com.cn/article/1572224043332
http://c.raqsoft.com.cn/article/1572223493703
http://c.raqsoft.com.cn/article/1572059735385
http://c.raqsoft.com.cn/article/1572059629209
http://c.raqsoft.com.cn/article/1572059522701
http://c.raqsoft.com.cn/article/1571621533070
http://c.raqsoft.com.cn/article/1571415567630
http://c.raqsoft.com.cn/article/1571413192335
http://c.raqsoft.com.cn/article/1571412914244
http://c.raqsoft.com.cn/article/1570071116634
http://c.raqsoft.com.cn/article/1570070716265
http://c.raqsoft.com.cn/article/1569832236141
http://c.raqsoft.com.cn/article/1569830011356
http://c.raqsoft.com.cn/article/1569826944317
http://c.raqsoft.com.cn/article/1569826566304
http://c.raqsoft.com.cn/article/1569483465631
http://c.raqsoft.com.cn/article/1569226651070
http://c.raqsoft.com.cn/article/1569226237489
http://c.raqsoft.com.cn/article/1569225805811
http://c.raqsoft.com.cn/article/1569225331867
http://c.raqsoft.com.cn/article/1568974953282
http://c.raqsoft.com.cn/article/1568968677562
http://c.raqsoft.com.cn/article/1575508917735
http://c.raqsoft.com.cn/article/1575451992198
http://c.raqsoft.com.cn/article/1575275504818
http://c.raqsoft.com.cn/article/1575275027976
http://c.raqsoft.com.cn/article/1574932142217
http://c.raqsoft.com.cn/article/1574932039458
http://c.raqsoft.com.cn/article/1574930390147
http://c.raqsoft.com.cn/article/1574930293585
http://c.raqsoft.com.cn/article/1574930114651
http://c.raqsoft.com.cn/article/1574404592581
http://c.raqsoft.com.cn/article/1574404252262
http://c.raqsoft.com.cn/article/1574404094641
http://c.raqsoft.com.cn/article/1574404021600
http://c.raqsoft.com.cn/article/1573701957387
http://c.raqsoft.com.cn/article/1573701652568
http://c.raqsoft.com.cn/article/1572926052851
http://c.raqsoft.com.cn/article/1572925467813
http://c.raqsoft.com.cn/article/1572602361726
http://c.raqsoft.com.cn/article/1572587936848
http://c.raqsoft.com.cn/article/1572568736107
http://c.raqsoft.com.cn/article/1572568602961
http://c.raqsoft.com.cn/article/1572485218698
http://c.raqsoft.com.cn/article/1572484957711
http://c.raqsoft.com.cn/article/1572248236424
http://c.raqsoft.com.cn/article/1572247891400
http://c.raqsoft.com.cn/article/1579225278725
http://c.raqsoft.com.cn/article/1579225071033
http://c.raqsoft.com.cn/article/1579224792001
http://c.raqsoft.com.cn/article/1579224636496
http://c.raqsoft.com.cn/article/1578382251618
http://c.raqsoft.com.cn/article/1578382152533
http://c.raqsoft.com.cn/article/1578382058204
http://c.raqsoft.com.cn/article/1578381485451
http://c.raqsoft.com.cn/article/1577720395024
http://c.raqsoft.com.cn/article/1577719988997
http://c.raqsoft.com.cn/article/1576562814244
http://c.raqsoft.com.cn/article/1576225048795
http://c.raqsoft.com.cn/article/1576048895157
http://c.raqsoft.com.cn/article/1575879781503
#SPL CookBook
更多相关内容 -
excel中实现多条件去重计数
2021-12-23 17:57:38这次我们来介绍怎么在excel中实现多条件去重计数。...如图,先用FILTER查询在A2:A11中符合在B2:B11中等于B2的单元格,C2:C11中等于C3的单元格,接着用UNIQUE函数去重,最后用COUNTA函数计算符合条件的单元格。 ...这次我们来介绍怎么在excel中实现多条件去重计数。
背景:我们需要计算出编号中为1,且时间中为2021年10月29日的配送中心有几个,抽象地来说我们需要对符合上述两个条件的配送中心进行计数。
用到的函数有:
1.COUNTA()
即计算范围内的非空单元格数
2.UNIQUE()
计算范围内去重后的数组
3.FILTER()
返回多条件查询后匹配的数组。
如图,
1.先用FILTER查询在A2:A11中符合在B2:B11中等于B2的单元格,C2:C11中等于C3的单元格。(多对一查询)
2.接着用UNIQUE函数去重。(查询到的数组进行去重)
3.最后用COUNTA函数计算符合条件的单元格。(数组计数)
-
一个合格的中级前端工程师需要掌握的技能笔记(上)
2021-05-30 00:43:27go"> id="file" max="100" value="70"> 70% </progress> </code></pre> <p>output标签</p> 表示计算或用户操作的结果。</p> <p>nav元素</p> 表示页面的一部分,其目的是在当前文档或其他文档中提供导航链接</p>...Github来源:一个合格的中级前端工程师需要掌握的技能 | 求星星 ✨ | 给个❤️关注,❤️点赞,❤️鼓励一下作者
大家好,我是魔王哪吒,很高兴认识你~~
哪吒人生信条:如果你所学的东西 处于喜欢 才会有强大的动力支撑。
每天学习编程,让你离梦想更新一步,感谢不负每一份热爱编程的程序员,不论知识点多么奇葩,和我一起,让那一颗四处流荡的心定下来,一直走下去,加油,
2021
加油!欢迎关注加我vx:xiaoda0423
,欢迎点赞、收藏和评论不要害怕做梦,但是呢,也不要光做梦,要做一个实干家,而不是空谈家,求真力行。
前言
如果这篇文章有帮助到你,给个❤️关注,❤️点赞,❤️鼓励一下作者,接收好挑战了吗?文章公众号首发,关注 程序员哆啦A梦 第一时间获取最新的文章
❤️笔芯❤️~
已阅:
ES6 系列之 let 和 const
ES6 系列之模板字符串
ES6 系列之箭头函数
ES6 系列之模拟实现 Symbol 类型
ES6 系列之迭代器与 for of
ES6 系列之模拟实现一个 Set 数据结构
ES6 系列之 WeakMap
ES6 系列之我们来聊聊 Promise
ES6 完全使用手册
ES6 系列之 defineProperty 与 proxy
ES6 系列之模块加载方案
ES6 系列之私有变量的实现
前端,校招,面淘宝,指南
前端,社招,面淘宝,指南
你累死累活做业务,绩效还不怎么样,我只能帮你到这了……
淘系前端校招负责人直播答疑文字实录
致2021届前端同学的一封信|砥砺前行,未来可期!
面试被问项目经验不用慌,按这个步骤回答绝对惊艳
项目不知道如何做性能优化?不妨试一下代码分割
HTML模块
HTML 标记包含一些特殊“元素”如 :
<head>,<title>,<body>,<header>,<footer>,<article>,<p>,<p>,<div>,<span>,<img>,<aside>,<audio>,<canvas>,<datalist>,<details>,<embed>,<nav>,<output>,<progress>,<video>
article元素
表示文档、页面、应用或网站中的独立结构,其意在成为可独立分配的或可复用的结构,如在发布中,它可能是论坛帖子、杂志或新闻文章、博客、用户提交的评论、交互式组件,或者其他独立的内容项目。
p元素
表示一个包含在HTML文档中的独立部分,它没有更具体的语义元素来表示,一般来说会有包含一个标题。
aside元素
表示一个和其余页面内容几乎无关的部分,被认为是独立于该内容的一部分并且可以被单独的拆分出来而不会使整体受影响。
audio元素
用于在文档中嵌入音频内容。
<audio controls src="/zzz.mp3"> dada <code>audio</code> . </audio>
canvas元素
用来通过JavaScript(Canvas API 或 WebGL API)绘制图形及图形动画。
<canvas id="canvas" width="300" height="300"></canvas> var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); ctx.fillStyle = 'green'; ctx.fillRect(10, 10, 100, 100);
datalist元素
包含了一组
<option>
元素,这些元素表示其它表单控件可选值.<input list="browsers" name="myBrowser" /></label> <datalist id="browsers"> <option value="Chrome"> <option value="Firefox"> <option value="Internet Explorer"> <option value="Opera"> <option value="Safari"> </datalist>
details元素
可创建一个挂件,仅在被切换成展开状态时,它才会显示内含的信息。
<summary>
元素可为该部件提供概要或者标签。
System Requirements<details> <summary>System Requirements</summary> <p>Requires a computer running an operating system. The computer must have some memory and ideally some kind of long-term storage. An input device as well as some form of output device is recommended.</p> </details>
Requires a computer running an operating system. The computer must have some memory and ideally some kind of long-term storage. An input device as well as some form of output device is recommended.
embed元素
外部内容嵌入元素
progress元素
用来显示一项任务的完成进度
<progress id="file" max="100" value="70"> 70% </progress>
output标签
表示计算或用户操作的结果。
nav元素
表示页面的一部分,其目的是在当前文档或其他文档中提供导航链接
表单小部件:
<form action="/my-handling-form-page" method="post"> <div> <label for="name">Name:</label> <input type="text" id="name"> </div> <div> <label for="mail">E-mail:</label> <input type="email" id="mail"> </div> <div> <label for="msg">Message:</label> <textarea id="msg"></textarea> </div> </form>
单行文本框
<input type="text" id="comment" name="comment" value="I'm a text field">
E-mail 地址框
<input type="email" id="email" name="email" multiple>
密码框
<input type="password" id="pwd" name="pwd">
搜索框
<input type="search" id="search" name="search">
电话号码栏:
<input type="tel" id="tel" name="tel">
URL 栏:
<input type="url" id="url" name="url">
多行文本框:
<textarea cols="30" rows="10"></textarea>
复选框:
<input type="checkbox" checked id="carrots" name="carrots" value="carrots">
单选按钮:
<input type="radio" checked id="soup" name="meal">
数字:
<input type="number" name="age" id="age" min="1" max="10" step="2">
滑块:
<input type="range" name="beans" id="beans" min="0" max="500" step="10">
日期时间选择器:
<input type="datetime-local" name="datetime" id="datetime"> <input type="month" name="month" id="month"> <input type="time" name="time" id="time"> <input type="week" name="week" id="week">
拾色器:
<input type="color" name="color" id="color">
文件选择器:
<input type="file" name="file" id="file" accept="image/*" multiple>
隐藏内容:
<input type="hidden" id="timestamp" name="timestamp" value="6354561">
发送表单数据
客户端/服务器体系结构
客户端(通常是web浏览器)向服务器发送请求(大多数情况下是Apache、Nginx、IIS、Tomcat等web服务器),使用HTTP 协议。
在客户端:定义如何发送数据:
action 属性-这个属性定义了发送数据要去的位置。
method属性-该属性定义了如何发送数据。
什么是表单数据校验?
访问任何一个带注册表单的网站,你都会发现,当你提交了没有输入符合预期格式的信息的表单时,注册页面都会给你一个反馈。
“该字段是必填的”(该字段不能留空)
请输入你的电话号码
请输入一个合法的邮箱地址
使用正则表达式校验
示例:
a — 匹配一个字符a(不能匹配 b, aa等等.) abc — 匹配 a, 其次 b, 最后 c. a* — 匹配0个或者多个字符 a (+ 代表至少匹配一个或者多个). [^a] — 匹配一个字符,但它不能是a. a|b — 匹配一个字符 a 或者 b. [abc] — 匹配一个字符,它可以是a,b或c. [^abc] — 匹配一个字符,但它不可以是a,b或c. [a-z] — 匹配字符范围 a-z且全部小写 (你可以使用 [A-Za-z] 涵盖大小写, 或 [A-Z] 来限制必须大写). a.c — 匹配字符 a,中间匹配任意一个字符,最后匹配字符 c. a{5} — 匹配字符 a五次. a{5,7} — 匹配字符 a五到七次,不能多或者少.
AJAX 技术主要依靠 XMLHttpRequest (XHR) DOM 对象。它可以构造 HTTP 请求、发送它们,并获取请求结果。
表单数据(
application/x-www-form-urlencoded
)由 URL编码的键/值对列表组成。为了传输二进制数据,HTTP请求被重新整合成multipart/form-data
形式。构建
XMLHttpRequest
:XMLHttpRequest
是进行 HTTP 请求的最安全和最可靠的方式。示例:
function sendData(data) { var XHR = new XMLHttpRequest(); var urlEncodedData = ""; var urlEncodedDataPairs = []; var name; // 将数据对象转换为URL编码的键/值对数组。 for(name in data) { urlEncodedDataPairs.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[name])); } // 将配对合并为单个字符串,并将所有%编码的空格替换为 // “+”字符;匹配浏览器表单提交的行为。 urlEncodedData = urlEncodedDataPairs.join('&').replace(/%20/g, '+'); // 定义成功数据提交时发生的情况 XHR.addEventListener('load', function(event) { alert('耶! 已发送数据并加载响应。'); }); // 定义错误提示 XHR.addEventListener('error', function(event) { alert('哎呀!出问题了。'); }); // 建立我们的请求 XHR.open('POST', 'https://example.com/cors.php'); // 为表单数据POST请求添加所需的HTTP头 XHR.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); // 最后,发送我们的数据。 XHR.send(urlEncodedData); }
利用FormData对象来处理表单数据请求。
示例:
function sendData(data) { var XHR = new XMLHttpRequest(); var FD = new FormData(); // 把我们的数据添加到这个FormData对象中 for(name in data) { FD.append(name, data[name]); } // 定义数据成功发送并返回后执行的操作 XHR.addEventListener('load', function(event) { alert('Yeah! 已发送数据并加载响应。'); }); // 定义发生错误时执行的操作 XHR.addEventListener('error', function(event) { alert('Oops! 出错了。'); }); // 设置请求地址和方法 XHR.open('POST', 'https://example.com/cors.php'); // 发送这个formData对象,HTTP请求头会自动设置 XHR.send(FD); }
使用绑定到表单元素上的 FormData
<form id="myForm"> <label for="myName">告诉我你的名字:</label> <input id="myName" name="name" value="John"> <input type="submit" value="提交"> </form>
示例:
window.addEventListener("load", function () { function sendData() { var XHR = new XMLHttpRequest(); // 我们把这个 FormData 和表单元素绑定在一起。 var FD = new FormData(form); // 我们定义了数据成功发送时会发生的事。 XHR.addEventListener("load", function(event) { alert(event.target.responseText); }); // 我们定义了失败的情形下会发生的事 XHR.addEventListener("error", function(event) { alert('哎呀!出了一些问题。'); }); // 我们设置了我们的请求 XHR.open("POST", "https://example.com/cors.php"); // 发送的数据是由用户在表单中提供的 XHR.send(FD); } // 我们需要获取表单元素 var form = document.getElementById("myForm"); // ...然后接管表单的提交事件 form.addEventListener("submit", function (event) { event.preventDefault(); sendData(); }); });
CORS
处理跨域图片通过搭配
crossorigin
属性和适当的CORS
标头,在<img>
元素中定义的图片可以从外部来源加载并在<canvas>
元素中使用,就像是从本地源加载一样。启用了
CORS
的图片尽管不通过 CORS 就可以在
<canvas>
中使用其他来源的图片,但是这会污染画布,并且不再认为是安全的画布,这将可能在<canvas>
检索数据过程中引发异常。在"被污染"的画布中调用以下方法:
在
<canvas>
的上下文上调用getImageData()
在
<canvas>
上调用toBlob()
在
<canvas>
上调用toDataURL()
CORS
设置属性一些提供了对
CORS
的支持的HTML
元素,比如<img>
或<video>
,具有crossorigin
元素属性/attribute
(crossOrigin
对象属性/property
),该属性能使你配置其跨域获取资源的请求。CanvasRenderingContext2D.getImageData()
CanvasRenderingContext2D.getImageData()
返回一个ImageData
对象,用来描述canvas
区域隐含的像素数据,这个区域通过矩形表示,起始点为(sx, sy)、宽为sw、高为sh
。语法
ImageData ctx.getImageData(sx, sy, sw, sh); sx 将要被提取的图像数据矩形区域的左上角 x 坐标。 sy 将要被提取的图像数据矩形区域的左上角 y 坐标。 sw 将要被提取的图像数据矩形区域的宽度。 sh 将要被提取的图像数据矩形区域的高度。 返回值 一个ImageData 对象,包含canvas给定的矩形图像数据。
使用 getImageData 方法:
<canvas id="canvas"></canvas> var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.rect(10, 10, 100, 100); ctx.fill(); console.log(ctx.getImageData(50, 50, 100, 100)); // ImageData { width: 100, height: 100, data: Uint8ClampedArray[40000] } 返回值 一个ImageData 对象,包含canvas给定的矩形图像数据。
HTMLCanvasElement.toBlob()
HTMLCanvasElement.toBlob()
方法创造Blob
对象,用以展示canvas
上的图片;这个图片文件可以被缓存或保存到本地,由用户代理端自行决定。如不特别指明,图片的类型默认为image/png
,分辨率为96dpi
。语法
canvas.toBlob(callback, type, encoderOptions); callback 回调函数,可获得一个单独的Blob对象参数。 type 可选 DOMString类型,指定图片格式,默认格式为image/png。 encoderOptions 可选 Number类型,值在0与1之间,当请求图片格式为image/jpeg或者image/webp时用来指定图片展示质量。如果这个参数的值不在指定类型与范围之内,则使用默认值,其余参数将被忽略。 返回值 无。
HTMLCanvasElement.toDataURL()
HTMLCanvasElement.toDataURL()
方法返回一个包含图片展示的data URI
。可以使用type
参数其类型,默认为PNG
格式。图片的分辨率为96dpi
。如果画布的高度或宽度是0,那么会返回字符串“
data:,
”。如果传入的类型非“
image/png
”,但是返回的值以“data:image/png”
开头,那么该传入的类型是不支持的。Chrome支持“
image/webp
”类型。
语法
canvas.toDataURL(type, encoderOptions); type 可选 图片格式,默认为 image/png encoderOptions 可选 在指定图片格式为 image/jpeg 或 image/webp的情况下,可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,将会使用默认值 0.92。其他参数会被忽略。 返回值 包含 data URI 的DOMString。
示例:
<canvas id="canvas" width="5" height="5"></canvas> var canvas = document.getElementById("canvas"); var dataURL = canvas.toDataURL(); console.log(dataURL); // "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNby // blAAAADElEQVQImWNgoBMAAABpAAFEI8ARAAAAAElFTkSuQmCC"
设置图片的质量:
var fullQuality = canvas.toDataURL("image/jpeg", 1.0); // data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...9oADAMBAAIRAxEAPwD/AD/6AP/Z" var mediumQuality = canvas.toDataURL("image/jpeg", 0.5); var lowQuality = canvas.toDataURL("image/jpeg", 0.1);
允许浏览器在下载图像数据时允许跨域访问请求
用户点击 "Download" 按钮时开始下载:
function startDownload() { let imageURL = "https://xxxx"; downloadedImg = new Image; downloadedImg.crossOrigin = "Anonymous"; downloadedImg.addEventListener("load", imageReceived, false); downloadedImg.src = imageURL; }
canvas
的toDataURL()
方法用于将图像转换为data:// URL
形式的PNG
格式图片通过
rel="preload"
进行内容预加载<link>
标签最常见的应用情形就是被用来加载CSS
文件,进而装饰你的页面:<link rel="stylesheet" href="styles/main.css"> <link rel="preload" href="style.css" as="style"> <link rel="preload" href="main.js" as="script">
哪些类型的内容可以被预加载?
audio: 音频文件。 document: 一个将要被嵌入到<frame>或<iframe>内部的HTML文档。 embed: 一个将要被嵌入到<embed>元素内部的资源。 fetch: 那些将要通过fetch和XHR请求来获取的资源,比如一个ArrayBuffer或JSON文件。 font: 字体文件。 image: 图片文件。 object: 一个将会被嵌入到<embed>元素内的文件。 script: JavaScript文件。 style: 样式表。 track: WebVTT文件。 worker: 一个JavaScript的web worker或shared worker。 video: 视频文件。
如何制作快速加载的HTML页面
减小页面的大小。
最小化文件数量:减少一个页面引用的文件数量可以降低在下载一个页面的过程中需要的HTTP请求数量,从而减少这些请求的收发时间。
使用 CDN。
减少域名查找:每个独立的域名都会消耗DNS查找的时间,页面加载时间会随着独立域名数量、CSS链接数量、JavaScript还有图片资源的数量增加而增加。
缓存重用的内容:确保任何内容可以被缓存,并且拥有一个合理的有效期。
高效地排列页面组件。
减少内联脚本的数量。
网页中添加矢量图形
image.png 示例:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vector versus raster</title> </head> <body> <h1>Vector versus raster</h1> <img src="star.png" alt="A raster star"> <img src="star.svg" alt="A vector star"> </body> </html>
创建一个圆和一个矩形:
image.png <svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg"> <rect width="100%" height="100%" fill="black" /> <circle cx="150" cy="100" r="90" fill="blue" /> </svg>
示例:
<img src="equilateral.svg" alt="triangle with all three sides equal" height="87px" width="100px" />
<svg width="300" height="200"> <rect width="100%" height="100%" fill="green" /> </svg>
使用SVG:
image.png <svg width="100%" height="100%"> <rect width="100%" height="100%" fill="red" /> <circle cx="100%" cy="100%" r="150" fill="blue" stroke="black" /> <polygon points="120,0 240,225 0,225" fill="green"/> <text x="50" y="100" font-family="Verdana" font-size="55" fill="white" stroke="black" stroke-width="2"> Hello! </text> </svg>
CSS模块
外边距重叠
块的上外边距
(margin-top)
和下外边距(margin-bottom)
有时合并(折叠)为单个边距,其大小为单个边距的最大值(或如果它们相等,则仅为其中一个),这种行为称为边距折叠。布局和包含块
image.png 层叠上下文
满足以下任意一个条件的元素形成:
文档根元素(
<html>
);position
值为absolute
(绝对定位)或relative
(相对定位)且z-index
值不为auto
的元素;position
值为fixed
(固定定位)或sticky
(粘滞定位)的元素(沾滞定位适配所有移动设备上的浏览器,但老的桌面浏览器不支持);flex (
flexbox
) 容器的子元素,且z-index
值不为 auto;grid (
grid
) 容器的子元素,且z-index
值不为 auto;opacity
属性值小于 1 的元素
块格式化上下文
块格式化上下文(
Block Formatting Context,BFC
) 是Web页面的可视CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。会创建块格式化上下文:
根元素(
<html>
)浮动元素(元素的
float
不是none
)绝对定位元素(
元素的 position 为 absolute 或 fixed
)行内块元素(元素的
display 为 inline-block
)表格单元格(元素的
display 为 table-cell
,HTML表格单元格默认为该值)表格标题(元素的
display 为 table-caption
,HTML表格标题默认为该值)contain
值为layout、content 或 paint
的元素弹性元素(
display 为 flex 或 inline-flex
元素的直接子元素)网格元素(
display 为 grid 或 inline-grid
元素的直接子元素)
使用
overflow: auto
创建一个会包含这个浮动的
BFC
,通常的做法是设置父元素overflow: auto
或者设置其他的非默认的overflow: visible
的值。设置
overflow: auto
创建一个新的BFC
来包含这个浮动。我们的<div>
元素现在变成布局中的迷你布局。任何子元素都会被包含进去。image.png image.png CSS 弹性盒子布局
此属性是以下CSS属性的简写:
flex-grow
flex-shrink
flex-basis
flex-shrink
属性指定了flex
元素的收缩规则。flex
元素仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据flex-shrink
的值。flex-shrink: 2; flex-shrink: 0.6; /* Global values */ flex-shrink: inherit; flex-shrink: initial; flex-shrink: unset
flex-grow
设置了一个flex
项主尺寸的flex
增长系数。它指定了flex
容器中剩余空间的多少应该分配给项目(flex
增长系数)。主尺寸是项的宽度或高度,这取决于
flex-direction
值。flex-basis
指定了flex
元素在主轴方向上的初始大小。如果不使用box-sizing
改变盒模型的话,那么这个属性就决定了flex
元素的内容盒(content-box
)的尺寸。flex-wrap
指定flex
元素单行显示还是多行显示 。如果允许换行,这个属性允许你控制行的堆叠方向。order
属性规定了弹性容器中的可伸缩项目在布局时的顺序。元素按照order
属性的值的增序进行布局。拥有相同order
属性值的元素按照它们在源代码中出现的顺序进行布局。flex-flow
属性是flex-direction
和flex-wrap
的简写。flex-direction: row flex-wrap: nowrap
对齐属性
align-content
属性设置了浏览器如何沿着弹性盒子布局的纵轴和网格布局的主轴在内容项之间和周围分配空间。/* 基本位置对齐 */ /*align-content不采用左右值 */ align-content: center; /* 将项目放置在中点 */ align-content: start; /* 最先放置项目 */ align-content: end; /* 最后放置项目 */ align-content: flex-start; /* 从起始点开始放置flex元素 */ align-content: flex-end; /* 从终止点开始放置flex元素 */ /* 默认对齐 */ align-content: normal; /*基线对齐*/ align-content: baseline; align-content: first baseline; align-content: last baseline; /* 分布式对齐 */ align-content: space-between; /* 均匀分布项目 第一项与起始点齐平, 最后一项与终止点齐平 */ align-content: space-around; /* 均匀分布项目 项目在两端有一半大小的空间*/ align-content: space-evenly; /* 均匀分布项目 项目周围有相等的空间 */ align-content: stretch; /* 均匀分布项目 拉伸‘自动’-大小的项目以充满容器 */ /* 溢出对齐 */ align-content: safe center; align-content: unsafe center; /* 全局属性 */ align-content: inherit; /* 继承 */ align-content: initial; /* 初始值 */ align-content: unset; /* 未设置 */
image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png align-items
示例:
align-items: stretch; align-items: center; align-items: start; align-items: end;
align-self: stretch;
效果如下:image.png align-self: center;
效果如下:image.png align-self: start;
效果如下:image.png align-self: end;
效果如下:image.png justify-content
✍justify-content: center; /* 居中排列 */ justify-content: start; /* Pack items from the start */ justify-content: end; /* Pack items from the end */ justify-content: flex-start; /* 从行首起始位置开始排列 */ justify-content: flex-end; /* 从行尾位置开始排列 */ justify-content: left; /* Pack items from the left */ justify-content: right; /* Pack items from the right */ justify-content: space-between; /* 均匀排列每个元素 首个元素放置于起点,末尾元素放置于终点 */ justify-content: space-around; /* 均匀排列每个元素 每个元素周围分配相同的空间 */ justify-content: space-evenly; /* 均匀排列每个元素 每个元素之间的间隔相等 */ justify-content: stretch; /* 均匀排列每个元素 'auto'-sized 的元素会被拉伸以适应容器的大小 */
place-content
属性是align-content
和justify-content
的简写animation
✍animation-name
animation-duration
animation-timing-function
animation-delay
animation-iteration-count
animation-direction
animation-fill-mode
animation-play-state
animation: 3s ease-in 1s infinite reverse both running slidein; animation: 3s linear 1s infinite running slidein; animation: 3s linear 1s infinite alternate slidein; animation: .5s linear 1s infinite alternate slidein; @keyframes slidein { from { transform: scaleX(0); } to { transform: scaleX(1); } }
animation-name: none
animation-duration: 0s
animation-timing-function: ease
animation-delay: 0s
animation-iteration-count: 1
animation-direction: normal
animation-fill-mode: none
animation-play-state: running
长度单位
css中有两种长度:相对长度和绝对长度。绝对长度不依赖于其他任何量度。绝对量度无论其所应用的环境如何都保持其长度。
相对长度依赖于使用的环境,如计算机显示器的屏幕分辨率或字体的大小。
绝对长度根据实际单位定义,如英寸,厘米和点等。
长度单位分相对长度单位和绝对长度单位:相对/绝对
相对长度单位。相对长度单位分:相对字体长度单位和相对视区长度单位
相对字体长度单位,
如em和ex,还有css3的rem和ch
相对视区长度单位,如
vh, vw, vmin, vmax
绝对长度单位,常见有
px,pt,cm,mm,pc
css
中的单位:时间单位
s,ms
,角度单位deg,rad
,长度单位px,em
%
不是长度单位选择器:1,类选择器,2,ID选择器,3,属性选择器,4,伪类选择器,5,伪元素选择器。
:first-child :last-child ::first-line ::first-letter ::before ::after
关系选择器:1,后代选择器,2,相邻后代选择器,3,兄弟选择器,4,相邻兄弟选择器。
规则:
@
@规则指的是以@字符开始的一些规则,如@media, @font-face, @page, @support
块级元素和
display为block
的元素不是一个概念。so,清除浮动:✍
.clear:after { content: '', display: table; // 可以是block, list-item clear: both; }
不使用
list-item
是:第一它字符比较多
会出现不需要的项目符号
IE浏览器不支持伪元素的
display
指为list-item
,主要是兼容性不好。对于IE浏览器,普通元素设置display:list-item
有效的,但:before/:after
伪元素就无效了。
块级盒子就负责结构,内联盒子就负责内容。
a标签元素默认display是inline,设置display:block为块状化,后面
width: 100%
就没有问题。box-sizing
box-sizing
盒尺寸,width
作用的细节,box-sizing
属性的作用是改变width
的作用细节。内在盒子的4个盒子:content box
padding box
border box
margin box
默认情况下,width是作用在
content box
上的,box-sizing
的作用就是可以把width
作用的盒子变成其他几个。理论上写法:✍
.box1 { box-sizing: content-box; } .box2 { box-sizing: padding-box; } .box3 { box-sizing: border-box; } .box4 { box-sizing: margin-box; }
不过只能写以下写法:✍
.box1 { box-sizing: content-box; } // 默认值 .box2 { box-sizing: padding-box; } // 曾经支持 .box3 { box-sizing: border-box; } // 支持 .box4 { box-sizing: margin-box; } // 从未支持
建议不要全局重置的做法。这种容易产生没必要的消耗,这种做法并不能解决所有问题。
*
通配符尽量不使用,因为它会选择所有标签元素,对于普通内联元素,box-sizing
无论是什么值,对其渲染表现都没有影响。同样有些元素,其默认的box-sizing
就是border-box
,所以也没有必要的消耗。Internet
工作原理在浏览器中输入Internet地址会发生什么情况:
在浏览器中输入www地址
浏览器与该地址的HTTP服务器进行交互
HTTP服务器接收浏览器的请求
HTTP服务器查找web文档
HTTP服务器发送Web文档
浏览器接收该文档
浏览器处理源代码
浏览器显示网页
服务器端计算器包含了用来处理所有web页面请求的http服务器软件。在浏览器中输入internet地址时,浏览器发出一个请求,经过很长的计算机网络传播,直到找到远程计算机的地址。在请求到达HTTP服务器后,HTTP服务器分析该请求,在服务器的硬盘上搜索请求的页面,并对该请求做出响应,返回所需的web页面。
响应经过另一条计算机链进行传播,一直到达您的计算机。然后浏览器打开该响应并读取HTTP服务器送回内容。如果服务器发送的是浏览器能够分析的HTML文档或其他文档,则浏览器会读取该文档的源代码并处理成可显示的web页面。
样式表是由规则组成的
规则由选择器和声明组成。
声明由属性和值组成。
值可以是关键字,长度,颜色,字符串,整型,实型,或者是URL。
em量度最好用于屏幕布局。
URI用于在CSS中包含样式表和背景图像。
可以使用style属性直接在HTML元素中内联地包含样式。
选择器
类和ID选择器
通用选择器
后代选择器
直接子选择器
相邻选择器
属性选择器
伪元素
伪类
基于属性值的选择
属性值选择器基于属性的存在性和值应用样式声明。
input[type="text"]{ background: blue; color: white; border: 3px solid royalblue; } <input type="text" name="first_name" value="name" size="25"/>
属性子字符串选择器
出现在另一个字符串中的字符串被称为字符串。
a[href^="ftp://"] { background: blue; color: white; border: 3px solid royalblue; } <a href="ftp://ftp.example.com"/>dadaqianduan.cn</a>
伪类:伪类是用来表示动态事件,状态改变或者是在文档中以其他方法不能轻易实现的情况,可能是用户的鼠标悬停或单击某元素。伪类对目标元素出现某种特殊的状态应用样式。
动态伪类
:link
,表示未访问的超链接:visited
,表示已访问的超链接:hover
,表示鼠标指针当前停留在该元素上:active
,表示用户正在单击该元素
a:link { color: red; } a:visited { color: yellow; }
:first-child
结构化伪类只用于当一个元素是另一个元素的第一个子元素时。文本属性
letter-spacing
属性以及使用它增加和减少单词字母间隔的方法word-spacing
属性以及使用它增加和减少句子中单词间隔的方法text-indent
属性以及使用它控制段落中文本缩进的方法text-align
属性以及使用它对齐文档中的文本的方法text-decoration
属性以及使用它对文本加下划线,上划线和删除线的方法text-transform
属性以及使用它控制文本的大小写和进行字母大小写之间转换的方法white-space
属性以及使用它控制文本流及格式的方法。
letter-spacing
属性,用来控制字母间隔的属性。
letter-spacing: normal;
word-spacing
属性,用来孔子单词之间的间隔
word-spacing: normal;
text-indent
属性缩进段落文本text-align
属性对齐文本text-decoration
属性,用来对文本加下划线,上划线,删除线。text-transform
属性,用来控制文本的大小写
#capitalize { text-transform: capitalize; } #uppercase { text-transform: uppercase; } #lowercase { text-transform: lowercase; }
white-space
属性,允许控制web
文档源代码的文本格式化
字体属性
font-family
属性指定字体。font-style
属性用来在一种特定字体提供的不同样式之间切换。font-weight
样式表属性提供了指定字体粗细的功能。font-size
属性用来控制字体的大小
溢出的内容
css的overflow属性用来处理易受尺寸限制影响的内容,这些内容很可能溢出尺寸限制的边界。overflow属性最常见的两个作用是当内容超过可用空间时隐藏内容,或者是通过滚动条使多余的内容可以被访问。
overflow: visible | hidden | scroll | auto
三角等图形绘制
image.png div { width: 0; border: 10px solid; border-color: #f30 transparent transparent; }
image.png <style type="text/css"> .div5 { width: 0; border: 10px solid; border-color: #f30 transparent transparent; } .div1 { width: 10px; height: 10px; border: 10px solid; border-color: #f30 transparent transparent; } .div2 { width: 10px; height: 10px; border: 10px solid; border-color: #f30 #00f #396 #0f0; } .div3 { width: 0; border-width: 10px 20px; border-style: solid; border-color: #f30 transparent transparent; } .div4 { width: 0; border-width: 10px 20px; border-style: solid; border-color: #f30 #f30 transparent transparent; } </style>
css中举足轻重的角色
line-height
行高的定义就是两基线的间距vertical-align
的默认值就是基线
JavaScript模块
事件示例:
const btn = document.querySelector('button'); btn.onclick = function() { const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; document.body.style.backgroundColor = rndCol; }
Array
创建数组
var fruits = ['Apple', 'Banana']; console.log(fruits.length); // 2
通过索引访问数组元素
var first = fruits[0]; // Apple var last = fruits[fruits.length - 1]; // Banana
遍历数组
fruits.forEach(function (item, index, array) { console.log(item, index); }); // Apple 0 // Banana 1
添加元素到数组的末尾
var newLength = fruits.push('Orange'); // newLength:3; fruits: ["Apple", "Banana", "Orange"]
删除数组末尾的元素
var last = fruits.pop(); // remove Orange (from the end) // last: "Orange"; fruits: ["Apple", "Banana"];
删除数组最前面(头部)的元素
var first = fruits.shift(); // remove Apple from the front // first: "Apple"; fruits: ["Banana"];
添加元素到数组的头部
var newLength = fruits.unshift('Strawberry') // add to the front // ["Strawberry", "Banana"];
找出某个元素在数组中的索引
fruits.push('Mango'); // ["Strawberry", "Banana", "Mango"] var pos = fruits.indexOf('Banana'); // 1
复制一个数组
var shallowCopy = fruits.slice(); // this is how to make a copy // ["Strawberry", "Mango"]
方法
Array.prototype.pop()
删除数组的最后一个元素,并返回这个元素。Array.prototype.push()
在数组的末尾增加一个或多个元素,并返回数组的新长度。Array.prototype.reverse()
颠倒数组中元素的排列顺序,即原先的第一个变为最后一个,原先的最后一个变为第一个。Array.prototype.shift()
删除数组的第一个元素,并返回这个元素。Array.prototype.sort()
对数组元素进行排序,并返回当前数组。Array.prototype.splice()
在任意的位置给数组添加或删除任意个元素。Array.prototype.unshift()
在数组的开头增加一个或多个元素,并返回数组的新长度。Array.prototype.concat()
返回一个由当前数组和其它若干个数组或者若干个非数组值组合而成的新数组。Array.prototype.join()
连接所有数组元素组成一个字符串。Array.prototype.slice()
抽取当前数组中的一段元素组合成一个新数组。Array.prototype.toString()
返回一个由所有数组元素组合而成的字符串。遮蔽了原型链上的Object.prototype.toString()
方法。Array.prototype.indexOf()
返回数组中第一个与指定值相等的元素的索引,如果找不到这样的元素,则返回-1
。Array.prototype.lastIndexOf()
返回数组中最后一个(从右边数第一个)与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1。Array.prototype.forEach()
为数组中的每个元素执行一次回调函数。Array.prototype.every()
如果数组中的每个元素都满足测试函数,则返回 true,否则返回 false。Array.prototype.some()
如果数组中至少有一个元素满足测试函数,则返回 true,否则返回 false。Array.prototype.filter()
将所有在过滤函数中返回 true 的数组元素放进一个新数组中并返回。Array.prototype.map()
返回一个由回调函数的返回值组成的新数组。Array.prototype.reduce()
reduce()
方法对数组中的每个元素执行一个由您提供的reducer
函数(升序执行),将其结果汇总为单个返回值。const array1 = [1, 2, 3, 4]; const reducer = (accumulator, currentValue) => accumulator + currentValue; // 1 + 2 + 3 + 4 console.log(array1.reduce(reducer)); // expected output: 10 // 5 + 1 + 2 + 3 + 4 console.log(array1.reduce(reducer, 5)); // expected output: 15
Array.prototype.reduceRight()
reduceRight()
方法接受一个函数作为累加器(accumulator)和数组的每个值(从右到左)将其减少为单个值。const array1 = [[0, 1], [2, 3], [4, 5]].reduceRight( (accumulator, currentValue) => accumulator.concat(currentValue) ); console.log(array1); // expected output: Array [4, 5, 2, 3, 0, 1]
Boolean
Boolean
对象是一个布尔值的对象包装器。0,-0,null,false,NaN,undefined
,或空字符串(""
),该对象具有的初始值false
。其值不是
undefined或null
的任何对象在传递给条件语句时都将计算为true。var x = new Boolean(false); if (x) { // 这里的代码会被执行 } var x = false; if (x) { // 这里的代码不会执行 } var x = Boolean(expression); // 推荐 var x = !!(expression); // 推荐 var x = new Boolean(expression); // 不太好
Boolean.prototype.toString()
根据对象的值返回字符串"true"或"false"
。重写Object.prototype.toString()
方法。Boolean.prototype.valueOf()
返回Boolean
对象的原始值。重写Object.prototype.valueOf()
方法。Date
创建一个 JavaScript Date 实例,该实例呈现时间中的某个时刻。image.png new Date(); new Date(value); new Date(dateString); new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]]);
创建一个新
Date
对象的唯一方法是通过new 操作符,例如:let now = new Date();
若将它作为常规函数调用(即不加new
操作符),将返回一个字符串,而非Date
对象。Date()
构造函数有四种基本形式year 表示年份的整数值。 monthIndex 表示月份的整数值,从 0(1月)到 11(12月)。 date 表示一个月中的第几天的整数值,从1开始。默认值为1。 hours 表示一天中的小时数的整数值 (24小时制)。默认值为0(午夜)。 minutes 表示一个完整时间(如 01:10:00)中的分钟部分的整数值。默认值为0。 seconds 表示一个完整时间(如 01:10:00)中的秒部分的整数值。默认值为0。 milliseconds 表示一个完整时间的毫秒部分的整数值。默认值为0。
实例方法
Date.prototype.getDate()
根据本地时间返回指定日期对象的月份中的第几天(1-31)。Date.prototype.getDay()
根据本地时间返回指定日期对象的星期中的第几天(0-6)。Date.prototype.getFullYear()
根据本地时间返回指定日期对象的年份(四位数年份时返回四位数字)。Date.prototype.getHours()
根据本地时间返回指定日期对象的小时(0-23)。Date.prototype.getMilliseconds()
根据本地时间返回指定日期对象的毫秒(0-999)。Date.prototype.getMinutes()
根据本地时间返回指定日期对象的分钟(0-59)。Date.prototype.getMonth()
根据本地时间返回指定日期对象的月份(0-11)。Date.prototype.getSeconds()
根据本地时间返回指定日期对象的秒数(0-59)。Date.prototype.getTime()
返回从1970-1-1 00:00:00 UTC
(协调世界时)到该日期经过的毫秒数,对于1970-1-1 00:00:00 UTC
之前的时间返回负值。Function
Function.prototype.apply() Function.prototype.bind() Function.prototype.call() Function.prototype.toString()
JSON
JSON.parse() JSON.stringify()
Math
方法Math.abs(x) 返回一个数的绝对值。 Math.acos(x) 返回一个数的反余弦值。 Math.acosh(x) 返回一个数的反双曲余弦值。 Math.asin(x) 返回一个数的反正弦值。 Math.asinh(x) 返回一个数的反双曲正弦值。 Math.atan(x) 返回一个数的反正切值。 Math.atanh(x) 返回一个数的反双曲正切值。 Math.atan2(y, x) 返回 y/x 的反正切值。 Math.cbrt(x) 返回一个数的立方根。 Math.ceil(x) 返回大于一个数的最小整数,即一个数向上取整后的值。 Math.clz32(x) 返回一个 32 位整数的前导零的数量。 Math.cos(x) 返回一个数的余弦值。 Math.cosh(x) 返回一个数的双曲余弦值。 Math.exp(x) 返回欧拉常数的参数次方,Ex,其中 x 为参数,E 是欧拉常数(2.718...,自然对数的底数)。 Math.expm1(x) 返回 exp(x) - 1 的值。 Math.floor(x) 返回小于一个数的最大整数,即一个数向下取整后的值。 Math.fround(x) 返回最接近一个数的单精度浮点型表示。 Math.hypot([x[, y[, …]]]) 返回其所有参数平方和的平方根。 Math.imul(x, y) 返回 32 位整数乘法的结果。 Math.log(x) 返回一个数的自然对数(㏒e,即 ㏑)。 Math.log1p(x) 返回一个数加 1 的和的自然对数(㏒e,即 ㏑)。 Math.log10(x) 返回一个数以 10 为底数的对数。 Math.log2(x) 返回一个数以 2 为底数的对数。 Math.max([x[, y[, …]]]) 返回零到多个数值中最大值。 Math.min([x[, y[, …]]]) 返回零到多个数值中最小值。 Math.pow(x, y) 返回一个数的 y 次幂。 Math.random() 返回一个 0 到 1 之间的伪随机数。 Math.round(x) 返回四舍五入后的整数。 Math.sign(x) 返回一个数的符号,得知一个数是正数、负数还是 0。 Math.sin(x) 返回一个数的正弦值。 Math.sinh(x) 返回一个数的双曲正弦值。 Math.sqrt(x) 返回一个数的平方根。 Math.tan(x) 返回一个数的正切值。 Math.tanh(x) 返回一个数的双曲正切值。 Math.toSource() 返回字符串 "Math"。 Math.trunc(x) 返回一个数的整数部分,直接去除其小数点及之后的部分。
Number
方法Number.isNaN() 确定传递的值是否是 NaN。 Number.isFinite() 确定传递的值类型及本身是否是有限数。 Number.isInteger() 确定传递的值类型是“number”,且是整数。 Number.parseFloat() 和全局对象 parseFloat() 一样。 Number.parseInt() 和全局对象 parseInt() 一样。
Object
Object
构造函数创建一个对象包装器。Object.assign() 通过复制一个或多个对象来创建一个新的对象。 Object.create() 使用指定的原型对象和属性创建一个新对象。 Object.defineProperty() 给对象添加一个属性并指定该属性的配置。 Object.defineProperties() 给对象添加多个属性并分别指定它们的配置。 Object.entries() 返回给定对象自身可枚举属性的 [key, value] 数组。 Object.freeze() 冻结对象:其他代码不能删除或更改任何属性。 Object.getOwnPropertyDescriptor() 返回对象指定的属性配置。 Object.getOwnPropertyNames() 返回一个数组,它包含了指定对象所有的可枚举或不可枚举的属性名。 Object.getOwnPropertySymbols() 返回一个数组,它包含了指定对象自身所有的符号属性。 Object.getPrototypeOf() 返回指定对象的原型对象。 Object.is() 比较两个值是否相同。 Object.isExtensible() 判断对象是否可扩展。 Object.isFrozen() 判断对象是否已经冻结。 Object.isSealed() 判断对象是否已经密封。 Object.setPrototypeOf() 设置对象的原型(即内部 [[Prototype]] 属性)。
WeakMap
WeakMap
对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的。WeakSet
WeakSet
对象允许你将弱保持对象存储在一个集合中。语法
new WeakSet([iterable]);
instanceof
instanceof
运算符用于检测构造函数的prototype
属性是否出现在某个实例对象的原型链上。function Car(make, model, year) { this.make = make; this.model = model; this.year = year; } const auto = new Car('2323', '2324', 1234); console.log(auto instanceof Car); // expected output: true console.log(auto instanceof Object); // expected output: true
typeof
typeof
操作符返回一个字符串,表示未经计算的操作数的类型。console.log(typeof 42); // expected output: "number" console.log(typeof 'blubber'); // expected output: "string" console.log(typeof true); // expected output: "boolean" console.log(typeof undeclaredVariable); // expected output: "undefined"
new
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
function Car(make, model, year) { this.make = make; this.model = model; this.year = year; } const car1 = new Car('sdfs', 'sdfsd sdf', 2234); console.log(car1.make); // expected output: "Eagle"
Promises/A+
规范fulfill,解决,指一个promise成功时进行一些列操作,如状态的改变,回调的执行。虽然规范中用fulfill来表示解决,但在后面的promise实现多以resolve来指代。
reject,拒绝,指一个promise失败时进行的一些列操作
eventual value,指的是promise被解决时传递给解决回调的指,由于promise有一次性的特征,因此当这个值被传递时,标志着promise等待态的结束,称为终值,有时称为值。
reason,拒绝原因,指在promise被拒绝时传递给拒绝回调的值。
示例:
var fs = require('fs') function writeFileAsync(fpath, data, cb) { fs.writeFile(fpath, data, function(err) { cb(err); }); } var fs = require('fs') var Promise = require('bluebird'); function writeFileAsync(fpath, data) { return new Promise(function(resolve, reject) { fs.writeFile(fpath, data, function(err){ if(err) reject(err) else resolve() }) }) }
// 回调嵌套 request(url, funcion(err, res, body) { if(err) handleError(err) fs.writeFile('1.txt', body, function(err) { if(err) handleError(err) request(url2, function(err, res, body) { if(err) handleError(err) }) }) }) // Promise写法 request(url) .then(function(result) { return wirteFileAsync('1.txt', result) }) .then(function(result) { return request(url2) }) .catch(function(e){ handleError(e) })
交通灯问题
function red() { console.log('red'); } function green() { console.log('green'); } function yellow() { console.log('yellow'); } var tic = function(timer, cb) { return new Promise(function(resolve, reject) { setTimeout(function(){ cb(); resolve(); },timer); }; }; var d = new Promise(function(resolve, reject){resolve();}); var step = function(def) { def.then(function() { return tic(3000, red); }).then(function() { return tic(2000, green); }).then(function() { return tic(1000, yellow); }); } var d = new Promise(function(resolve, reject) {resolve();}); var step = function(def){ while(true) { def.then(function() { return tic(3000, red); }).then(function() { return tic(2000, green); }).then(function() { return tic(1000, yellow); }); } } var d = new Promise(function(resolve, reject) { resolve();}); var step = function(def) { def.then(function() { return tic(3000, red); }).then(function() { return tic(2000, green); }).then(function() { step(def); }); }
优化:
var tic = function(timmer, str){ return new Promise(function(resolve, reject) { setTimeout(function() { console.log(str); resolve(1); }, timmer); }); }; function *gen(){ yield tic(3000, 'red'); yield tic(1000, 'green'); yield tic(2000, 'yellow'); } var iterator = gen(); var step = function(gen, iterator){ var s = iterator.next(); if (s.done) { step(gen, gen()); } else { s.value.then(function() { step(gen, iterator); }); } } step(gen, iterator);
var promise = new Promise(function(resolve) { resolve(42); }); promise.then(function(value) { console.log(value); }).catch(function(error) { console.log(error); });
使用了回调函数的异步处理
getAsync("file.txt", function(error, result) { if(error){ // 取得失败时的处理 throw error; } // 取得成功时的处理 });
使用Promise进行异步处理的一个例子
var promise = getAsyncPromise('fileA.txt'); promise.then(function(result) { // 获取文件内容成功时的处理 }).catch(function(error) { // 获取文件内容失败时的处理 });
Constructor
Promise
类似于XMLHttpRequest
,从构造函数Promise
来创建一个新建新promise
对象作为接口。要想创建一个
promise
对象、可以使用new
来调用Promise
的构造器来进行实例化。var promise = new Promise(function(resolve, reject) { // 异步处理 // 处理结束后、调用resolve 或 reject });
promise.then(onFulfilled, onRejected)
resolve
(成功)时onFulfilled
会被调用reject
(失败)时onRejected
会被调用Promise
的状态用new Promise 实例化的promise对象有以下三个状态。
"has-resolution" - Fulfilled
resolve
(成功)时。此时会调用onFulfilled
"has-rejection" - Rejected
reject
(失败)时。此时会调用onRejected
"unresolved" - Pending
既不是resolve
也不是reject
的状态。也就是promise
对象刚被创建后的初始化状态等promise
对象的状态,从Pending
转换为Fulfilled
或Rejected
之后, 这个promise
对象的状态就不会再发生任何变化。也就是说,
Promise
与Event
等不同,在.then
后执行的函数可以肯定地说只会被调用一次。创建XHR的promise对象
function getURL(URL) { return new Promise(function (resolve, reject) { var req = new XMLHttpRequest(); req.open('GET', URL, true); req.onload = function() { if(req.status === 200) { resolve(req.responseText); }else{ reject(new Error(req.statusText)); } }; req.onerror = function() { reject(new Error(req.statusText)); }; req.send(); }); } // 运行示例xxx var URL = "http://x'x'x.org/get"; getURL(URL).then(function onFulfilled(value){ console.log(value); }).catch(function onRejected(error){ console.error(error); });
Promise.resolve(42).then(function(value){ console.log(value); });
var promise = new Promise(function (resolve){ console.log("inner promise"); // 1 resolve(42); }); promise.then(function(value){ console.log(value); // 3 }); console.log("outer promise"); // 2 nner promise // 1 outer promise // 2 42 // 3
示例:
function taskA() { console.log("Task A"); } function taskB() { console.log("Task B"); } function onRejected(error) { console.log("Catch Error: A or B", error); } function finalTask() { console.log("Final Task"); } var promise = Promise.resolve(); promise .then(taskA) .then(taskB) .catch(onRejected) .then(finalTask); Task A Task B Final Task
image.png AMD 与 CMD 的区别
CMD 推崇依赖就近,AMD 推崇依赖前置。
AMD 是提前执行,CMD 是延迟执行
AMD 和 CMD 都是用于浏览器端的模块规范,而在服务器端比如 node,采用的则是 CommonJS 规范。
CommonJS 规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。
AMD规范则是非同步加载模块,允许指定回调函数。
CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。
如何查看代码利用率
打开 Chrome Dev Tool;
按下 Cmd + Shift + P or Ctrl + Shift + P ;
输入 Coverage,并选择第一个出现的选项;
使用 Array.includes 来处理多个条件
示例:
function test(fruit) { if (fruit == 'apple' || fruit == 'strawberry') { console.log('red'); } }
优化:
function test(fruit) { // 条件提取到数组中 const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries']; if (redFruits.includes(fruit)) { console.log('red'); } }
减少嵌套,提前使用 return 语句
function test(fruit, quantity) { const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries']; // 条件 1:fruit 必须有值 if (fruit) { // 条件 2:必须为红色 if (redFruits.includes(fruit)) { console.log('red'); // 条件 3:数量必须大于 10 if (quantity > 10) { console.log('big quantity'); } } } else { throw new Error('No fruit!'); } } // 测试结果 test(null); // 抛出错误:No fruits test('apple'); // 打印:red test('apple', 20); // 打印:red,big quantity
优化:
/* 在发现无效条件时提前 return */ function test(fruit, quantity) { const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries']; // 条件 1:提前抛出错误 if (!fruit) throw new Error('No fruit!'); // 条件2:必须为红色 if (redFruits.includes(fruit)) { console.log('red'); // 条件 3:数量必须大于 10 if (quantity > 10) { console.log('big quantity'); } } }
优化:
/* 在发现无效条件时提前 return */ function test(fruit, quantity) { const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries']; if (!fruit) throw new Error('No fruit!'); // 条件 1:提前抛出错误 if (!redFruits.includes(fruit)) return; // 条件 2:当 fruit 不是红色的时候,提前 return console.log('red'); // 条件 3:必须是大量存在 if (quantity > 10) { console.log('big quantity'); } }
使用函数的默认参数 和 解构
使用 JavaScript 时总是需要检查
null / undefined
值并分配默认值:function test(fruit, quantity) { if (!fruit) return; const q = quantity || 1; // 如果没有提供 quantity 参数,则默认为 1 console.log(`We have ${q} ${fruit}!`); } // 测试结果 test('banana'); // We have 1 banana! test('apple', 2); // We have 2 apple!
优化:
function test(fruit, quantity = 1) { // i如果没有提供 quantity 参数,则默认为 1 if (!fruit) return; console.log(`We have ${quantity} ${fruit}!`); } // 测试结果 test('banana'); // We have 1 banana! test('apple', 2); // We have 2 apple!
function test(fruit) { // 如果有值,则打印 fruit.name if (fruit && fruit.name) { console.log (fruit.name); } else { console.log('unknown'); } } //测试结果 test(undefined); // unknown test({ }); // unknown test({ name: 'apple', color: 'red' }); // apple
优化:
// 解构 —— 只获得 name 属性 // 参数默认分配空对象 {} function test({name} = {}) { console.log (name || 'unknown'); } //测试结果 test(undefined); // unknown test({ }); // unknown test({ name: 'apple', color: 'red' }); // apple
优化:
// 引入 lodash 库,我们将获得 _.get() function test(fruit) { console.log(_.get(fruit, 'name', 'unknown'); // 获取 name 属性,如果没有分配,则设为默认值 unknown } //测试结果 test(undefined); // unknown test({ }); // unknown test({ name: 'apple', color: 'red' }); // apple
选择
Map / Object
字面量,而不是Switch
语句示例:
function test(color) { // 使用 switch case 语句,根据颜色找出对应的水果 switch (color) { case 'red': return ['apple', 'strawberry']; case 'yellow': return ['banana', 'pineapple']; case 'purple': return ['grape', 'plum']; default: return []; } } //测试结果 test(null); // [] test('yellow'); // ['banana', 'pineapple']
优化:
// 使用对象字面量,根据颜色找出对应的水果 const fruitColor = { red: ['apple', 'strawberry'], yellow: ['banana', 'pineapple'], purple: ['grape', 'plum'] }; function test(color) { return fruitColor[color] || []; }
// 使用 Map ,根据颜色找出对应的水果 const fruitColor = new Map() .set('red', ['apple', 'strawberry']) .set('yellow', ['banana', 'pineapple']) .set('purple', ['grape', 'plum']); function test(color) { return fruitColor.get(color) || []; }
const fruits = [ { name: 'apple', color: 'red' }, { name: 'strawberry', color: 'red' }, { name: 'banana', color: 'yellow' }, { name: 'pineapple', color: 'yellow' }, { name: 'grape', color: 'purple' }, { name: 'plum', color: 'purple' } ]; function test(color) { // 使用 Array filter ,根据颜色找出对应的水果 return fruits.filter(f => f.color == color); }
使用
Array.every
和Array.some
来处理全部/部分满足条件const fruits = [ { name: 'apple', color: 'red' }, { name: 'banana', color: 'yellow' }, { name: 'grape', color: 'purple' } ]; function test() { let isAllRed = true; // 条件:所有的水果都必须是红色 for (let f of fruits) { if (!isAllRed) break; isAllRed = (f.color == 'red'); } console.log(isAllRed); // false }
优化:
const fruits = [ { name: 'apple', color: 'red' }, { name: 'banana', color: 'yellow' }, { name: 'grape', color: 'purple' } ]; function test() { // 条件:简短方式,所有的水果都必须是红色 const isAllRed = fruits.every(f => f.color == 'red'); console.log(isAllRed); // false }
使用
Array.some
const fruits = [ { name: 'apple', color: 'red' }, { name: 'banana', color: 'yellow' }, { name: 'grape', color: 'purple' } ]; function test() { // 条件:是否存在红色的水果 const isAnyRed = fruits.some(f => f.color == 'red'); console.log(isAnyRed); // true }
Spread operator
(展开操作符)示例:
const favoriteFood = ['Pizza', 'Fries', 'Swedish-meatballs']; console.log(...favoriteFood); //Pizza Fries Swedish-meatballs
for…of
迭代器const toolBox = ['Hammer', 'Screwdriver', 'Ruler'] for(const item of toolBox) { console.log(item) } // Hammer // Screwdriver // Ruler
Includes()
方法const garge = ['BMW', 'AUDI', 'VOLVO']; const findCar = garge.includes('BMW'); console.log(findCar); // true
清空或截断数组
const arr = [11, 22, 33, 44, 55, 66]; // truncanting arr.length = 3; console.log(arr); //=> [11, 22, 33] // clearing arr.length = 0; console.log(arr); //=> [] console.log(arr[2]); //=> undefined
使用对象解构(
destructuring
)模拟命名参数示例:
doSomething({ foo: 'Hello', bar: 'Hey!', baz: 42 }); function doSomething(config) { const foo = config.foo !== undefined ? config.foo : 'Hi'; const bar = config.bar !== undefined ? config.bar : 'Yo!'; const baz = config.baz !== undefined ? config.baz : 13; // ... }
优化:
function doSomething({ foo = 'Hi', bar = 'Yo!', baz = 13 } = {}) { // ... }
使用
async/await
来await
多个async
函数await Promise.all([anAsyncCall(), thisIsAlsoAsync(), oneMore()])
创建纯(
pure
)对象示例:
const pureObject = Object.create(null); console.log(pureObject); //=> {} console.log(pureObject.constructor); //=> undefined console.log(pureObject.toString); //=> undefined console.log(pureObject.hasOwnProperty); //=> undefined
平铺多维数组
示例:
// 仅仅适用于二维数组 const arr = [11, [22, 33], [44, 55], 66]; const flatArr = [].concat(...arr); //=> [11, 22, 33, 44, 55, 66]
优化:
unction flattenArray(arr) { const flattened = [].concat(...arr); return flattened.some(item => Array.isArray(item)) ? flattenArray(flattened) : flattened; } const arr = [11, [22, 33], [44, [55, 66, [77, [88]], 99]]]; const flatArr = flattenArray(arr); //=> [11, 22, 33, 44, 55, 66, 77, 88, 99]
Array.prototype
Array.prototype
属性表示Array
构造函数的原型,并允许您向所有Array
对象添加新的属性和方法。示例:
/* 如果JavaScript本身不提供 first() 方法, 添加一个返回数组的第一个元素的新方法。 */ if(!Array.prototype.first) { Array.prototype.first = function() { console.log(`如果JavaScript本身不提供 first() 方法, 添加一个返回数组的第一个元素的新方法。`); return this[0]; } }
Array.isArray(Array.prototype); // true
方法-会改变自身的方法
Array.prototype.pop() 删除数组的最后一个元素,并返回这个元素。 Array.prototype.push() 在数组的末尾增加一个或多个元素,并返回数组的新长度。 Array.prototype.reverse() 颠倒数组中元素的排列顺序,即原先的第一个变为最后一个,原先的最后一个变为第一个。 Array.prototype.shift() 删除数组的第一个元素,并返回这个元素。 Array.prototype.sort() 对数组元素进行排序,并返回当前数组。 Array.prototype.splice() 在任意的位置给数组添加或删除任意个元素。 Array.prototype.unshift() 在数组的开头增加一个或多个元素,并返回数组的新长度。
不会改变自身的方法
Array.prototype.concat() 返回一个由当前数组和其它若干个数组或者若干个非数组值组合而成的新数组。 Array.prototype.join() 连接所有数组元素组成一个字符串。 Array.prototype.slice() 抽取当前数组中的一段元素组合成一个新数组。 Array.prototype.toString() 返回一个由所有数组元素组合而成的字符串。遮蔽了原型链上的 Object.prototype.toString() 方法。 Array.prototype.indexOf() 返回数组中第一个与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1。 Array.prototype.lastIndexOf() 返回数组中最后一个(从右边数第一个)与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1。
遍历方法
Array.prototype.forEach() 为数组中的每个元素执行一次回调函数。
Array.from()
Array.from()
方法从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。console.log(Array.from('foo')); // expected output: Array ["f", "o", "o"] console.log(Array.from([1, 2, 3], x => x + x)); // expected output: Array [2, 4, 6]
语法
Array.from(arrayLike[, mapFn[, thisArg]]) 返回值 一个新的数组实例。
从 String 生成数组
Array.from('foo'); // [ "f", "o", "o" ]
从 Set 生成数组
const set = new Set(['foo', 'bar', 'baz', 'foo']); Array.from(set); // [ "foo", "bar", "baz" ]
从类数组对象(arguments)生成数组
function f() { return Array.from(arguments); } f(1, 2, 3); // [ 1, 2, 3 ]
数组去重合并
function combine(){ let arr = [].concat.apply([], arguments); //没有去重复的新数组 return Array.from(new Set(arr)); } var m = [1, 2, 2], n = [2,3,3]; console.log(combine(m,n)); // [1, 2, 3]
Array.isArray()
Array.isArray()
用于确定传递的值是否是一个 Array。示例:
Array.isArray([1, 2, 3]); // true Array.isArray({foo: 123}); // false Array.isArray("foobar"); // false Array.isArray(undefined); // false
instanceof 和 isArray
当检测
Array
实例时,Array.isArray
优于instanceof
,因为Array.isArray
能检测iframes
.var iframe = document.createElement('iframe'); document.body.appendChild(iframe); xArray = window.frames[window.frames.length-1].Array; var arr = new xArray(1,2,3); // [1,2,3] // Correctly checking for Array Array.isArray(arr); // true // Considered harmful, because doesn't work though iframes arr instanceof Array; // false
Polyfill
示例:
if (!Array.isArray) { Array.isArray = function(arg) { return Object.prototype.toString.call(arg) === '[object Array]'; }; }
Array.of()
Array.of()
方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。Array.of()
和 Array 构造函数之间的区别在于处理整数参数:Array.of(7)
创建一个具有单个元素 7 的数组,而Array(7)
创建一个长度为7的空数组(注意:这是指一个有7个空位(empty
)的数组,而不是由7个undefined
组成的数组)。Array.of(7); // [7] Array.of(1, 2, 3); // [1, 2, 3] Array(7); // [ , , , , , , ] Array(1, 2, 3); // [1, 2, 3]
语法
Array.of(element0[, element1[, ...[, elementN]]])
示例
Array.of(1); // [1] Array.of(1, 2, 3); // [1, 2, 3] Array.of(undefined); // [undefined]
兼容旧环境
if (!Array.of) { Array.of = function() { return Array.prototype.slice.call(arguments); }; }
get Array[@@species]
Array[@@species]
访问器属性返回 Array 的构造函数。语法
Array[Symbol.species]
返回值
Array
的构造函数。描述
species
访问器属性返回Array
对象的默认构造函数。子类的构造函数可能会覆盖并改变构造函数的赋值。示例
species
属性返回默认构造函数, 它用于 Array 对象的构造函数Array:
Array[Symbol.species]; // function Array()
闭包
闭包让你可以在一个内层函数中访问到其外层函数的作用域。在
JavaScript
中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。词法作用域
示例:
function init() { var name = "Mozilla"; // name 是一个被 init 创建的局部变量 function displayName() { // displayName() 是内部函数,一个闭包 alert(name); // 使用了父函数中声明的变量 } displayName(); } init();
词法(
lexical
)一词指的是,词法作用域根据源代码中声明变量的位置来确定该变量在何处可用。嵌套函数可访问声明于它们外部作用域的变量。闭包
示例:
function makeFunc() { var name = "Mozilla"; function displayName() { alert(name); } return displayName; } var myFunc = makeFunc(); myFunc();
闭包是由函数以及声明该函数的词法环境组合而成的。该环境包含了这个闭包创建时作用域内的任何局部变量。
示例:
// add5 和 add10 都是闭包。它们共享相同的函数定义,但是保存了不同的词法环境。 function makeAdder(x) { return function(y) { return x + y; }; } var add5 = makeAdder(5); var add10 = makeAdder(10); console.log(add5(2)); // 7 console.log(add10(2)); // 12
示例:
function MyObject(name, message) { this.name = name.toString(); this.message = message.toString(); this.getName = function() { return this.name; }; this.getMessage = function() { return this.message; }; } function MyObject(name, message) { this.name = name.toString(); this.message = message.toString(); } MyObject.prototype = { getName: function() { return this.name; }, getMessage: function() { return this.message; } }; function MyObject(name, message) { this.name = name.toString(); this.message = message.toString(); } MyObject.prototype.getName = function() { return this.name; }; MyObject.prototype.getMessage = function() { return this.message; };
继承与原型链
当谈到继承时,
JavaScript
只有一种结构:对象。每个实例对象(object
)都有一个私有属性(称之为__proto__
)指向它的构造函数的原型对象(prototype
)。该原型对象也有一个自己的原型对象(__proto__
) ,层层向上直到一个对象的原型对象为null
。根据定义,null
没有原型,并作为这个原型链中的最后一个环节。几乎所有
JavaScript
中的对象都是位于原型链顶端的Object
的实例。JavaScript
对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。遵循
ECMAScript
标准,someObject.[[Prototype]]
符号是用于指向someObject
的原型。从ECMAScript 6
开始,[[Prototype]]
可以通过Object.getPrototypeOf()
和Object.setPrototypeOf()
访问器来访问。这个等同于JavaScript
的非标准但许多浏览器实现的属性__proto__
。示例:
// 让我们从一个函数里创建一个对象o,它自身拥有属性a和b的: let f = function () { this.a = 1; this.b = 2; } /* 这么写也一样 function f() { this.a = 1; this.b = 2; } */ let o = new f(); // {a: 1, b: 2} // 在f函数的原型上定义属性 f.prototype.b = 3; f.prototype.c = 4; // 不要在 f 函数的原型上直接定义 f.prototype = {b:3,c:4};这样会直接打破原型链 // o.[[Prototype]] 有属性 b 和 c // (其实就是 o.__proto__ 或者 o.constructor.prototype) // o.[[Prototype]].[[Prototype]] 是 Object.prototype. // 最后o.[[Prototype]].[[Prototype]].[[Prototype]]是null // 这就是原型链的末尾,即 null, // 根据定义,null 就是没有 [[Prototype]]。 // 综上,整个原型链如下: // {a:1, b:2} ---> {b:3, c:4} ---> Object.prototype---> null console.log(o.a); // 1 // a是o的自身属性吗?是的,该属性的值为 1 console.log(o.b); // 2 // b是o的自身属性吗?是的,该属性的值为 2 // 原型上也有一个'b'属性,但是它不会被访问到。 // 这种情况被称为"属性遮蔽 (property shadowing)" console.log(o.c); // 4 // c是o的自身属性吗?不是,那看看它的原型上有没有 // c是o.[[Prototype]]的属性吗?是的,该属性的值为 4 console.log(o.d); // undefined // d 是 o 的自身属性吗?不是,那看看它的原型上有没有 // d 是 o.[[Prototype]] 的属性吗?不是,那看看它的原型上有没有 // o.[[Prototype]].[[Prototype]] 为 null,停止搜索 // 找不到 d 属性,返回 undefined
继承方法
var o = { a: 2, m: function(){ return this.a + 1; } }; console.log(o.m()); // 3 // 当调用 o.m 时,'this' 指向了 o. var p = Object.create(o); // p是一个继承自 o 的对象 p.a = 4; // 创建 p 的自身属性 'a' console.log(p.m()); // 5 // 调用 p.m 时,'this' 指向了 p // 又因为 p 继承了 o 的 m 函数 // 所以,此时的 'this.a' 即 p.a,就是 p 的自身属性 'a'
在 JavaScript 中使用原型
function doSomething(){} console.log( doSomething.prototype ); // 和声明函数的方式无关, // JavaScript 中的函数永远有一个默认原型属性。 var doSomething = function(){}; console.log( doSomething.prototype );
控制台:
{ constructor: ƒ doSomething(), __proto__: { constructor: ƒ Object(), hasOwnProperty: ƒ hasOwnProperty(), isPrototypeOf: ƒ isPrototypeOf(), propertyIsEnumerable: ƒ propertyIsEnumerable(), toLocaleString: ƒ toLocaleString(), toString: ƒ toString(), valueOf: ƒ valueOf() } }
给doSomething函数的原型对象添加新属性,如下:
function doSomething(){} doSomething.prototype.foo = "bar"; console.log( doSomething.prototype ); { foo: "bar", constructor: ƒ doSomething(), __proto__: { constructor: ƒ Object(), hasOwnProperty: ƒ hasOwnProperty(), isPrototypeOf: ƒ isPrototypeOf(), propertyIsEnumerable: ƒ propertyIsEnumerable(), toLocaleString: ƒ toLocaleString(), toString: ƒ toString(), valueOf: ƒ valueOf() } }
使用语法结构创建的对象
var o = {a: 1}; // o 这个对象继承了 Object.prototype 上面的所有属性 // o 自身没有名为 hasOwnProperty 的属性 // hasOwnProperty 是 Object.prototype 的属性 // 因此 o 继承了 Object.prototype 的 hasOwnProperty // Object.prototype 的原型为 null // 原型链如下: // o ---> Object.prototype ---> null var a = ["yo", "whadup", "?"]; // 数组都继承于 Array.prototype // (Array.prototype 中包含 indexOf, forEach 等方法) // 原型链如下: // a ---> Array.prototype ---> Object.prototype ---> null function f(){ return 2; } // 函数都继承于 Function.prototype // (Function.prototype 中包含 call, bind等方法) // 原型链如下: // f ---> Function.prototype ---> Object.prototype ---> null
使用构造器创建的对象
function Graph() { this.vertices = []; this.edges = []; } Graph.prototype = { addVertex: function(v){ this.vertices.push(v); } }; var g = new Graph(); // g 是生成的对象,他的自身属性有 'vertices' 和 'edges'。 // 在 g 被实例化时,g.[[Prototype]] 指向了 Graph.prototype。
使用 Object.create 创建的对象
可以调用这个方法来创建一个新对象。新对象的原型就是调用
create
方法时传入的第一个参数:var a = {a: 1}; // a ---> Object.prototype ---> null var b = Object.create(a); // b ---> a ---> Object.prototype ---> null console.log(b.a); // 1 (继承而来) var c = Object.create(b); // c ---> b ---> a ---> Object.prototype ---> null var d = Object.create(null); // d ---> null console.log(d.hasOwnProperty); // undefined, 因为d没有继承Object.prototype
使用
class
关键字创建的对象关键字包括
class, constructor,static,extends 和 super
。示例:
"use strict"; class Polygon { constructor(height, width) { this.height = height; this.width = width; } } class Square extends Polygon { constructor(sideLength) { super(sideLength, sideLength); } get area() { return this.height * this.width; } set sideLength(newLength) { this.height = newLength; this.width = newLength; } } var square = new Square(2);
❤️关注+点赞+收藏+评论+转发❤️,原创不易,鼓励笔者创作更好的文章
点赞、收藏和评论
我是
Jeskson
(达达前端),感谢各位人才的:点赞、收藏和评论,我们下期见!(如本文内容有地方讲解有误,欢迎指出☞谢谢,一起学习了)我们下期见!
github
收录,欢迎Star
:https://github.com/webVueBlog/WebFamily -
报表工具对比选型系列用例——排名及跨行组统计
2020-12-20 01:36:21排名与跨行组运算也是典型的中国复杂报表形式,这类报表的源数据集通常比较简单,但在表格的单元格之间会有较随意的计算要求。在制作报表时,单元格还没有扩展出来,因而不能像 Excel 那样直接引用单元格名字,报表...继《多源分片报表》后,我们继续考察这些报表工具对复杂报表的支持程度。
排名与跨行组运算也是典型的中国复杂报表形式,这类报表的源数据集通常比较简单,但在表格的单元格之间会有较随意的计算要求。在制作报表时,单元格还没有扩展出来,因而不能像 Excel 那样直接引用单元格名字,报表工具需要提供某种机制允许在表达式中引用还没有产生的单元格。
用例说明
报表式样
数据结构
[学生成绩表]
学生成绩表中存储各班级同学历年语文、数学、语文成绩信息
特点分析:
1、 报表中根据学生成绩既要做班级内排名,又要做年级内排名。
2、 报表中要列出去年班级内的名次,以用来展示该同学本学期较上学期的名次变化。
3、 要求统计出各班级内前三名的学号。
4、 要求统计出各班级内名次较上学期上升最快的三位同学的学号。
关于工作量的评估,我们仍假定使用者熟悉相应的报表工具,并只记录实际的制作和正常调试的时间,不包括查阅产品函数资料的时间。
润乾报表
制作过程:
1、 配置并连接数据源。
2、 设置参数及数据集
2.1 此报表要求查询出相应年度的学生成绩,所以需要通过传入参数控制具体展示哪年数据,报表中增加参数,参数名为 nd。
2.2 报表中既要统计所选年度数据,还需要和去年数据做比较,所以报表中要取出两年数据,这里为了方便制作和理解,建立两个数据集,分别取出两年数据,如:
ds1(取今年数据):
对应传入参数设置:
ds2(取去年数据)
数据集语法为 select * from xscj where nd=?
对应传入参数为:nd-1
两个数据集 SQL 语句完全一样,用 ? 代替变量,然后在参数中设置 ? 具体传入值,润乾在传入参数这不仅可以直接写入参数,也可以写入表达式先进行计算。
3、 设计报表模板
这个报表从展现形式上来看是一个分组报表,按照年级分组,列出各班级同学的成绩、排名等信息,然后在每个班级下再增加对应的汇总信息,下面介绍下主要单元格设置情况:
3.1、 A 列到 F 列单元格,都是普通的分组、取数等,按照常规设置就行, 其中 A3 单元格中,数据库里存储的是 1,2,3,4 这种数字格式,显示值表达式中写入:chn(int(value()))+“班”,将数字转换成中文
3.2、 G3 格:=count(F3[A3]{F3>$F3})+1,取出班级内的排名,润乾提供了排名计算方法,统计当前班级内成绩大于当前这人成绩的人员个数,然后再加 1,就是当前这个人的排名。
3.3、 H3 格:
,前边单元格统计了班级内排名,这个单元格中要统计整个年级的排名情况,表达式同 G3 类似,只不过 G3 中对 F3 计数时加了 [A3], 也就是表示取当年班级内的成绩排名,此处是 [`0],取所有成绩排名,这是润乾特有的层次坐标表示法,可以引用各个分组层次的单元格(及集合)。
3.4、 I3 格:=ds2.select(YUWEN+YINGYU+SHUXUE,bj==A3 && studentid==B3),因为报表中要列出去年的排名,所以这里要取出去年的总分情况,此列是辅助单元格,然后将这列隐藏掉就行。
3.5、 J3 格:=count(I3[A3]{I3>$I3})+1,去年成绩排名,一样的做法
3.6、 B4~K4,是个合并单元格,表达式:=disp(A3)+“成绩前三名同学是:”+B3{G3==1}+“,”+B3{G3==2}+“,”+B3{G3==3},A3 单元格在数据库中存储的是 1,2,3 这种形式,用 disp 函数取这个单元格的显示值,学号在 B3 单元格,在 G3 单元格中已经算出了排名,所以可以根据排名来获取对应的数据,B3{G3==1} 这个表达式表示取 G3 等于 1 的 B3 单元格的值,这样就取出了第一名的学号,后边两个同样的做法。
3.7、 B5~K5,合并单元格,表达式:=“班级名次上升最快的三位同学是:”+string(esproc(“?.m(?.ptop(-3))”,B3{},K3{})),这个单元格要求取出名次上升最快的三位同学,有多种做法,可以像排名那样,先对名次变化幅度做个排名,然后再根据幅度排名获取前三位,但是这种做法要增加辅助单元格。这里采用了另一做法,使用润乾内置函数 esproc,将 K3 单元格(名次变化幅度)传入,ptop(-3) 取最大的 3 位的位置,然后用 m() 函数根据位置取对应的姓名。esproc 函数允许在报表中引用润乾集算器的表达式,能组合出更为复杂丰富的运算 。
运行结果:
完成后点评
1、 用时 1 小时。报表主要难点排名、汇总统计等都用内置的函数或者特定的做法就行。
2、 函数功能强,像排名时用到的 count 函数,统计分析时的 esproc 函数等,只需要几个函数或者特定的语法就能够完成一些比较复杂的需求。
3、 底层模型强,润乾报表模型中提供了完善的层次坐标引用机制,对于排名计算中会涉及到跨行组之间的计算,直接用特定的语法就行,以及取班级前三名时,B3{G3==1},可以根据已有排名直接获取对应的数据。
4、 关联简单,比如这个报表要求取去年数据,为了简单起见,直接新建了个取去年数据的数据集,在报表中通过字段能直接将两个数据集数据关联在一起,这样制作起来比较方便,也比较易于理解。
帆软报表
制作过程:
1、 配置并连接数据源。
2、 设置参数及数据集
2.1、 参数设置,增加模板参数 p1, 参数类型为字符串,默认值为 2019.
2.2、 数据集设置,拖拽数据库表生成基础 sql, 添加 where 条件,其中数据集中引用参数使用 参数名,ds1:SELECT∗FROMDEMO.XSCJwherend=参数名,ds1:SELECT∗FROMDEMO.XSCJwherend={p1}, 算出参数对应年份的成绩信息。
2.3、 ds2:SELECT bj,studentid,yuwen+shuxue+yingyu zf,nd FROM DEMO.XSCJ where nd=${p1}-1,算出参数对应去年的成绩。
3、 设计报表模板
3.1 A3 单元格显示班级名称,数据库表该字段值是 1,2,3,4 这样的数据,需要设置公式形态 NUMTO(TOINTEGER($$$),true)+"班" 来达到效果。
3.2 G3 单元格的公式为:=count(F3[!0;!0]{A3 = A3 && F3 >A3 && F3 >F3}) + 1。
3.3 H3 单元格计算年级排名,单元格的公式为 =count(F3[!0;!0]{F3 >= $F3}) + 1。
3.4 在 I3 单元格中通过另一个数据集 ds2 取到对应去年的成绩,在高级中增加关联条件:(列名:BJ) 等于 ‘A3’ and (列名:STUDENGID) 等于 ‘B3’。
3.5 在 J3 单元格根据 I3 的去年成绩进行排名,公式为:=count(I3[!0;!0]{A3 = A3 && I3 >A3 && I3 >I3}) + 1。
3.6 在 B4 单元格里要动态显示对应每个班级的名称,帆软中没找到引用其他格子显示值的方法,所以在 B3 单元格表达式中为了得到 1 对应的大写一,表达式中又写了遍 NUMTO(TOINTEGER(A3,true))+“班成绩前三名同学学号是:”+B3{G3==1}+“,”+B3{G3==2}+“,”+B3{G3==3}。
3.7 为了能在 C5 格子得到名次上升最快的三位同学学号,增加了辅助列 L3,L3 的单元格表达式为:=count(K3[!0;!0]{A3 = A3 && K3 >A3 && K3 >K3}) + 1,先对每班的名次变化排了个名,然后对应取到排名为 1,2,3 的学生学号,C5 的单元格表达式为:NUMTO(TOINTEGER(A3,true))+“班班级名次上升最快的三位同学学号是:”+B3{L3==1}+“,”+B3{L3==2}+“,”+B3{L3==3}。
报表结果
完成后点评
1、 用时 1 小时左右。
2、 设计思路、操作过程、工具使用等大多数方法和润乾基本一致,这里就不一一细说了。
3、 帆软没有类似润乾 esproc 的函数,做名次上升最快的统计时,就需要通过增加辅助隐藏列来计算名次变化,增加了额外资源的耗用和开发工作量,当然本例单元格不多,影响不大。
4、 姓名列排序默认是按照 ASCII 排序,并不是按照常规的首字母方式,要按首字母排序要用 StringPinyin() 函数转换下,而且发现一般最后两个人的排序颠倒了,前两个文字的相同,最后一个帆(fan)应该在菲(fei)前边,这个暂时没找到原因。
Smartbi
制作过程
1、 配置并连接数据源。
2、 设置参数及数据集
2.1、 增加‘’年度”参数,参数名为 nianfen。
2.2、 准备数据集
因为要同时查去年成绩作对比,所以这里准备两个数据集(当年成绩、去年成绩、班级转换字典表)。
采用原生 SQL 数据集
当年成绩:
去年成绩:
班级在数据库中存储的是 1,2,3,4 这种,想显示成中文班级需要创建一个中文字典表数据集,数据结构如下:
数据集中直接用 SQL 语句:select * from bj 。
3、 设计报表模板
报表的设计在 excel 内完成,借助丰富的 excel 函数,smartbi 解决这种格间运算也不是太麻烦。如几个关键计算:
3.1 A5 单元格借助“转换规则”将 A5 中的班级通过班级的中文字典表转换成中文的班级名字。
3.2 班级排名(组内排序)G5:=RANK(F5,SSR_GetSubCells(F5,A5)) ,excel 的 RANK 函数和 smartbi 自身函数结合。
3.3 年级排名(组外或总排序)I5:=RANK(F5,(SSR_GetSubCells(F5)))
3.4 去年班级排名(组内排序)J5:与 G5 同理,只不过去年总分不需要显示,H 列为隐藏列
3.5 另外是班级前三及进步最快的学生,这个也可以实现,方法都是 excel 函数与 smartbi 函数的结合,不过写起来有点长。班级前三(B6):=A5&“成绩前三名同学学号是:”&INDEX(SSR_GetSubCells(B5,A5),MATCH(1,SSR_GetSubCells(G5,A5),0))&“,”&INDEX(SSR_GetSubCells(B5,A5),MATCH(2,SSR_GetSubCells(G5,A5),0))&“,”&INDEX(SSR_GetSubCells(B5,A5),MATCH(3,SSR_GetSubCells(G5,A5),0))
3.6 进步前三(B7):=“班级名次上升最快的三位同学学号是:”&INDEX(SSR_GetSubCells(B5,A5),MATCH(LARGE(SSR_GetSubCells(K5,A5),1),SSR_GetSubCells(K5,A5),0))&“,”&INDEX(SSR_GetSubCells(B5,A5),MATCH(LARGE(SSR_GetSubCells(K5,A5),2),SSR_GetSubCells(K5,A5),0))&“,”&INDEX(SSR_GetSubCells(B5,A5),MATCH(LARGE(SSR_GetSubCells(K5,A5),3),SSR_GetSubCells(K5,A5),0))
运行结果
完成后点评:
1、 用时:两小时左右,Smartbi 在 excel 中进行报表开发,比较符合常规使用习惯。
2、 完全在 excel 中操作,容易上手,操作起来比较方便。excel 函数丰富,这个报表主要是其查找类函数的使用。
3、 没有真实值和显示值的分类,在处理数据表的 bj(班级,数据为 1、2 等数值)字段以“一班”等形式呈现的时候,需要借助“转换规则”,先建转换规则,然后给业务数据集的字段选择规则,然后单元格属性勾选“使用显示值”这个东西是系统配置,也就是需要系统功能配合才能做到 ID 反显名称。
4、 提供有按层次访问单元格集合的机制,但层次坐标体系没有润乾和帆软做得简单,可以引用指定位置的单元格,但很麻烦,导致在做前三名统计时,表达式有点复杂。
永洪 BI
制作过程:
1、 配置并连接数据源。
2、 设置参数及数据集
2.1 增加参数“年度”
2.2 本例中要取上年,实际上也是个简单的多源关联报表,在之前制作多源关联报表时,永洪单元格内的多源关联有些问题,所以这里还是在数据集阶段进行处理,这里创建三个数据集:
数据集 1:学生成绩:用 SQL 语句取数,条件中加了个 nd=?{年度},年度是数据定义的传入参数,根据这个参数做数据过滤。并且根据三科成绩新增字段“总分”,班级字段在数据库中存的是数字,这里新增字段做值映射。
数据集 2:上学期成绩:因为要根据传入参数取上学期数据,所以此处增加条件:nd+1=?{年度}
数据集 3:学生成绩统计,新增“组合数据集”,将上述两个数据集通过班级和学号关联在一起:
3、 设计报表模板
3.1 班级列:按照班级进行分组,并且设置纵向三个单元格合并。
3.2 姓名列:取 studentid 字段的值扩展,设置父单元格为班级列
3.3 语文、英语、数学、总分四列,将相应字段按照“总和”方式拖拽到对应位置,注意,这里一定要是总和,否则后边排名会有问题。
3.4 班级排名:将总分字段按照求和方式拖拽到对应单元格,设置动态计算方式为“排名计算”,计算依据设置成“沿平面纵向”,并且设置“纵向父单元格”为 studentid 所在位置
3.5 年级排名:按照班级排名方式进行设置,最后设置计算依据为:“格子”。
3.6 上学期排名:按照班级排名操作,将上学期总分拖拽到对应单元格,并进行设置,数据集中通过组合数据集已经将上学期数据关联在一起。
3.7 名次变化:将单元格类型设置成“格间计算”,设置公式为:cell(ridx,8)-cell(ridx,6),永洪中没有 Excel 单元格概念,所以要用自己内部的一些语法,cell 函数可以根据行列号获取对应单元格的值,ridx 表示当前行号,8 表示报表中的第 9 列
3.8 成绩前三名统计:该单元格类型设置成“格间计算”,里边公式为:cell(ridx-10,0)+“成绩前三名同学是:”,此处做了个字符串拼接,cell(ridx-10,0),这个取对应的班级名称,ridx 是当前行号,现在每个班级都是 10 个人,所以此处减去 10,如果每个班级不同,那么还需要找单元格算出对应的数量才能获取。
3.9 前三名取法:设置单元格类型为“格间计算”,里边公式写入:
此处通过 js 的语法,对班级列做行列循环,然后获取名次 <=3 的行号,从而获取对应的学号,这里只是返回前三名,但是前三名的学号并不是第一的排最前边,如果要按照顺序,这个 js 脚本要写的比较复杂,这里就不做过多设置。
名次进步最快的三个同学,也是用格间计算 JavaScript 脚本方式,可以做出来,但是需要比较多的脚本来支持了,更多的是考验报表开发人员的变成能力了,这里就不做验证了。
注:这两行总结行虽说前边班级分组做了合并单元格,这里也要手动设置下纵向父单元格,否则无法做到跟随扩展。
运行结果
完成后点评
1、 用时约四小时,格间计算那几个单元格处理时间较长,比较考验开发能力,如果加上名次上升最快三位,需要更长时间。
2、 内置统计模型丰富,比如这里做排名,直接用内置方法排名计算就行,除了排名外还有其他方法供使用。
3、 组合数据集设置比较方便,这样可以将当年和上期数据在数据集阶段可以合成一个,可以不用再报表中关联。
4、 中文字典显示和排序不方便,比如班级在数据库中存的数字,想显示中文的话现在是在数据集里新增了键值映射,或者要通过字典表关联。报表单元格里要想显示中文,必须用中文字段,但是排序就会按照中文排序,要手动去调整,如果班级不固定,比较难调。
5、 单元格间计算不方便,比如和上学期的名次变化,在类 Excel 的开发工具中,直接引用单元格名称就可以一,但永洪只能用格间计算,并且里边要用自己的坐标方式,使用起来不太方便。
6、 做一些单元格汇总时,只能写格间计算,里边写入 javascript 脚本,虽说很灵活,但是难度较高,复杂的需要较多代码,开发周期长,多报表开发人员的技术水平要求更高
亿信
制作过程
1、 配置并链接数据源
2、 设置参数及数据集
2.1、 增加参数“nd”。
2.2、 在数据集中添加主题表,亿信报表计算时会根据报表单元格的设置生成 SQL 从主题表中取数,本例要取今年和去年数据,所以数据集中要取两年数据,直接用 SQL:select * from xscj where nd= or nd+1=
3、 设计报表模板
核心设置:
3.1 班级内部排名:=F3.rank
3.2 年级间排名:=F3$$.rank(F3),本例中只有两层排名,班级排名是最内层排名,年级排名是最外层排名,两个排名使用 rank 函数就行,如果中间还有其他层级需要排名,就不能这么做了,需要增加辅助单元格,下面通过一个省、市、县三级来看下多层级排名的使用。
县排名和省排名,一个是最内层一个是最外层,所以表达式就是之前提到的,而市级排名需要增加辅助行,第三行,首先将 A2 和 A3 合并,这个就相当于其他工具的左主格设定,然后在 E3 单元格中写入表达式:=GRID1.E2$.join(“,”),取当前省内对应的 E2 的值拼成一个字符串,然后在市排名的 G2 单元格中写入表达式:=asstr(GRID1.E3).split(“,”).rank(E2),取 E3 的值按逗号分割后排序回填到对应位置。**
3.3 报表中要取当前学期和上学期的数据,在《多源关联分片》测试中看到,亿信多源关联会有些限制,所以本例中并没有采用润乾或者帆软那种多数据集形式,而是在数据集中取出了两年的数据,然后在报表单元格里加指标限定条件,比如上学期数据配置指标的过滤条件:
3.4 获取成绩前三名同学学号:=B3[G3[G3.FIND(“1”)]+“,”+B3[G3[G3.FIND(“2”)]+“,”+B3[G3[G3.FIND(“3”)],B3[G3[G3.FIND(“1”)] 表达式含义:班级是个合并格,G3.FIND(“1”)表示取出当前班级内的G3等于1的值所在的位置,然后B3.FIND(“1”)表示取出当前班级内的G3等于1的值所在的位置,然后B3[] 根据这个位置取到对应 B3 的值,也就是取到排名第一的人的姓名,其余类似。
3.5 班级名次上升最快的三位同学学号:=K3$.sort().mid(0,3).select(true,@.leftcell(9).txt).join(“,”),其中,.sort 是将 K3 浮动出来的数据降序排序,mid(0,3) 是取排序后的前三项(即前三名),select 的作用的取这前三名对应的 B2 表元的值(字号列),join 是把前面返回的结果用逗号隔开转成字符串
运行结果
完成后点评:
1、 制作用时:1.5 小时
2、 内置排名函数比较丰富,可以直接使用实现排名计算;求前 N 条最大值等操作
3、 各个指标(科目成绩)之间可以划定不同的条件范围,可以直接取出来去年的数据。
4、 ID 转 NAME 时只能通过维表设置,也就是必须在数据库中额外添加一个码表,显示值配置不简便灵活;
5、 rank 函数只支持重复排名,_rk 虽然可以实现不重复排名,但是会改变数据的结果顺序,而且只支持指标字段,不支持具体的单元格 / 表元;
6、 本例取两个学期的数据对比,可以制作两个数据集通过关联字段关联在一起,也可以直接在数据集中取出两学期数据,然后在报表单元格通过年度参数进行数据过滤,亿信这里采用的是后者,在单元格中加条件来限定是取今年成绩还是去年成绩,当然这个其他工具也都支持,就是一个单元格过滤。
7、 没有层次坐标体系。两级排名还可以用相对固定的方法,比如最内层:=F3.rank,最外层:=F3$$.rank(F3)。如果还有更多层,那么需要增加辅助单元格取这个层级下需要排名的数值,比如数值在 E2 单元格中,那么需要在辅助单元格中(比如 E3)写入:=GRID1.E2$.join(“,”)****,这个是获取到当前层级下的 E2 的值用逗号做为分割符拼接在一起,然后在需要显示的排名的地方写入:=asstr(GRID1.E3).split(“,”).rank(E2),这样才能生成排名,如果层级还增多的话,那么需要大量的辅助单元格,操作上会相当繁琐。
总结
本例大体还是能延续上一例《多源分片报表》的结论:
这个例子也是各家产品都能实现,基本的排名运算都没有问题。
对于本例中重点考查的跨行组运算,润乾与帆软都提供了较完善的层次坐标机制,对付这种格间运算毫无压力。Smartbi 也有类似的概念,但语法体系设计得很烦琐,写起来复杂度要高很多。而永洪就没有层次坐标体系了,应对这种跨行组的格间运算比较吃力,需要写出有过程的 js 代码,可以说对格间运算基本就没有像样的支持,和前面三款产品的差距相当大。亿信看起来实现比较简单,但其实也没有层次坐标体系来应对通用的跨行组运算模型,只是凑巧有这样几个内置函数,深究下来,和永洪是一个档次的,只是因为有内置函数而略微胜出。也就是说,润乾和帆软在这方面属于成熟产品,Smartbi 基本算是及格,而永洪和亿信都不能算及格了,永洪更弱一点。
润乾和帆软相比,报表扩展与引用模型区别不大,但计算模型却有差距。润乾增加了特有的计算引擎,对于更复杂的运算情况就会有明显优势了(本例中的 esproc 函数)。帆软复制了润乾报表模型大部分内容,但计算引擎是润乾后加的,而且内容非常丰富,就没有那么容易复制过去了。
相关链接
-
Elasticsearch Bucket Aggregations示例
2020-02-13 17:05:20根据 Elasticsearch 的机制,每个分片都会根据各自拥有的数据进行计算并且进行排序,最后协调节点对各个分片的计算结果进行整理并返回给客户端。而就是因为这样,产生出精度的问题,也就是计算的结果有误差。 下面... -
tableau prep学习
2020-12-20 15:56:31数据计算:可以实现跨越层级的数据计算,可以进一步把数据计算字段,加入到数据准备阶段。 数据流Flow:最后把数据清理的结果,以数据流的形式展现出来。 二.数据整理 1、Connect to Data 连接数据 在这一步,可以... -
powerbi 笔记
2021-01-04 00:13:40) 四、计算行数 [订单数量]=Countrows(‘销售表’) 五、其它函数 CountA函数:计算列中单元格不为空的数目 Countblank函数:计算列中单元格为空白数量 Distinctcount函数:计算列中非重复值的数量 举例: 单店销售量... -
利用poi实现对数据清洗
2021-04-30 15:21:30ps:那么我们该怎么实现数据清洗呢,我们的做法是对爬虫获取到的数据实现统计求和或者去重排序等 导读模块:我们本次的清洗就是将三个excel中的薪水,进行归类统计,对面议和其他等这些情况的薪水忽略不计 2.1.... -
Excel基础操作
2022-04-24 16:36:59选择性粘贴2 第二十五节-单元格样式和套用表格格式 第二十六节-条件格式1 第二十七节-条件格式2 第二十八节-条件格式3 第二十九节-排序 第三十节-筛选 第三十一节-高级筛选 第三十三节-自动求和 第三十四节和第三十... -
【YOLOV5-5.x 源码解读】metrics.py
2021-08-09 21:11:42i: 记录着所有预测框是否是c类别框 是c类对应位置为True, 否则为False i = pred_cls == c # n_l: gt框中的c类别框数量 = tp+fn 254 n_l = (target_cls == c).sum() # number of labels # n_p: 预测框中c类别的框数量... -
Excel-Countif函数对重复值的处理之删除、统计和标记
2020-09-03 10:12:29函数解释: =countif(range,criteria) #COUNTIF 是一个统计函数,用于统计满足某个条件的单元格的数量。 #range:要查找的区域;criteria:要查找的的内容,返回该内容出现的次数。 第一步:在H2单元格英文状态... -
[python][科学计算][pandas]使用指南
2019-04-20 15:06:50使用指南6 - 排序与去重 (直接与间接排序,去重) 使用指南7 - 乱序与抽样 (随机排序,抽样) 使用指南8 - 读写 (读写csv,读写excel,读写sql) 使用指南9 - 快速绘图 (曲线图,条形图,直方图,箱线图,散点图... -
论文阅读笔记01:YOLO v1(You Only Look Once: Unified, Real-Time Object Detection)
2021-02-07 09:57:44... 这是一篇目标检测领域的文章,发布于2016年。 Introduction 在Yolo被提出之前,DPM和R-...R-CNN使用选取潜在的候选区域,然后运行分类器,分类后细化并去重;(缺点:慢、难以优化、单独的组件要单独训练) Yolo -
数据库系统原理(BNU_党德鹏_慕课)超详细听课笔记
2022-01-13 13:20:59 条件连接:在笛卡尔积的基础上,选取满足给定条件的元组 首先计算笛卡尔积 然后选取满足给定条件的元组 examinee和department按照examine.dname = eeexam.dname进行联接 条件联接查询 赋值 赋值运算是将←... -
回溯算法建立在 DFS 基础之上,在搜索过程中,达到结束/裁剪条件后,恢复状态,回溯上一层,再次搜索】
2021-06-14 22:38:15res = [] path = [] def backtrack(未探索区域, res, path): if 未探索区域满足结束条件: res.add(path) # 深度拷贝 return for 选择 in 未探索区域当前可能的选择: if 当前选择符合要求: path.add(当前选择) ... -
MySQL核心技术学习笔记
2021-02-22 17:08:25语句执行顺序 FROM:指定数据来源表,将存储的表文件加载到内容 WHERE:对查询数据做第一次过滤,生成一张新的临时表 GROUP BY:分组,生成若干个临时表 HAVING:对分组后的数据做第二次过滤,排除掉不符合条件的... -
CDA LEVELⅠ2021最新模拟题一(全网最详细有答案)
2021-04-21 15:51:04完整性约束是为了防止不符合规范的数据进入数据库,在用户对数据进行插入、修改、删除等操作时,DBMS自动按照一定的约束条件对数据进行监测,使不符合规范的数据不能进入数据库,以确保数据库中存储的数据正确、有效... -
拼多多2020学霸批数据分析师笔试 —— SQL整理(2019.7.28)
2019-08-14 08:50:50也就是说,只有这一个连续操作是符合条件的。 完整代码 CREATE VIEW view1 AS (SELECT user_id, log_time, opr_type, row_number() over (PARTITION BY log_time ORDER BY user_id) AS flag FROM ... -
专升本信息技术
2022-04-24 20:27:12> 扩展大脑功能的计算(处理)与存储技术。 > 扩展效应器官功能的控制与显示技术。 具体案例:雷达、卫星遥感等感测与识别技术使人们的感知范围、感知精度和灵敏度大为提高:电话、电视、因特网(Internet)等... -
用户行为分析的基本概览和常用名词解释
2021-09-22 17:11:04筛选条件分类 按目标 筛选用户:筛选条件作用于用户表,只看符合筛选条件的那些用户;一般在用户属性上进行条件设置,或者选择用户分群获取符合分析条件的用户。 筛选事件:筛选条件作用于事件,只看符合筛选条件的... -
pandas打印某一列_Pandas-01之DataFrame&Series
2020-11-20 01:35:28pandas.DataFrame中取某几行 pandas.DataFrame中按一个条件过滤行 pandas.DataFrame中按多个条件过滤行 pandas.DataFrame中结合map 和lambda函数过滤行 pandas.DataFrame中结合isin过滤行 pandas.DataFrame中取某... -
23篇大数据系列(三)sql基础知识(史上最全,建议收藏)
2021-06-26 19:30:33ON 后面跟关联条件 WHERE 后面跟过滤条件,只有满足条件的行才会保留下来 GROUP BY 后面跟用来分组的列或计算公式 HAVING 后面跟分组后的过滤条件 ORDER BY 后面跟用于排序的列或计算公式 LIMIT 从结果中选取前N行,... -
EXCEL如何将分表中的数据汇总到总表 - 卡饭网
2020-12-19 15:31:55打开需要处理的工作簿,在这个工作簿中,"11月采购表"和"12月采购表"工作表包含需要合并的数据,如图1所示."合计"工作表用于放置进行合并计算后的数据,其结构如图2所示. 图1 需要合并的两张工作表 图2 "合计"工作表的... -
[工作必备]pandas数据分析处理52个常用技巧
2021-04-22 20:52:20pandas工具包类似于python中的excel, 在excel中的筛选、排序、计算、透视、vlookup、分类汇总等操作用python如何实现呢? 本文精心整理的pandas数据处理与分析的51个技巧, 100多个知识点 这么多技巧除了收藏, 如何... -
CDA Level1知识点总结之数据库应用
2021-09-13 10:19:17select fname, fcity, fsalary, count(*) over() 工资小于5000员工数 from t_person where fsalary 在上边的例子中,开窗函数 COUNT(*) OVER()对于查询结果的每一行都返回所有符合条件的行的条数。OVER 关键字后的... -
转录组功能分析数据库及富集分析
2022-03-16 21:08:0810) #初筛样本表达基因 rownames(res2) degs.list=as.character(res2$symbol)[select.FPKM] #提取res2 基因名列符合筛选条件的基因名 res3=distinct(res2,symbol,.keep_all = T) #去重 rownames(res3)=res3$symbol #... -
PART 1:基于大数据人才岗位招聘情况对数据进行清洗、初步分析
2021-04-01 00:51:38提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、文本函数二、数学函数1.常使用的函数2.统计指标(1)集中趋势指标:平均数、中...功能:对数值类数据进行计算。(数学换算、统计 -
人人都能学会数据分析-笔记
2022-02-14 13:57:24是对数值类数据进行计算 基本功能:数学换算、统计、类型转换 计算集中趋势、离散趋势 课后作业 计算集中趋势指标:平均值、中位数、众数 1-4 处理重复数据 数据预处理的重要性 清洗、格式化、去重、排序、基础计算 ... -
CDA LEVELⅠ2021新版模拟题二(附答案)
2022-05-15 16:07:51完整性约束是为了防止不符合规范的数据进入数据库,在用户对数据进行插入、修改、删除等操作时,DBMS自动按照一定的约束条件对数据进行监测,使不符合规范的数据不能进入数据库,以确保数据库中存储的数据正确、有效... -
sql查询语句
2022-02-17 08:20:57Mysql查询语句分组统计分页查询分组增强数据分组总结多表查询自连接子查询all_any子查询临时表多列子查询子查询练习合并查询外连接自增长自我复制 ...分页查询表示从start + 1行开始取取出rows行,start从0开始计算 SE