wingmeng / front-end-quiz

前端小测试答题收集
0 stars 0 forks source link

JS基础测试33:自定义 toFixed 方法 #17

Open wingmeng opened 5 years ago

wingmeng commented 5 years ago

题目:

image


我的回答:

Chrome Firefox IE11
0.6.toFixed(0) 1 1 1
1.6.toFixed(0) 2 2 2
0.035.toFixed(2) 0.04 0.04 0.04
0.045.toFixed(2) 0.04 0.04 0.05
Number.prototype.toFixed = myToFixed;
String.prototype.toFixed = myToFixed;

function myToFixed(digits = 0) {
  let num = String(this);

  // 小数位不足时后置补零
  const postfixZero = s => {
    let len = digits;

    if (s.indexOf('.') > 0) {
      len = digits - s.split('.')[1].length;
    } else if (len > 0) {
      s += '.';  // 整数位后补小数点
    }

    return s + '0'.repeat(len);
  };

  digits = parseInt(digits, 10);

  if (isNaN(digits)) {  // 非数值
    throw new Error('digits argument must be a number(or string number)');
  }

  if (digits < 0) {  // 负数
    throw new Error('digits argument must be greater than or equal to 0');
  }

  if (!isFinite(num)) {  // +-Infinity
    return num;
  }

  if (num.indexOf('.') > 0) {
    let times = Math.pow(10, digits);  // 根据小数位长度获取升幂倍数
    num = Math.round(num * times) / times + '';  // 四舍五入,降幂
  }

  return postfixZero(num);
}

测试用例:

console.group('普通场景测试');
  console.log(0.6.toFixed(0));  // "1"
  console.log(1.6.toFixed(0));  // "2"
  console.log(0.035.toFixed(2));  // "0.04"
  console.log(0.045.toFixed(2));  // "0.05"
console.groupEnd();    

console.group('进阶场景测试');
  console.log(Math.PI.toFixed(10));  // "3.1415926536"
  console.log(0.9.toFixed());  // "1"
  console.log(Number(5).toFixed(2));  // "5.00"
  console.log(3..toFixed(3));  // "3.000"
  console.log(.5.toFixed('3'));  // "0.500"
  console.log(1.2345.toFixed(2.6));  // "1.23"
console.groupEnd();

console.group('参数异常测试');
  console.log(Infinity.toFixed(5));  // "Infinity"
  console.log(0.5.toFixed(-2));  // Error: digits argument must be greater than or equal to 0
  console.log(0.5.toFixed(null));  // Error: digits argument must be a number(or string number)
console.groupEnd();
//zxz:  滴~满分~
wingmeng commented 5 years ago

自我评分:一般

优秀、良好、一般、差劲

不足之处:

  1. 代码实现比较中庸,无突出亮点;
  2. 有 bug,无法通过 1.005.toFixed(2) 的测试用例,期望返回 1.01 实际返回 1.00

学习收获:

  1. toFixed 的兼容性问题;
  2. toFixed 只有当保留小数位后面仅为5的时候会出现预期之外的结果,改为 6 就正常了,或者补一位小数。
wingmeng commented 5 years ago

最佳实践:

var oldtoFixed = Number.prototype.toFixed
Number.prototype.toFixed = function(digits){
    var length = (parseFloat(this) + '').replace(/^\d+\.?/, '').length;
    var len = length > digits ? length : digits;
    var number = Number(this) + Math.pow(10, -len-1);
    return oldtoFixed.call(number, digits);
}