Daily-Interview-Question icon indicating copy to clipboard operation
Daily-Interview-Question copied to clipboard

第 50 题:实现 (5).add(3).minus(2) 功能

Open LiuMengzhou opened this issue 5 years ago • 33 comments

Number.prototype.add = function(n) {
  return this.valueOf() + n;
};
Number.prototype.minus = function(n) {
  return this.valueOf() - n;
};

image

LiuMengzhou avatar Apr 08 '19 17:04 LiuMengzhou

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 

也是可以的

zeroone001 avatar Apr 08 '19 23:04 zeroone001

Number.prototype.add =  function(n){
  return this + n
}
Number.prototype.minus =  function(n){
  return this - n
}
console.log((5).add(3).minus(2))//6

yeyi361936738 avatar Apr 09 '19 00:04 yeyi361936738

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 构造的对象

jjeejj avatar Apr 09 '19 01:04 jjeejj

首先看到题干第一反应和楼上几位一样,链式操作+给Number/Object对象添加方法。

Number.prototype.add = function(i=0){
	return this.valueOf()+i
}
Number.prototype.minus = function(i=0){
	return this.valueOf()-i
}

不知道是否是考虑的不周全,就仔细想想,感觉会有一些好玩的知识点在里面,就做了一些小实验。 在 Chrome 的 DevTools 里,我们可以做这个实验: image 这里问题就来了——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作为最高兼容小数位数】 image

这样就能相对比较完善地解决这个问题了~希望大家多多补充

noctiomg avatar Apr 09 '19 01:04 noctiomg

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;
};
}

hqzh avatar Apr 09 '19 13:04 hqzh

// 辅助函数当然也可以写到方法里去,但是要重复写
// 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

pengcc avatar Apr 09 '19 15:04 pengcc

Number.prototype.add = function(num) {
	return this + num;
};
Number.prototype.minus = function(num) {
	return this - num;
}

FanShiDe avatar Apr 10 '19 01:04 FanShiDe

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进行合并。

不过望大佬指出不同意见,本人小白一个

bran-nie avatar Apr 10 '19 11:04 bran-nie

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 })

Hillkinsh avatar Apr 10 '19 15:04 Hillkinsh

Number.prototype.add=function(x){ return this+x} Number.prototype.minus=function(x){return this-x}

IAMSBLOL avatar Jul 19 '19 02:07 IAMSBLOL

Number.prototype.add = function (num) {
    return this + num
}
Number.prototype.minus = function (num) {
    return this - num
}

console.log((5).add(3).minus(2))   // 6

mongonice avatar Jul 24 '19 08:07 mongonice

Number.prototype.add = function(n) {
  return this.valueOf() + n;
};
Number.prototype.minus = function(n) {
  return this.valueOf() - n;
};

image

how to realize in typescript ?

safarishi avatar Jul 30 '19 14:07 safarishi

我的一个疑惑

为什么 8.add(1) 不行,而 8['add'](1)以及(8).add(1)可以

上面代码中,调用方法之所以写成8['add'],而不是8.add,是因为数值后面的点,会被解释为小数点,而不是点运算符。

将数值放在圆括号中,数字就会自动转化为基本包装类型,就可以使用点运算符调用方法了。

参考

zzNire avatar Aug 09 '19 07:08 zzNire

	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))

webbobola avatar Aug 30 '19 04:08 webbobola

 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)是报同样的错。

aeolusheath avatar Oct 11 '19 07:10 aeolusheath

```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)就可以了

ScholatLouis avatar Oct 11 '19 13:10 ScholatLouis

~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

huatten avatar Nov 21 '19 08:11 huatten

例: 5 + 3 - 2,结果为 6

yygmind avatar Dec 16 '19 03:12 yygmind

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

blade254353074 avatar Mar 20 '20 09:03 blade254353074

思路:将addminus方法挂在到Number的原型上面,并且在每个函数中返回Number类型的结果

Number.prototype.add = function(num) {
      return Number(this + num)
}
Number.prototype.minus = function(num) {
      return Number(this - num)
} 

arixse avatar May 04 '20 14:05 arixse

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进行合并。

不过望大佬指出不同意见,本人小白一个

牛皮

fariellany avatar May 24 '20 08:05 fariellany

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))

long-joan avatar May 25 '20 07:05 long-joan

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有啥区别...

SnailOwO avatar Jul 14 '20 07:07 SnailOwO

想问下,(5)为啥就变成Number Object了,真的有点好奇js那是怎么处理的

SnailOwO avatar Jul 14 '20 07:07 SnailOwO

想问下,(5)为啥就变成Number Object了,真的有点好奇js那是怎么处理的 明白了...(5) === Number(5)

SnailOwO avatar Jul 14 '20 08:07 SnailOwO

image

libin1991 avatar Aug 27 '20 11:08 libin1991

Number.prototype.add = function (val) {
    return this + val
}

Number.prototype.minus = function (val) {
    return this - val
}

blank1u avatar Nov 29 '20 10:11 blank1u


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 )

jiangmingwen avatar Feb 02 '21 04:02 jiangmingwen

为什么我将function改成箭头函数,就不对了??

企业微信截图_cc297912-663b-46fd-91bd-8003bf59c722

lianglei777 avatar Feb 28 '21 08:02 lianglei777


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啊。这可是动了基本类型啊。。

zizifn avatar Dec 29 '21 17:12 zizifn

为什么我将function改成箭头函数,就不对了??

企业微信截图_cc297912-663b-46fd-91bd-8003bf59c722

因你例子的 arrow function 的 this 会指向 window,所以 add 是回传 window.valueOf() - n,为 NaN,自然在 call minus 时会炸掉

Dylan0916 avatar Apr 05 '22 03:04 Dylan0916

 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))

XW666 avatar Aug 18 '22 06:08 XW666

您的来信已收到,我会尽快回复,谢谢

ScholatLouis avatar Aug 18 '22 06:08 ScholatLouis