sofish / learn-js

老婆想学 js 这件事就是一个政治任务
143 stars 9 forks source link

第九天:无依赖小库 #11

Open sofish opened 8 years ago

sofish commented 8 years ago

对于球迷来说 NBA 是一种精神,对于 Benz 粉丝来说 AMG 是一种精神,对于黑客来说无依赖也是一种精神。前段时间因为 leftPad 在 npm unpublish 之后引发了一堆对 leftPad 的讨论,就如坐我旁边的同事,就叫我当场写个 leftPad,然后在内部分享会嘲笑我写的太差。

刚半夜看 GitHub Trending 发现了一个无依赖的对字符串操作的小库 dleitee/strman。喜欢看薄的书,看简单的代码。所以看了一波:

export const _isArray = value => {
    return (value !== null &&
           value.length >= 0 &&
           Object.prototype.toString.call(value) === '[object Array]');
};

export const _pop = array => {
    let newarray = [];
    for(let i = 0; i < array.length-1; i++){
        newarray[i] = array[i];
    }
    return newarray;
};

如果是我写的话,可能会是这样的:

export const _isArray = value =>  Object.prototype.toString.call(value) === '[object Array]';
export const _pop = array => array.slice();

所以我觉得这个库还是把东西写复杂了,随后发了一条微博轻吐槽(其实是反问),经提示,发现了一个坑(像 sort 要返回 true/false 一样的坑,以前注意过后来全忘记了):

let str = new String();
typeof str; // object
'' instanceof String; // false

真是一脸懵逼 😿 ,当然,像上面的 _isArray 还可以这样写:

export const _isArray = value =>  Array.isArray(value);

但这样写有一个不好的点 —— 不兼容老浏览器。似乎 Symbal 没这个问题?(这个留给大家)。所以总的来说 Object.prototype.toString.call 还是比较安全的办法。

var frame = document.createElement('iframe');
frame.src = window.location.href;
document.body.appendChild(frame);

var arr = new frame.contentWindow.Array();

console.log(arr instanceof Array); // false
console.log(Array.isArray(arr)); // true

这里我记错了,写一个例子来看看,多谢微博提醒的同学

要总结的话只有一句:我不喜欢看源代码,不过无依赖的看看也挺舒服;要啰嗦的是,突然想起百度 5、6 年前开源过一个叫 Tangram 的库,我就几乎全读了,后来发现当时了解的 js 技巧似乎比现在还多;要自黑的是,当隔三个月看自己的代码觉得是垃圾的时候说明一切都还好,当隔了一年了看自己的代码觉得当时自己很牛逼的话,那说明水平已经比较水 —— 说的就是我。

sofish commented 8 years ago

上次同事要求写的必须自黑的代码,目标不是代码,而是我喜欢自己写而不是 npm install leftpad --save

function leftPad(value, length, char) {
  var ret = '';
  char = String(char);
  while(length--) ret += char;
  return ret + value;
}

function padLeft(value, length, char) {
  return new Array(length).fill(char).join('') + value;
}

leftPad('ciao', 3, 'love');
padLeft('ciao', 3, 'love');

话说用 replace 也很好玩,跟 Array.fill 一样不用考虑 char 是数字还是字符串,不过兼容性更好:

function leftpad(value, length, char) {
  return new Array(length + 1).join(',').replace(/,/g, char) + value;
}