每日学习总结系列(五)
一、好看的代码截图网站
二、utf-8转中文
var value = '成'
function utfTranslate(value){
return unescape(value.replace(/&#x/g,'%u').replace(/\\u/g,'%u').replace(/;/g,''))
}
utfTranslate(value)
//成
三、正常script、asycn、defer
之前我知道defer
最好,但不求甚解,看了这个图,清晰多了。
四、deno
deno
今天正式发布了,点击: 了解一下 去 => github地址
五、in运算符
今天看到实现map
等数组方法里,通过下标是否in
数组来判断当前这一项是否为空。重新认识一下in
运算符:
如果指定的属性在指定的对象或其原型链中,则in
运算符返回true
。
prop in object
prop
: 一个字符串类型或者symbol
类型的属性名或者数组索引(非symbol类型将会强制转为字符串)。
六、如何创建一个包含数字1-50的数组
今天别人问我一个这样的问题,我想了下,其实原理是创建一个50
个值的数组,然后通过数组一些方法返回的下标进行重新构建新数组,或者通过array from
的回调函数返回下标组成的数组,这样可以写出很多炫技的写法。
Array.from({length:100}, (v, k) => k)
Array.from(Array(100), (v, k) =>k)
//这个比较特殊,keys直接返回索引键的迭代器对象
Array.from(new Array(100).keys())
new Array(50).fill(0).map((v, k) => k)
Object.keys(Array.apply(null, {length: 100})).map(v => +v)
Object.keys(Array(100).fill(0)).map(v => +v)
七、>> 以及 >>>
看实现数组的一些方法里,使用了>>>
,同时也引申出了>>
,它们有什么异同呢?
>>
(有符号移位):该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,拷贝最左侧的位以填充左侧
-9 >> 2
11111111111111111111111111110111 // -9 -> 11111111111111111111111111111101 // -3
>>>
(无符号移位):该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,左侧用0填充。因为符号位变成了 0,所以结果总是非负的
9 >>> 2
00000000000000000000000000001001 // 9 -> 00000000000000000000000000000010 // 2
移位0有什么意义?
原来移位操作符在移位前做了两种转换,第一将不是number
类型的数据转换为number
,第二将number
转换为无符号的32bit
数据,也就是Uint32
类型。
Uint32类型是如何转换的?
- 如果不能转换为Number,那就为0
- 如果为非整数,先转换为整数,参考公式
sign(n) ⋅ floor(abs(n))
function ToInteger(x) {
x = Number(x);
return x < 0 ? Math.ceil(x) : Math.floor(x);
}
- 如果是正数,返回正数
- 如果是负数,返回负数 +
2的32次方
function modulo(a, b) {
return a - Math.floor(a / b) * b;
}
function ToUint32(x) {
return modulo(ToInteger(x), Math.pow(2, 32));
}
八、使用提前return消灭不必要的else语句
反向思考,让人耳目一新,值得借鉴
九、实现数组map方法
Array.prototype.map = function (callbackfn, thisArg) {
// 处理数组类型异常
if (this === null || this === undefined) {
throw new TypeError("Cannot read property 'map' of null or undefined");
}
// 处理回调类型异常
if (Object.prototype.toString.call(callbackfn) != "[object Function]") {
throw new TypeError(callbackfn + ' is not a function')
}
// 草案中提到要先转换为对象
let O = Object(this);
let T = thisArg;
let len = O.length >>> 0;
let A = new Array(len);
for (let k = 0; k < len; k++) {
// in 表示在原型链查找
// 如果用 hasOwnProperty 是有问题的,它只能找私有属性
if (k in O) {
let kValue = O[k];
// 依次传入this, 当前项,当前索引,整个数组
let mappedValue = callbackfn.call(T, kValue, k, O);
A[k] = mappedValue;
}
}
return A;
}
const arr = new Array(10)
arr[5] = 5
arr.map(v => {
return v.a
})
// [empty × 5, 5, empty × 4]
十、实现数组reduce方法
Array.prototype.reduce = function (callbackfn, initialValue) {
// 异常处理,和 map 一样
// 处理数组类型异常
if (this === null || this === undefined) {
throw new TypeError("Cannot read property 'reduce' of null or undefined");
}
// 处理回调类型异常
if (Object.prototype.toString.call(callbackfn) != "[object Function]") {
throw new TypeError(callbackfn + ' is not a function')
}
let O = Object(this);
let len = O.length >>> 0;
let k = 0;
let accumulator = initialValue;
// 没有初始值
if (accumulator === undefined) {
for (; k < len; k++) {
// 查找原型链
if (k in O) {
accumulator = O[k];
k++;
console.log(k)
break;
}
}
}
// 表示数组全为空
if (k === len && accumulator === undefined) {
throw new Error('Each element of the array is empty');
}
for (; k < len; k++) {
if (k in O) {
// 注意,核心!
accumulator = callbackfn.call(undefined, accumulator, O[k], k, O);
}
}
return accumulator;
}
好记性不如烂笔头,看到自己觉得应该记录的知识点,结合自己的理解进行记录,用于以后回顾。