如何覆盖JavaScript函数

146

我试图重写 JavaScript 中内置的 parseFloat 函数。

我应该如何实现这个目标?


9
我不建议那样做。也许可以在原型中创建另一个函数? - KJYe.Name
你可以直接写 function parseFloat() {},但据我所知,没有办法实际调用本地版本。 - pimvdb
覆盖函数是非常常见的做法。 - OKEEngine
你可以使用组合。const parseFloatOverride = () => parseFloat(); - tim-montague
5个回答

267
var origParseFloat = parseFloat;
parseFloat = function(str) {
     alert("And I'm in your floats!");
     return origParseFloat(str);
}

2
@David Waters:恐怕你当前的代码在Chrome中会一直弹出警告。 - pimvdb
13
请记住函数提升,这意味着 origParseFloat 指向您声明的函数。这个 可以工作。 - HoLyVieR
@HoLyVieR:谢谢,我看到可以覆盖和使用本地的parseFloat:http://jsfiddle.net/huZG2/3/. - pimvdb
1
@HoLyVieR 谢谢,已修复,通过将函数分配给名称进行更新,详见 http://jsfiddle.net/huZG2/6/。 - David Waters
1
这不是函数重载。重载不会改变原始函数。这是覆盖。 - tim-montague
显示剩余2条评论

48

你可以通过重新声明它来覆盖任何内置函数。

parseFloat = function(a){
  alert(a)
};

现在parseFloat(3)会弹出3。


1
但是在这个答案中没有函数重载的概念,即保持函数名称相同但覆盖功能。 - Ahsan
3
这不是函数重载,而是完全覆盖。 - tim-montague

40

您可以覆盖它,或者更好地像这样扩展其实现

parseFloat = (function(_super) {
    return function() {
        // Extend it to log the value for example that is passed
        console.log(arguments[0]);
        // Or override it by always subtracting 1 for example
        arguments[0] = arguments[0] - 1;
        return _super.apply(this, arguments);
    };         

})(parseFloat);

像平常一样调用它:

var result = parseFloat(1.345); // It should log the value 1.345 but get the value 0.345

12

你可以这样做:

alert(parseFloat("1.1531531414")); // alerts the float
parseFloat = function(input) { return 1; };
alert(parseFloat("1.1531531414")); // alerts '1'

请查看一个完整的示例: http://jsfiddle.net/LtjzW/1/


8

Override是面向对象编程中的一个概念,用于通过继承来扩展类方法

Javascript有类(以及原型继承),但parseFloat仅是一个函数而不是类(或原型)。因此,您需要将parseFloat转换为一个类方法,或覆盖相关的Number.parseFloat方法。

让我们进一步探讨。覆盖方法不会改变(扩展或覆盖)原始的父方法,如下例所示:

class A {
  // parent method
  print() {
    console.log("class A");
  }
}

class B extends A {
  // override method
  print() {
    console.log("class B");
  }
  parentPrint() {
    super.print();
  }
}

const b = new B();
b.print(); // prints "class B" from override method
b.parentPrint(); // prints "class A" from parent method

为了将这个应用到Number.parseFloat,我们可以进行如下操作:
class B extends Number {
  // overrides `parseFloat` from Number class
  parseFloat() {
    super.parseFloat();
  }
}

const b = new B();
b.parseFloat();

然而,现代实践更倾向于使用组合而不是面向对象继承。

与继承相比,组合被认为更具混淆性、脆弱性和灵活性。例如,React(Facebook)和Go(Google)编程语言都鼓励使用组合:

因此,我的基本建议是使用组合:

const parseFloatOverride = function () {
  return parseFloat();
};

我的推荐是使用依赖注入的组合方式来创建松耦合的依赖关系,这更适合单元测试。
// Inject the `Number` dependency
const parseFloatOverride = function (Number number) {
  return number.parseFloat();
};

警告:不要覆盖Javascript核心库

此外,本主题中几乎每个答案都覆盖了parseFloat函数。这是一种不良实践,因为(a)开发人员期望 parseFloat 按照文档正常工作,(b)其中包括编写您可能使用的任何第三方包的开发人员,这将导致这些包受到破坏。因此,请勿覆盖Javascript核心库,而应使用组合或继承。

const parseFloat = function () {}; // Bad practice
const Number.prototype.parseFloat = function () {}; // Also bad practice

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接