# 数组
arr.flat(depth) // new 将指定深度的元素与最外层元素合并
# 基础
# bigint
js的最新类型。通过在数字后面加n
定义.
在JS中,按照IEEE 754-2008 (opens new window)标准的定义,所有数字都以双精度64位浮点 (opens new window)格式表示。JS 中的Number
类型只能安全地表示-9007199254740991 (-(2^53-1))
和9007199254740991(2^53-1)
之间的整数,任何超出此范围的整数值都可能失去精度(四舍五入)。
console.log(9999999999999999)
// 10000000000000000
console.log(9999999999999999n)
// 9999999999999999n
typeof 9999999999999999n
// "bigint"
# globalThis
全局对象
// 浏览器环境下
globalThis === window // true
# 位运算符
位逻辑运算符工作流程如下:
- 操作数被转换为32bit整數,以位序列(0和1组成)表示.若超過32bits,則取低位32bit
- 第一个操作数的每一位都与第二个操作数的对应位组对: 第一位对应第一位,第二位对应第二位,以此类推.
- 运算符被应用到每一对"位"上, 最终的运算结果由每一对“位”的运算结果组合起来.
15 & 9 // 9 1111 & 1001 = 1001
15 | 9 // 15 1111 | 1001 = 1111
15 ^ 9 // 6 1111 ^ 1001 = 0110
~15 // -16 ~00000...00000001111 = 11111...11111110000
9 << 2 // 36 1001 << 2 = 100100
9 >> 2 // 2 1001 >> 2 = 0010 [用符号位填充]
19 >>> 2 // 4 10011 >>> 2 = 100 [用0填充]
// 使用
y >> x // 相当于除以2的x次方
x >> 0 // Math.floor()
~~2.2 // 取整 2
# 书写技巧
# 过滤NaN
if (x !== x) { /* do some thing */ }
# 检查某对象是否有某属性
in关键字可以原型链
var myObject = {
name: '@tips_js'
};
myObject.hasOwnProperty('name'); // true
'name' in myObject; // true
myObject.hasOwnProperty('valueOf'); // false, valueOf 继承自原型链
'valueOf' in myObject; // true
# 字符串转数字
console.log(+'123')
// expected output: 123
console.log(+'');
// expected output: 0
console.log(+true);
// expected output: 1
console.log(+false);
// expected output: 0
console.log(+'hello');
// expected output: NaN
# forEach 中无法break 或 continue
使用some或every进行循环
- 在一次循环中返回true则进行break
- 在一次循环中返回false则进行continue
[0, 1, 2, 3, 4].some(function(val, i) {
if (val === 2) {
return true;
}
console.log(val); // your code
});
//> 0, 1
# 判等
NaN === NaN // false
Object.is(NaN, NaN) // true
# 函数传入空参数
## queston
> method('parameter1', , 'parameter3');
Uncaught SyntaxError: Unexpected token ,
## 常见方式
> method('parameter1', null, 'parameter3') // or
> method('parameter1', undefined, 'parameter3');
## es6
> method(...['parameter1', , 'parameter3']);
# Infinity
表示最大的数
// 寻找最小的值
const array = [2,4,5,1,3]
let min = Infinity // 作为初始值
for (const item of array) {
min = Math.min(min, item)
}
# 将Key统一变为number
parseInt(' 10', 2)
// 2
# ?? 空值合并
当发现null和undefined的时候使用后面的值
const foo = null ?? 'default string';
console.log(foo);
// expected output: "default string"
const baz = 0 ?? 42;
console.log(baz);
// expected output: 0
# 函数域的改变
在很多源码中出现,
var foo = {
fullName:"Peter",
sayName: function() { console.log("My name is", this.fullName); }
};
window.fullName ="Shiny";
foo.sayName(); // My name is Peter
(foo.sayName)(); // My name is Peter
(0, foo.sayName)(); // My name is Shiny
# 语句前的分号;
由于js引擎会自动在语句末添加;
,导致一些问题的出现
var globalCounter = { }
(function () {
var n = 0
globalCounter.increment = function () {
return ++n
}
})()
这样在第一句末尾则不会添加分毫,从而将{}
作为函数来执行。所以在'semi': [2, 'never']
规则下,通常这样写
var globalCounter = { }
;(function () {
var n = 0
globalCounter.increment = function () {
return ++n
}
})()
# 任务队列
// requestIdleCallback 来实现任务队列
function workLoop(deadline) {
while ((deadline.timeRemaining() > 1 || deadline.didTimeout) && works.length > 0) {
performUnitOfWork();
}
if (works.length > 0) {
window.requestIdleCallback(workLoop, { timeout: 1000 });
}
}
function performUnitOfWork() {
works.shift()();
}
requestIdleCallback(workLoop, { timeout: 1000 });
// MessageChannel 实现
const threshold = 5
let deadline = 0
const getTime = () => performance.now()
const flush = () => {
let task, next
deadline = getTime() + threshold
while (getTime() < deadline) {
if (works.length) works.pop()()
}
if (works.length) setTimeout(flush)
}
flush()