javascript使用现有原型重新定义原型

javascript redefine prototype using existing prototype

本文关键字:原型 定义 新定义 javascript      更新时间:2023-09-26

我想重新定义一个原型,但仍然使用原始的原型函数。目的是将测试台调试代码添加到现有的生产原型定义中。

// production definition
function tester(n) { this.name = n ; }
tester.prototype.getName = function() { return this.name; }
// debug override
if (typeof tester.prototype.getName === 'function') {
  var f = tester.prototype.getName;
  tester.prototype.getName = function () {
    return f() + " (plus some more)";
  };
}
// test
var tt = new tester('testing');
console.log(tt.getName());  // logs ' (plus some more)' but I want 'testing (plus some more)'

当然,我的生产原型要复杂得多,我宁愿不在生产代码中嵌入我的测试台代码。

非常感谢!-John:)

您必须使用正确的this值和正确的参数调用f

f.apply(this, arguments);

了解有关thisapply的更多信息。


这似乎是一种非常脆弱的方法,因为它还需要你知道原始方法返回的值是什么,以及调用代码对它做了什么

但我想你这样做只是为了非常具体的方法。

在重新定义中,需要使用Function.prototype.apply()f函数设置正确的上下文(this)。在代码中,f函数的上下文被设置为全局范围,即使在tt的重新定义的getName属性中调用它也是如此。相反,它应该是重新定义的getName函数的上下文。

// production definition
function tester(n) { this.name = n ; }
tester.prototype.getName = function() { return this.name; }
// debug override
if (typeof tester.prototype.getName === 'function') {
  var f = tester.prototype.getName;
  // Here, 'this' is the global scope (window).
  console.log('Global scope:');
  console.log(this);  
  console.log('f called with context of global scope:');
  console.log(f()); // prints 'name' prop of global scope
  tester.prototype.getName = function () {
    console.log("Instance:");
    console.log(this);
    // Here, 'this' is tt when tt.getName() is evaluated.
    // If we call f() here, the context for f 
    // will still be the global scope, instead of tt.
    // So, we use apply to set the context of f to 
    // an instance of tester.
    return f.apply(this) + " (plus some more)";  
  };
}
// test
var tt = new tester('testing');
console.log(tt.getName());  // logs testing (plus some more)'

http://jsfiddle.net/a27xzqc9/3/

用封装扩展Felix和Patrick的答案,以避免使用全局变量"f",因为我将多次重用此结构。

;(function(){
  if (typeof tester.prototype.getName === 'function') {
    var f = tester.prototype.getName;
    tester.prototype.getName = function () {
      return f.apply(this) + " (plus some more)";
    };
  }
})();