let now = +new Date();
// or 谢 @麦当苗儿[zuojiazi]
// 该方法在 ECMA-262 第五版中被标准化, 存在一些兼容问题 IE9+
now = Date.now()
// 仅仅适用于二维数组。不过,通过递归,我们可以平铺任意维度的嵌套数组。
const arr = [11, [22, 33], [44, 55], 66];
const flatArr = [].concat(...arr); //=> [11, 22, 33, 44, 55, 66]
// flat 法
[1,2, [1, [2, [3]]]].flat()
// (4) [1, 2, 1, Array(2)]
// 提供另一种场景化很强的思路。
// 其实有更简单的. 任意维度数组都可以搞定,
arr.join().split(',')
// 但是存在风险: 类型会变。我们可以提供 转换回调。
// 平铺数字数组 + 转换回调
[1,2, [1, [2, 1+ 2 +1, Number(true)]]].join().split(',').map((index) => Number(index)) // (6) [1, 2, 1, 2, 4, 1]
// 对于通式
Arr.join().split(',').map(fn)
这个方法可能限制很多,比如数组元素类型不一致, 比如非基础类型等
第一个问题: 我们不妨想想,一个数组中既有 number,又有 string 是合理么?实际上这种数组在逻辑,潜在风险和处理上存在非常多的问题。大多数情况下是一个不好的设计。 但是如果在 Typescript 中往往有比较好的场景。
第二个问题:非基础类型则不好处理, 其实像这种比较 Hacker 的方法, 往往不是用于处理普遍情况的,往往是在特殊场景发挥奇效的。没有最好的方案,只有最合适的方案。
仅仅是另一种思路。
// api
Math.floor(10.8222)
// 双位移
console.log(~~47.11) // -> 47
console.log(~~-12.88) // -> -12
console.log(~~1.9999) // -> 1
console.log(~~3) // -> 3
//失败的情况
console.log(~~[]) // -> 0
console.log(~~NaN) // -> 0
console.log(~~null) // -> 0
//大于32位整数则失败
console.log(~~(2147483647 + 1) === (2147483647 + 1)) // -> 0
const obj = {
foo: { bar: [11, 22, 33, 44], baz: { bing: true, boom: 'Hello' } }
};
// The third parameter is the number of spaces used to
// beautify the JSON output.
JSON.stringify(obj, null, 4);
// "{
// "foo": {
// "bar": [
// 11,
// 22,
// 33,
// 44
// ],
// "baz": {
// "bing": true,
// "boom": "Hello"
// }
// }
// }"
console.time("Array initialize");
const arr = new Array(100);
const len = arr.length;
for (let i = 0; i < len; i++) {
arr[i] = new Object();
};
console.timeEnd("Array initialize");
它不会从 Object 继承任何属性或方法(例如,constructor,toString() 等)
const pureObject = Object.create(null);
console.log(pureObject); //=> {}
console.log(pureObject.constructor); //=> undefined
console.log(pureObject.toString); //=> undefined
console.log(pureObject.hasOwnProperty); //=> undefined
const require = function( message ){
throw new Error( message );
}
const getSum = (a = require('a is not defined'), b = require('b is not defined')) => a + b
getSum( 10 ) // throws Error, b is not defined
getSum( undefined, 10 ) // throws Error, a is not defined
如下为主要代码, 完整代码需要 Typescript 环境。
@validate
greet(p1, p2, p3, @required name: string, p5) {
// p1-5 仅仅用于占位, 用来测试 required 的第四个参数。
return "Hello " + name + ", " + this.greeting;
}
// output
// throw (constructors.name + "." + String(method_1) + "[\u5B9E\u9645\u4E0A\u662F\uFF1A" + constructors.name + ".prototype." + String(method_1) + "]\u7B2C " +(index + 1) + " \u4E2A\u53C2\u6570\u662F\u5FC5\u4F20\u53C2\u6570\uFF0C\u8BF7\u63D0\u4F9B\u3002");
^
// Greeter.greet[ Greeter.prototype.greet ] 第 4 个参数是必传参数,请提供。
+function fn() {
console.log([...arguments]); // (4) [1, 2, 3, 4]
console.log(Array.prototype.slice.call(arguments));
}(1,2,3,4)
通常库遇到的问题往往是,用户不按照你想要的方式调用,特别是 new 的问题,很多代码中会存在一谢逻辑去校验用户是否是 new 调用。诸如:
var _ = function(obj) {
if (obj instanceof _)
return obj;
if (!(this instanceof _))
return new _(obj);
this._wrapped = obj;
};
class Fn{}
// TypeError: Class constructor Fn cannot be invoked without 'new'
Fn();
function Foo() {
if (!new.target) throw "Foo() must be called with new";
console.log("Foo instantiated with new");
}
new Foo(); // logs "Foo instantiated with new"
Foo(); // throws "Foo() must be called with new"
// new.target 在构造中
class A {
constructor() {
console.log(new.target.name);
}
}
new A(); // A
[x, y] = [y, x];
a = a + b;
b = a - b;
a = a - b;
a^b^b=a
a = a ^ b;
b = a ^ b;
a = a ^ b;
~~2.8 // 2 巧用位运算: 小数取整
3.86 | 0 // 2 巧用位运算: 小数取整
!!0 // false 转 bool
+ '123' // 123 string -> number
铺垫知识 [建议细看]
首先要明确的一点是,计算机内部在做数学运算时(也就是计算机的0和1的运算),都是以补码为标准的,说白了 计算机中就一种码那就是补码,而现实社会中的编码规则,例如原码、反码都是我们自定义的,为了和计算机中的补码形成转换关系。所以说在我们手工计算这类由计算机计算的01运算,要站在计算机的角度。因此首先就要将我们的原码反码什么的全都先转为补码,再来计算^^。这样才能使得正数和负数的表示统一起来,具体可以参阅【补码的历史】,这里不过多展开了。 接着来看那个问题,从问题入手,解决了实际问题,概念也就自然了然于心了。^^
5 的补码是它本身(ps:正数的原、反、补码都是它本身;负数的原码最高为为1开头,反码是最高符号位不变,其余位在原码的基础上取反,补码是在反码的基础上+1即可得到) 5的补码:00000101
~5 (也就是5按位取反运算,下面涉及的是补码运算): 00000101按位取反,这里需要将原始01串完全反转过来,不存在最高符号位的概念,取反结果为: 11111010
注意这里的结果是用补码表示的,毕竟这还是机器表示形式,转化为自然语言的编码,把结果(补码)转化为原码就是:
看看 [ ~ -6 = 5 ] 的计算过程, 假设有符号六位
按位取反的快捷运算公式 -(x+1). 【~~x -> -( -(x + 1) + 1) -> -( -x - 1 + 1) -> –x -> x】