JS函数
函数传参
需要注意的是,JS中的函数传参都是按值传递的,这意味着不管参数是基本数据类型还是引用数据类型,函数外传进去的值都会被复制到函数内部,对于引用类型,可以理解为:函数内创造了一个自己的指针指向传入的这个引用类型参数
例子:
1 | // 第一段代码 |
从上述例子可以看出,函数内部的person并不是我们传入的pp对象本身,而是函数新创造的一个和pp指向同一片内存的指针。一旦person被重新赋值,将无法再修改传入的参数。
模板字面量标签函数
模板字面量支持自定义标签函数,标签函数本身是一个普通函数,通过前缀到模板字面量来应用自定义行为
1 | function tag(strings, ...expressions) { |
数组函数
Array.from
是一个静态方法,从 可迭代对象 或 类数组对象【带有length属性和索引元素的对象】 创建一个新的浅拷贝 的数组实例
参数有三个:
Iterable:可迭代对象或类数组对象?mapFn:可选参数,每个将要添加到数组的值会首先传递给该函数,该函数接受两个参数: element正在处理的元素和index 索引?thisArg:可选参数,是执行mapFn时用的this
例子
1 | // 从字符串生成数组 |
待理解
from() 方法可以在任何构造函数上调用,只要该构造函数接受一个表示新数组长度的单个参数。
1 | function NotArray(len) { |
当this不是一个构造函数,返回一个普通数组对象
1 | console.log(Array.from.call({}, {length:1,0: "ff"})) |
转换异步的可迭代对象到数组,可使用Array.fromAsync()方法
Array.prototype.flat
flat方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回
1 | const arr = [1,2,3,[2,3,4,[5,6]], 8]; |
Array.prototype.indexOf()、lastIndexOf()、index()使用严格相等算法(即===),需要注意的是 NaN == NaN 为false
Array.prototype.includes() 是一个零值相等算法(零值相等不作为API公开,详见下一节笔记),NaN值视作相等
函数防抖和节流
通过定时器来减少不必要的函数调用频率,得到更好的用户体验和性能。指定的行为在停止指定时间后,再执行对应任务,
一个频繁执行的函数,在规定的时间内,只在最后一次触发执行,场景:输入框提示语,避免每次输入都发送请求;登录、发送按钮,用户点击太快,发送多次请求。关键在于清零,比如在点击登录后1s再发送请求,设置一个定时器,用户每次操作都会清零这个定时器,只有用户停止操作规定时间才会发送请求
1 | /** |
一个频繁操作的函数,在执行过一次后,只有经过规定的时间才会执行第二次,在规定时间内,函数只会执行一次,场景:每隔1s更改一次播放进度;每隔1s计算一次scroll高度,需要两个时间 lastTime 和 nowTime 来计算时间差 由此来判断是否执行事件 先将lastTime初始化为0 然后获取系统时间 做差判断是否大于delay 如果大于则执行事件并将nowTime赋予lastTime 由此完成节流。
1 | /* |
函数(柯里化)currying
把接受多个参数的函数变化成接受一个单一参数(最初函数的第一个参数)的函数,返回一个接受剩下参数的新函数
1 | //curring前 |
1 | curring化的好处在于: |
compose函数
1 | compose = (fn1,fn2) => c =>fn1(fn2(c)); |
function的length
function函数的length等于 第一个具有默认值的参数之前的参数个数,剩余参数(即function(…fn))不参与length计算
1 | function f1(x,y) |
bind/call/apply
这三个函数的功能都是把函数绑定到某个对象,使函数体内的this指向bind/call/apply函数的第一个参数。方法的第一个参数即函数的this指向,即函数f内的this将指向对象{z:1},后面的函数会依次传递给原始函数,即bind的第二个参数3将传递给函数f
call的第二第三个函数是依次传递给原始函数的,apply的所有参数放在一个数组里面传递进去bind返回的是一个新函数,参数和call一样是多个,逗号隔开的。
1 | let f=function(x,y){ |
bind函数的返回值时绑定了this的新函数,它不是立即执行的
【more】
非严格模式下:如果传递的第一个参数是一个基本类型,会被包装成对象;传入null或undefined时会被绑定为全局对象
严格模型下:传啥就是啥
参考文档:https://segmentfault.com/a/1190000002640298
console.log
console.log 会尝试将接收的所有参数转换为字符串,针对不同类型会有不同的处理
- 对原始类型,它们的toString()方法会被调用,输出相应的字符串表示
- 对函数对象,取决于不同的js环境
- 对普通对象,通常不会直接调用
setTimeout 和 setInterval
当传入的第二个参数是0ms,实际的执行时间并不一定会像预想的那样立即实现,具体来说,延时设置为0意味着这个任务被立即放入了微任务队列中,但是这个队列什么时候能执行到这个回调函数,是未知的
HTML5规定:一旦对 setTimeout 的嵌套调用被安排了 5 次,浏览器将强制执行 4 毫秒的最小超时。浏览器内部以 32 位带符号整数存储延时。这就会导致如果一个延时大于 2147483647 毫秒(大约 24.8 天)时就会溢出,导致定时器将会被立即执行。
为了优化后台标签的加载损耗(以及降低耗电量),浏览器会在非活动标签中强制执行一个最小的超时延迟
占位符
1 | // %s %d %i(整数) %f %o %O(obj) %c(css样式) 等占位符在console.log中同样适用 |
class的静态方法
静态方法被设计为只能被创建它们的构造器使用,不能传递给实例,无法被实例使用。
JS API
toLocaleString
mdntoLocaleString()返回这个数字在特定语言环境下的表示字符串
语法
1 | toLocaleString([locales[,options]]); |
参数
locales:可选参数,带有BCP 47语言标记的字符串或字符串数组,用来表示要转为目标语言的类型
options:可选参数,用来配置属性对象。{style: ‘xxx’, }
| style可选值 | 注释 |
|---|---|
| decimal | 纯数字格式(默认) |
| currency | 货币格式 |
| percent | 百分比格式 |
| unit | 单位格式 |
当options.style === ‘currency’时,需要增加options.currency属性
| currency可选值 | 注释 |
|---|---|
| USD | 美元格式 |
| EUR | 欧元格式 |
| CNY | 人民币格式 |
- 将date对象转成字符串形式
1
2
3
4
5
6
7
8
9const now = new Date()
now.toLocaleString() // "2022/1/12 下午4:59:49"
const num = 12876431
num.toLocaleString('zh', {style: 'currency', currency: 'usd'}) // 'US$1,231,124.00'
num.toLocaleString('zh', {style: 'currency', currency: 'cny', currencyDisplay: 'name'})// '1,231,124.00人民币'
let arr = [12,'56']
arr.toLocaleString('zh') //'12,56'
typeof
typeof 操作符会返回变量的基本类型
哪些情况下typeof会返回'undefined'
typeof undefined === 'undefined'- 对一个未声明的变量使用
typeof会返回'undefined',但对处于’暂时性死区‘的变量使用typeof会抛出ReferenceError - 对未定义的对象属性使用
typeof - 未定义的函数参数使用
typeof,如果在函数调用时,某个参数未传参,在函数内访问此变量会是undefined
使用Object.prototype.toString.call()检测数据类型
object.prototype.toString()方法返回对象的字符串表示,当调用一个对象的toString()方法时,它会返回一个表示该对象的字符串。这个字符串通常包含对象的类名和内部标识符,可以用来识别对象的类型和内容。
1 | // 判断目标变量的数据类型 |
Date对象
1 | // Date对象格式化方法 |
Object.defineProperty
使用Object.defineProperty方法定义的对象属性
- 默认不可被枚举,即(Object.keys中没有)
- 默认不可改变
1 | const person = { |
createElement
createElementNS
1 | document.createElementNS(ns, name); |
创建一个带有指定命名空间的元素节点,返回一个element元素
scrollIntoView方法
有三种方式
1 | scrollIntoView() |
scrollIntoViewOptions包含3个属性:behavior, block, inline
behavior定义滚动行为。可选值:
- **
smooth**: 平滑滚动 - **
instant**:直接跳转 - **
auto**:默认值。由css属性scroll-behavior 决定
block定义垂直方向的对齐方式,可选值
- **
start**:默认值。与滚动容器顶部对齐 - **
center**:与滚动容器居中对齐 - **
end**:与滚动容器底部对齐 - **
nearest**:在视野范围内就不滚动,否则滚动到顶部或底部中较近的那个
inline定义水平方向的对齐方式,和block一样,可选值:
- **
start**:元素左侧和滚动容器左侧对齐 - **
center**:元素和滚动容器居中对齐 - **
end**:元素右侧和滚动容器右侧对齐 - **
nearest**:默认值。如果已经在视野范围内,就不滚动,否则就滚动到左边或者右边(哪个更靠近就滚到哪里)
使用CSS属性scroll-margin可设置scrollIntoView滚动距离边界的边距。
scrollIntoViewIfNeeded方法可做到只需要在滚动定位的时候才会滚动,和nearest类似,但同时又满足了center。兼容性如下:
字符串类型的replace函数
接受两个参数:
- 第一个是一个RegExp对象或者一个字符串,当传递字符串时只会匹配第一个子串,传递正则表达式并携带全局标记时可替换所有子串。
- 第二个参数是一个字符串或一个函数。当传递字符串时,可以用几个特殊的字符序列来插入正则表达式操作的值
| 字符序列 | 替换文本 |
|---|---|
$$ |
$ |
$& |
匹配整个模式的子字符串 |
$' |
匹配的子串之前的字符串 |
| $` | 匹配的子串之后的字符串 |
$n |
匹配的第n个捕获组的字符串,$n>=0;n<=9$ |
$nn |
匹配的第nn个捕获组的字符串 |
| 当传递的是一个函数时,如果只有一个匹配项,这个函数接受三个参数: | |
match:对整个正则匹配项而言,模式匹配的字符子串 |
|
pos:匹配项在整个字符串中的开始位置 |
|
originalText:以及整个字符串。 |
|
| 如果有多个匹配项,在原来三个参数的基础上,还会把对每一个匹配项匹配到的字符串传进去,假设有n个匹配项参数会变成: |
- match 匹配整个正则的子串
- p1 第一个匹配项捕获到的部分
- p2 第二个匹配项捕获到的部分
- …
- pn 第n个匹配项捕获到的部分
- pos
- originalText
参数的最后两个始终是模式匹配的开始位置和原始字符串
console
==console.log/error/warning==
日志/错误/警告打印
1 | console.log({name, age, grade}); |
==console.time + console.timeEnd==
计算代码段执行时间
==console.assert断言==
1 | console.assert(false, 'is false') |
==console.dir==
打印dom节点
1 | console.dir($0); |