Daily-Interview-Question
Daily-Interview-Question copied to clipboard
第 50 题:实现 (5).add(3).minus(2) 功能
Number.prototype.add = function(n) {
return this.valueOf() + n;
};
Number.prototype.minus = function(n) {
return this.valueOf() - n;
};
Number.prototype.add = function (number) {
if (typeof number !== 'number') {
throw new Error('请输入数字~');
}
return this + number;
};
Number.prototype.minus = function (number) {
if (typeof number !== 'number') {
throw new Error('请输入数字~');
}
return this - number;
};
console.log((5).add(3).minus(2));
扩展
Object.prototype.add
Object.prototype.minus
也是可以的
Number.prototype.add = function(n){
return this + n
}
Number.prototype.minus = function(n){
return this - n
}
console.log((5).add(3).minus(2))//6
Number.prototype.add = function (number) { if (typeof number !== 'number') { throw new Error('请输入数字~'); } return this + number; }; Number.prototype.minus = function (number) { if (typeof number !== 'number') { throw new Error('请输入数字~'); } return this - number; }; console.log((5).add(3).minus(2));
扩展
Object.prototype.add Object.prototype.minus
也是可以的
这个方法,可以扩展到数字字符串类型和排除 NaN
值
Number.prototype.add = function (value) {
let number = parseFloat(value);
if (typeof number !== 'number' || Number.isNaN(number)) {
throw new Error('请输入数字或者数字字符串~');
};
return this + number;
};
Number.prototype.minus = function (value) {
let number = parseFloat(value);
if (typeof number !== 'number' || Number.isNaN(number)) {
throw new Error('请输入数字或者数字字符串~');
}
return this - number;
};
console.log((5).add(3).minus(2));
对于在 Object
上添加原型方法是不建议的,因为这个影响太大,会影响所有以Object
构造的对象
首先看到题干第一反应和楼上几位一样,链式操作+给Number/Object对象添加方法。
Number.prototype.add = function(i=0){
return this.valueOf()+i
}
Number.prototype.minus = function(i=0){
return this.valueOf()-i
}
不知道是否是考虑的不周全,就仔细想想,感觉会有一些好玩的知识点在里面,就做了一些小实验。
在 Chrome 的 DevTools 里,我们可以做这个实验:
这里问题就来了——JS的经典的浮点数陷阱。
在简单地搜索之后,我在 GitHub 上搜到了一位阿里大佬的解法,然后参考了一下他的解法和楼上大佬们的解法,对我上面的答案进行了如下修正:
Number.MAX_SAFE_DIGITS = Number.MAX_SAFE_INTEGER.toString().length-2
Number.prototype.digits = function(){
let result = (this.valueOf().toString().split('.')[1] || '').length
return result > Number.MAX_SAFE_DIGITS ? Number.MAX_SAFE_DIGITS : result
}
Number.prototype.add = function(i=0){
if (typeof i !== 'number') {
throw new Error('请输入正确的数字');
}
const v = this.valueOf();
const thisDigits = this.digits();
const iDigits = i.digits();
const baseNum = Math.pow(10, Math.max(thisDigits, iDigits));
const result = (v * baseNum + i * baseNum) / baseNum;
if(result>0){ return result > Number.MAX_SAFE_INTEGER ? Number.MAX_SAFE_INTEGER : result }
else{ return result < Number.MIN_SAFE_INTEGER ? Number.MIN_SAFE_INTEGER : result }
}
Number.prototype.minus = function(i=0){
if (typeof i !== 'number') {
throw new Error('请输入正确的数字');
}
const v = this.valueOf();
const thisDigits = this.digits();
const iDigits = i.digits();
const baseNum = Math.pow(10, Math.max(thisDigits, iDigits));
const result = (v * baseNum - i * baseNum) / baseNum;
if(result>0){ return result > Number.MAX_SAFE_INTEGER ? Number.MAX_SAFE_INTEGER : result }
else{ return result < Number.MIN_SAFE_INTEGER ? Number.MIN_SAFE_INTEGER : result }
}
【大数加减:直接通过 Number 原生的安全极值来进行判断,超出则直接取安全极值】
【超级多位数的小数加减:取JS安全极值位数-2作为最高兼容小数位数】
这样就能相对比较完善地解决这个问题了~希望大家多多补充
Number.prototype.add = function (number) { if (typeof number !== 'number') { throw new Error('请输入数字~'); } return this + number; }; Number.prototype.minus = function (number) { if (typeof number !== 'number') { throw new Error('请输入数字~'); } return this - number; }; console.log((5).add(3).minus(2));
扩展
Object.prototype.add Object.prototype.minus
也是可以的
这个方法,可以扩展到数字字符串类型和排除
NaN
值Number.prototype.add = function (value) { let number = parseFloat(value); if (typeof number !== 'number' || Number.isNaN(number)) { throw new Error('请输入数字或者数字字符串~'); }; return this + number; }; Number.prototype.minus = function (value) { let number = parseFloat(value); if (typeof number !== 'number' || Number.isNaN(number)) { throw new Error('请输入数字或者数字字符串~'); } return this - number; }; console.log((5).add(3).minus(2));
对于在
Object
上添加原型方法是不建议的,因为这个影响太大,会影响所有以Object
构造的对象
function MyNumber(){
MyNumber.prototype= new Number().__proto__
MyNumber.prototype.add = function (number) {
if (typeof number !== 'number') {
throw new Error('请输入数字~');
}
return this + number;
};
}
// 辅助函数当然也可以写到方法里去,但是要重复写
// get decimal places
const getDeimalPlaces = (num) => {
const _num = parseFloat(num);
if (Number.isNaN(_num)) {
throw('This is not a Number!');
}
const _strArr = _num.toString().split('.');
return _strArr.length > 1 ? _strArr[1].length : 0;
}
const getMaxDecimalPlaces = (x, y) => Math.max(getDeimalPlaces(x), getDeimalPlaces(y));
const calculateFloatSafely = (num, decimalPlaces) => parseFloat(num.toFixed(decimalPlaces));
Number.prototype.add = function (num) {
const DECIMAL_PLACES = getMaxDecimalPlaces(this, num);
return calculateFloatSafely((this + num), DECIMAL_PLACES);
}
Number.prototype.minus = function (num) {
const DECIMAL_PLACES = getMaxDecimalPlaces(this, num);
return calculateFloatSafely((this - num), DECIMAL_PLACES);
}
// usage
console.log((5).add(3).minus(2)); // 6
console.log((5.08).add(3.12).minus(2.1)); // 6.1
console.log((10.021).add(3.58).minus(2.102));// 11.499
Number.prototype.add = function(num) {
return this + num;
};
Number.prototype.minus = function(num) {
return this - num;
}
let myFun = {
add(number) {
if (typeof number !== 'number') {
throw new Error('请输入数字')
}
return this + number
},
minus(number) {
if (typeof number !== 'number') {
throw new Error('请输入数字')
}
return this - number
}
}
// 挂载到原型上
Object.assign(Number.prototype, myFun)
;(5).add(3).minus(2)
// 6
让一让,我分享一个比较简便、便于维护的方法。🙈 将需要增加到Number原型上的方法,集中到一个对象里面,再用assign进行合并。
不过望大佬指出不同意见,本人小白一个
Function.prototype.method = function (name, fn) { this.prototype[name] = fn; return this } Number.method('add', function (a) { return this + a }) Number.method('minus', function (a) { return this - a })
Number.prototype.add=function(x){ return this+x} Number.prototype.minus=function(x){return this-x}
Number.prototype.add = function (num) {
return this + num
}
Number.prototype.minus = function (num) {
return this - num
}
console.log((5).add(3).minus(2)) // 6
Number.prototype.add = function(n) { return this.valueOf() + n; }; Number.prototype.minus = function(n) { return this.valueOf() - n; };
how to realize in typescript ?
我的一个疑惑
为什么
8.add(1)
不行,而8['add'](1)
以及(8).add(1)
可以
上面代码中,调用方法之所以写成8['add'],而不是8.add,是因为数值后面的点,会被解释为小数点,而不是点运算符。
将数值放在圆括号中,数字就会自动转化为基本包装类型,就可以使用点运算符调用方法了。
class MyNumber extends Number {
constructor(e) {
super(e);
}
add(n=0) {
if(typeof n !== "number") {
throw new Error("Please enter the correct data type")
}
return new MyNumber(this+n);
}
minus(n=0) {
if(typeof n !== "number") {
throw new Error("Please enter the correct data type")
}
return new MyNumber(this-n);
}
}
var a=new MyNumber (10);
console.log(a.minus(-1).add(2))
Number.prototype.add = function(num) {
return this + num
}
Number.prototype.minus = function(num) {
return this - num
}
5.add(3)报错,因为js引擎将5.识别为一个数字,一个数字+add(3)报错。 5add(3)是报同样的错。
```js Number.prototype.add = function(num) { return this + num } Number.prototype.minus = function(num) { return this - num }
5.add(3)报错,因为js引擎将5.识别为一个数字,一个数字+add(3)报错。 5add(3)是报同样的错。
5..add(3)就可以了
~function () {
function verify(n) {
n = Number(n)
return isNaN(n) ? 0 : n;
}
function add(n) {
n = verify(n)
return this + n;
}
function minus(n) {
n = verify(n)
return this - n;
}
["add", "minus"].forEach(item => {
Number.prototype[item] = eval(item)
})
}()
(5).add(2).minus(3) // 4
例: 5 + 3 - 2,结果为 6
Number.prototype.add = function(i = 0){
return parseFloat((this + i).toPrecision(12))
}
Number.prototype.minus = function(i = 0){
return parseFloat((this - i).toPrecision(12))
}
2.1.minus(1.9) // 0.2
思路:将add
和minus
方法挂在到Number
的原型上面,并且在每个函数中返回Number
类型的结果
Number.prototype.add = function(num) {
return Number(this + num)
}
Number.prototype.minus = function(num) {
return Number(this - num)
}
let myFun = { add(number) { if (typeof number !== 'number') { throw new Error('请输入数字') } return this + number }, minus(number) { if (typeof number !== 'number') { throw new Error('请输入数字') } return this - number } } // 挂载到原型上 Object.assign(Number.prototype, myFun) ;(5).add(3).minus(2) // 6
让一让,我分享一个比较简便、便于维护的方法。🙈 将需要增加到Number原型上的方法,集中到一个对象里面,再用assign进行合并。
不过望大佬指出不同意见,本人小白一个
牛皮
Number.prototype.add = function(n){return this.toString()*1 + n} Number.prototype.minus = function(n){return this.toString()*1 - n} console.log((5).add(3).minus(2))
Number.prototype.add = function(n){return this.toString()*1 + n} Number.prototype.minus = function(n){return this.toString()*1 - n} console.log((5).add(3).minus(2))
你这和调用valueOf有啥区别...
想问下,(5)为啥就变成Number Object了,真的有点好奇js那是怎么处理的
想问下,(5)为啥就变成Number Object了,真的有点好奇js那是怎么处理的 明白了...(5) === Number(5)
Number.prototype.add = function (val) {
return this + val
}
Number.prototype.minus = function (val) {
return this - val
}
class Num {
num = 0
constructor(num){
this.num = num
}
add(count){
this.num += count
return this
}
minus(count){
this.num -= count
return this
}
}
console.log(new Num(5).add(3).minus(2).num )
为什么我将function改成箭头函数,就不对了??

class Num { num = 0 constructor(num){ this.num = num } add(count){ this.num += count return this } minus(count){ this.num -= count return this } } console.log(new Num(5).add(3).minus(2).num )
看到其他答案,都改number 原型链,就不怕该出bug啊。这可是动了基本类型啊。。
为什么我将function改成箭头函数,就不对了??
![]()
因你例子的 arrow function 的 this 会指向 window,所以 add
是回传 window.valueOf() - n
,为 NaN
,自然在 call minus
时会炸掉
class MyNumber {
constructor(num) {
this.num = num
}
add(count) {
let m = count + this.num
return new MyNumber(m)
}
minus(count) {
let m = this.num - count
return new MyNumber(m)
}
}
let m = new MyNumber(2)
console.log('MyNumber', m.add(3).minus(1))
您的来信已收到,我会尽快回复,谢谢