js综合笔记
if else
var s = '123'; if (s.length) { // 条件计算结果为3 // }
JavaScript把null
、undefined
、0
、NaN
和空字符串''
视为false
,其他值一概视为true
,因此上述代码条件判断的结果是true
。
iterable
遍历Array
可以采用下标循环,遍历Map
和Set
就无法使用下标。为了统一集合类型,ES6标准引入了新的iterable
类型,Array
、Map
和Set
都属于iterable
类型。
具有iterable
类型的集合可以通过新的for ... of
循环来遍历。
用for ... of
循环遍历集合,用法如下:
var a = ['A', 'B', 'C']; var s = new Set(['A', 'B', 'C']); var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]); for (var x of a) { // 遍历Array console.log(x); } for (var x of s) { // 遍历Set console.log(x); } for (var x of m) { // 遍历Map console.log(x[0] + '=' + x[1]); }
你可能会有疑问,for ... of
循环和for ... in
循环有何区别?
for ... in
循环由于历史遗留问题,它遍历的实际上是对象的属性名称。一个Array
数组实际上也是一个对象,它的每个元素的索引被视为一个属性。
当我们手动给Array
对象添加了额外的属性后,for ... in
循环将带来意想不到的意外效果:
var a = ['A', 'B', 'C']; a.name = 'Hello'; for (var x in a) { console.log(x); // '0', '1', '2', 'name' }
for ... in
循环将把name
包括在内,但Array
的length
属性却不包括在内。
for ... of
循环则完全修复了这些问题,它只循环集合本身的元素:
var a = ['A', 'B', 'C']; a.name = 'Hello'; for (var x of a) { console.log(x); // 'A', 'B', 'C' }
这就是为什么要引入新的for ... of
循环。
然而,更好的方式是直接使用iterable
内置的forEach
方法,它接收一个函数,每次迭代就自动回调该函数。以Array
为例:
'use strict'; var a = ['A', 'B', 'C'];
a.forEach(function (element, index, array) { // element: 指向当前元素的值 // index: 指向当前索引 // array: 指向Array对象本身 console.log(array+'中'+element + ', index = ' + index); });
Set
与Array
类似,但Set
没有索引,因此回调函数的前两个参数都是元素本身:
var s = new Set(['A', 'B', 'C']); s.forEach(function (element, sameElement, set) { console.log(element); });
Map
的回调函数参数依次为value
、key
和map
本身:
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]); m.forEach(function (value, key, map) { console.log(value); });
如果对某些参数不感兴趣,由于JavaScript的函数调用不要求参数必须一致,因此可以忽略它们。例如,只需要获得Array
的element
:
var a = ['A', 'B', 'C']; a.forEach(function (element) { console.log(element); });
Web 计时
Web 计时机制的核心是 window.performance 对象。对页面的所有度量信息,包括那些规范中已经定义的和将来才能确定的,都包含在这个对象里面。Web Timing 规范一开始就为 performance 对象定义了两个属性。
其中,performance.navigation 属性也是一个对象,包含着与页面导航有关的多个属性,如下所示
redirectCount:页面加载前的重定向次数。
type:数值常量,表示刚刚发生的导航类型。
performance.navigation.TYPE_NAVIGATE (0):页面第一次加载。
performance.navigation.TYPE_RELOAD (1):页面重载过。
performance.navigation.TYPE_BACK_FORWARD (2):页面是通过“后退”或“前进”按钮打开的。
nloadEventStart:前一个页面的 unload 事件开始的时间。但只有在前一个页面与当前页面来自同一个域时这个属性才会有值;否则,值为 0。
unloadEventEnd:前一个页面的 unload 事件结束的时间。但只有在前一个页面与当前页面来自同一个域时这个属性才会有值;否则,值为 0。
redirectStart:到当前页面的重定向开始的时间。但只有在重定向的页面来自同一个域时这个属性才会有值;否则,值为 0。
redirectEnd:到当前页面的重定向结束的时间。但只有在重定向的页面来自同一个域时这个属性才会有值;否则,值为 0
fetchStart:开始通过 HTTP GET 取得页面的时间
domainLookupStart:开始查询当前页面 DNS 的时间。
domainLookupEnd:查询当前页面 DNS 结束的时间。
connectStart:浏览器尝试连接服务器的时间。
connectEnd:浏览器成功连接到服务器的时间。
secureConnectionStart:浏览器尝试以 SSL 方式连接服务器的时间。不使用 SSL 方式连接时,这个属性的值为 0。
requestStart:浏览器开始请求页面的时间。
responseStart:浏览器接收到页面第一字节的时间
responseEnd:浏览器接收到页面所有内容的时间。
domLoading:document.readyState 变为"loading"的时间。
domInteractive:document.readyState 变为"interactive"的时间。
domContentLoadedEventStart:发生 DOMContentLoaded 事件的时间。
domContentLoadedEventEnd:DOMContentLoaded 事件已经发生且执行完所有事件处理程序的时间。
domComplete:document.readyState 变为"complete"的时间。
loadEventStart:发生 load 事件的时间。
loadEventEnd:load 事件已经发生且执行完所有事件处理程序的时间。
谷歌控制台打开如下:
8年javascript知识点积累 https://www.cnblogs.com/tylerdonet/p/5543813.html
函数柯里化在程序中的应用 (转载掘金 https://juejin.im/post/5be5b5a65188250fa835897e)
1、编写轻松重用和配置的小代码块,就像我们使用npm一样:
举个例子,比如你有一间士多店并且你想给你优惠的顾客给个10%的折扣(即打九折):
function discount(price, discount) { return price * discount }
当一位优惠的顾客买了一间价值$500的物品,你给他打折:
const price = discount(500,0.10); // $50 // $500 - $50 = $450
你可以预见,从长远来看,我们会发现自己每天都在计算10%的折扣:
const price = discount(1500,0.10); // $150 // $1,500 - $150 = $1,350 const price = discount(2000,0.10); // $200 // $2,000 - $200 = $1,800 const price = discount(50,0.10); // $5 // $50 - $5 = $45 const price = discount(5000,0.10); // $500 // $5,000 - $500 = $4,500 const price = discount(300,0.10); // $30 // $300 - $30 = $270
我们可以将discount函数柯里化,这样我们就不用总是每次增加这0.01的折扣。
function discount(discount) { return (price) => { return price * discount; } } const tenPercentDiscount = discount(0.1);
现在,我们可以只计算你的顾客买的物品的价格了:
tenPercentDiscount(500); // $50 // $500 - $50 = $450
同样地,有些优惠顾客比一些优惠顾客更重要-让我们称之为超级客户。并且我们想给这些超级客户提供20%的折扣。 可以使用我们的柯里化的discount函数:
const twentyPercentDiscount = discount(0.2);
我们通过这个柯里化的discount函数折扣调为0.2(即20%),给我们的超级客户配置了一个新的函数。 返回的函数twentyPercentDiscount将用于计算我们的超级客户的折扣:
twentyPercentDiscount(500); // 100 // $500 - $100 = $400 twentyPercentDiscount(5000); // 1000 // $5,000 - $1,000 = $4,000 twentyPercentDiscount(1000000); // 200000 // $1,000,000 - $200,000 = $600,000
2、避免频繁调用具有相同参数的函数
举个例子,我们有一个计算圆柱体积的函数
function volume(l, w, h) { return l * w * h; }
碰巧仓库所有的气缸高度为100米,你将会看到你将重复调用此函数,h为100米
volume(200,30,100) // 2003000l volume(32,45,100); //144000l volume(2322,232,100) // 53870400l
要解决以上问题,你可以将volume函数柯里化(像我们之前做的):
function volume(h) { return (w) => { return (l) => { return l * w * h } } }
我们可以定义一个专门指定圆柱体高度的的函数:
const hCylinderHeight = volume(100); hCylinderHeight(200)(30); // 600,000l hCylinderHeight(2322)(232); // 53,870,400l
通用的柯里化函数
我们来开发一个函数,它接受任何函数并返回一个柯里化版本的函数。 要做到这点,我们将有这个(虽然你的方法可能跟我的不一样):
function curry(fn, ...args) { return (..._arg) => { return fn(...args, ..._arg); } }
function volume(l,h,w) { return l * h * w } const hCy = curry(volume,100); hCy(200,900); // 18000000l hCy(70,60); // 420000l