...
function foo(...args){
console.log(args);
}
foo(1, 2, 3, 4, 5); // [1, 2, 3, 4, 5]
function foo(x = 1, y = 2){
console.log(x, y);
}
foo(); // 1 2
foo(undefined, null); // 1 null
foo(3, 4); // 3 4
// function bar(x = x + 1, y = x + 2) Error ---> ReferenceError: Cannot access 'x' before initialization
// function bar(x = y + 1, y = x + 2) Error ---> ReferenceError: Cannot access 'y' before initialization
function bar(x = 1, y = x + 2) {
console.log(x, y);
}
bar(); // 1 3
bar(undefined, null); // 1 null
bar(3, 4); // 3 4
function bar(x = 1, y = ((num) => num)(2)) {
console.log(x, y);
}
bar(); // 1 2
bar(undefined, null); // 1 null
bar(3, 4); // 3 4
let data = {
code: 200,
data: {
name: 'Lee',
age: 18,
list: [1, 2, 3]
},
msg: 'ok'
}
let { code: c, msg: m, data: d, data: { name: n, age: a, list: [n1, n2, n3] } } = data;
console.log(c, m, d, n, a, n1, n2, n3); // 200 'ok' {name: 'Lee', age: 18, list: Array(3)} 'Lee' 18 1 2 3
var o1 = { a: 1, b: 2, c: 3 },
o2 = {};
({ a: o2.x, b: o2.y, c: o2.z } = o1);
console.log(o2); // {x: 1, y: 2, z: 3}
var o1 = { a: 1, b: 2, c: 3 },
a2 = [];
({ a: a2[0], b: a2[1], c: a2[2] } = o1);
console.log(a2); // [1, 2, 3]
var a1 = [1, 2, 3],
o2 = {};
[o2.a, o2.b, o2.c] = a1;
console.log(o2.a, o2.b, o2.c); // 1 2 3
var a1 = [1, 2, 3],
a2 = [];
[a2[2], a2[0], a2[1]] = a1;
console.log(a2); // [2, 3, 1]
var o = { a: 1, b: 2, c: 3 },
a, b, c, p;
p = { a, b, c } = o;
console.log(a, b, c); // 1 2 3
p === o; // true
var o = { a: 1, b: 2, c: 3 },
p = [4, 5, 6],
a, b, c, x, y, z;
({ a } = { b, c } = o);
[x, y] = [z] = p;
console.log(a, b, c); // 1 2 3
console.log(x, y, z); // 4 5 4
let data = [1, undefined, 3];
let [a = 10, b = 20, c = 30, d = 40] = data;
console.log(a, b, c, d); // 1 20 3 40
var o1 = {
foo() {
console.log("o1:foo");
}
};
var o2 = {
foo() {
super.foo(); // o1.foo
console.log("o2:foo");
}
};
Object.setPrototypeOf(o2, o1);
o2.foo(); // o1:foo o2:foo
/**
* 标签模板字面量
* strings:
* 是一个由所有普通字符串(插入表达式之间的部分)组成的数组
* strings.raw:
* 原始(raw)字符串,原始版本的值保留了原始的转义码 \n 序列(\ 和 n 是独立的字符),而处理过的版本把它当作是一个单独的换行符
* values:
* 插入的值组成的数组
*/
function foo(strings, ...values) {
console.log(strings);
console.log(strings.raw);
console.log(values);
}
var name = "Lee";
var age = 18;
// strings ---> ['Hello, 我叫', '\n今年', '岁!', raw: Array(3)]
// strings.raw ---> ['Hello, 我叫', '\\n今年', '岁!']
// values ---> ['Lee', 18]
foo`Hello, 我叫${name}\n今年${age}岁!`;
console.log(String.raw`Hello\nLee!!!`); // Hello\nLee!!!
function* foo() {
yield 1;
yield 2;
yield 3;
return 4;
}
let it = foo();
console.log(it.next()); // {value: 1, done: false}
console.log(it.return()); // {value: undefined, done: true}
console.log(it.return(5)); // {value: 5, done: true}
class Foo {
static msg = 'Hello Foo';
constructor() {
console.log(new.target.msg);
}
}
class Bar extends Foo {
static desc = 'Hello Bar';
constructor() {
super();
console.log(new.target.desc, new.target.msg);
}
baz() {
console.log(new.target);
}
}
new Foo(); // Hello Foo
var b = new Bar(); // Hello Foo --- Hello Bar, Hello Foo
b.baz(); // undefined
new.target
作用:
new.target
可以访问 静态属性 / 方法
new.target
如果是 undefined
,那么就可以知道这个函数不是通过 new
调用的,因此如果需要的话可以强制一个 new
调用var m = new Map();
var x = { id: 1 },
y = { id: 2 };
// 设置值
m.set(x, "foo");
m.set(y, "bar");
// 元素含量
console.log(m.size); // 2
// 查询值
console.log(m.get(x)); // foo
console.log(m.get(y)); // bar
console.log(m.values());
console.log(m.values().next()); // {value: 'foo', done: false}
console.log(m.entries());
console.log(m.entries().next()); // {value: Array(2) [{id: 1}, 'foo'], done: false}
console.log(m.keys());
console.log(m.keys().next()); // {value: {id: 1}, done: false}
// 删除值
m.delete(y);
// 清空值
m.clear();
WeakMap 是 map 的变体,二者的多数外部行为特性都是一样的,区别在于内部内存分配(特别是其 GC)的工作方式
注意:
WeakMap(只)接受对象作为键
WeakMap 没有 size 属性或 clear() 方法,也不会暴露任何键、值或项目上的迭代器
var m = new WeakMap();
var x = { id: 1 },
y = { id: 2 };
m.set(x, "foo");
m.has(x); // true
m.has(y); // false
var m = new WeakMap();
var x = { id: 1 },
y = { id: 2 },
z = { id: 3 },
w = { id: 4 };
m.set(x, y);
x = null; // { id: 1 } 可GC
y = null; // { id: 2 } 可GC
// 只因 { id: 1 } 可GC
m.set(z, w);
w = null; // { id: 4 } 不可GC
set 是一个值的集合,其中的值唯一(重复会被忽略)
set 的 API 和 map 类似。只是 add(…) 方法代替了 set(…) 方法(某种程度上说有点讽刺),没有 get(…) 方法。
var s = new Set();
var x = { id: 1 },
y = { id: 2 };
s.add(x);
s.add(y);
s.add(x);
// s.size; // 2
// s.delete(y);
// s.size; // 1
// s.clear();
// s.size; // 0
var s = new Set();
var x = { id: 1 },
y = { id: 2 };
s.add(x).add(y);
var keys = [...s.keys()],
vals = [...s.values()],
entries = [...s.entries()];
s.keys().next();
s.values().next();
s.entries().next();
keys[0] === x; // true
keys[1] === y; // true
vals[0] === x; // true
vals[1] === y; // true
entries[0][0] === x; // true
entries[0][1] === x; // true
entries[1][0] === y; // true
entries[1][1] === y; // true
就像 WeakMap 弱持有它的键(对其值是强持有的)一样,WeakSet 对其值也是弱持有的(这里并没有键):
WeakSet 的值必须是对象,而并不像 set 一样可以是原生类型值。
var s = new WeakSet();
var x = { id: 1 },
y = { id: 2 };
s.add(x);
s.add(y);
x = null; // x可GC
y = null; // y可GC
Array.of(..)
var a = Array(3);
console.log(a); // (3) [空属性 × 3]
console.log(a.length); // 3
console.log(a[0]); // undefined
var b = Array.of(3);
console.log(b); // [3]
console.log(b.length); // 1
console.log(b[0]); // 3
var c = Array.of(1, 2, undefined);
console.log(c); // (3) [1, 2, undefined]
console.log(c.length); // 3
console.log(c[2]); // undefined
Array.from(..)
注意
空值
和undefined
// 类数组对象
var arrLike = {
length: 3,
0: "foo",
3: "bar"
};
Array.prototype.slice.call(arrLike); // (3) ['foo', 空属性 × 2]
Array.from(arrLike); // (3) ['foo', undefined, undefined]
var arrLike = {
length: 4,
2: "foo"
};
Array.from(arrLike); // [undefined, undefined, 'foo', undefined]
var arrLike = {
length: 4,
2: "foo"
};
let arr = Array.from(arrLike, (value, index) => {
console.log(value, index);
return {key: index, value};
});
console.log(arr);
copyWithin(..)
copyWithin(..)
从一个数组中复制一部分到同一个数组的另一个位置,覆盖这个位置所有原来的值
copyWithin(..)
方法不会增加数组的长度。到达数组结尾复制就会停止
[1, 2, 3, 4, 5].copyWithin(3, 0); // [1,2,3,1,2]
[1, 2, 3, 4, 5].copyWithin(3, 0, 1); // [1,2,3,1,5]
[1, 2, 3, 4, 5].copyWithin(0, -2); // [4,5,3,4,5]
[1, 2, 3, 4, 5].copyWithin(0, -2, -1); // [4,2,3,4,5]
copyWithin
fill(..)
Array(4).fill(undefined); // [undefined, undefined, undefined, undefined]
entries()
、values()
、keys()
迭代器方法
var a = [1,2,3];
[...a.values()]; // [1,2,3]
[...a.keys()]; // [0,1,2]
[...a.entries()]; // [ [0,1], [1,2], [2,3] ]
[...a[Symbol.iterator]()]; // [1,2,3]
var a = [];
a.length = 3;
a[1] = 2;
[...a.values()]; // [undefined,2,undefined]
[...a.keys()]; // [0,1,2]
[...a.entries()]; // [ [0,undefined], [1,2], [2,undefined] ]
Object.is(..)
如果需要严格识别 NaN 或者 -0 值,那么应该选择 Object.is(…)
var x = NaN, y = 0, z = -0;
x === x; // false
y === z; // true
Object.is(x, x); // true
Object.is(y, z); // false
Object.getOwnPropertySymbols(..)
获取对象上所有的符号属性
var o = {
foo: 42,
[Symbol("bar")]: "hello world",
baz: true
};
Object.getOwnPropertySymbols(o); // [ Symbol(bar) ]
Object.setPrototypeOf(..)
行为委托
var o1 = {
foo() {
console.log("foo");
}
};
var o2 = {};
Object.setPrototypeOf(o2, o1);
// 委托给o1.foo()
o2.foo(); // foo
var o1 = {
foo() {
console.log("foo");
}
};
var o2 = Object.setPrototypeOf({}, o1 );
// 委托给o1.foo()
o2.foo(); // foo
cosh(..)
双曲余弦函数acosh(..)
双曲反余弦函数sinh(..)
双曲正弦函数asinh(..)
双曲反正弦函数tanh(..)
双曲正切函数atanh(..)
双曲反正切函数hypot(..)
平方和的平方根(也即:广义勾股定理)cbrt(..)
立方根clz32(..)
计算 32 位二进制表示的前导 0 个数expm1(..)
等价于 exp(x) - 1log2(..)
二进制对数(以 2 为底的对数)log10(..)
以 10 为底的对数log1p(..)
等价于 log(x + 1)imul(..)
两个数字的 32 位整数乘法sign(..)
返回数字符号trunc(..)
返回数字的整数部分fround(..)
向最接近的 32 位(单精度)浮点值取整Number.isFinite(..)
和 Number.isNaN(..)
isFinite
检查一个数值是否为有限的
Number.isFinite(..)
和 Number.isNaN(..)
与传统的全局方法isFinite()
和isNaN()
的区别在于:
Number()
将非数值的值
转为数值
,再进行判断Number.isFinite()
对于非数值一律返回false
,Number.isNaN()
只有对于NaN
才返回true
,非NaN
一律返回false
var a = NaN, b = Infinity, c = 42;
Number.isFinite(a); // false
Number.isFinite(b); // false
Number.isFinite(c); // true
var a = "42";
isFinite(a); // true
Number.isFinite(a); // false
Number.isInteger(..)
判断
整数
Number.isInteger(4); // true
Number.isInteger(4.2; // false
Number.isInteger(NaN); // false
Number.isInteger(Infinity); // false
isFloat
function isFloat(x) {
return Number.isFinite(x) && !Number.isInteger(x);
}
isFloat(4.2); // true
isFloat(4); // false
isFloat(NaN); // false
isFloat(Infinity); // false
Number.isSafeInteger(..)
具检查一个值以确保其为整数并且在
Number.MIN_SAFE_INTEGER
-Number.MAX_SAFE_INTEGER
范围之内(全包含)
var x = Math.pow(2, 53),
y = Math.pow(-2, 53);
Number.isSafeInteger(x - 1); // true
Number.isSafeInteger(y + 1); // true
Number.isSafeInteger(x); // false
Number.isSafeInteger(y); // false
String.fromCodePoint(0x1d49e); // "𝒞"
"ab𝒞d".codePointAt(2).toString(16); // "1d49e"
var s1 = "e\u0301";
s1.length; // 2
var s2 = s1.normalize();
s2.length; // 1
s2 === "\xE9"; // true
String.raw(..)
var str = "bc";
String.raw`\ta${str}d\xE9`;
// '\\tabcd\\xE9', 而不是" abcdé"
repeat(..)
"foo" * 3; // "foofoofoo"
"foo".repeat( 3 ); // "foofoofoo"
startsWith(..)
、endsWidth(..)
和 includes(..)
var palindrome = "step on no pets";
palindrome.startsWith("step on"); // true
palindrome.startsWith("on", 5); // true
palindrome.endsWith("no pets"); // true
palindrome.endsWith("no", 10); // true
palindrome.includes("on"); // true
palindrome.includes("on", 6); // false