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

时间:2015-11-13 22:09:25

标签: javascript debugging prototype

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

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

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

非常感谢提前! - 约翰:)

3 个答案:

答案 0 :(得分:1)

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

f.apply(this, arguments);

详细了解thisapply

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

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

答案 1 :(得分:0)

在重新定义中,您需要使用thisf函数设置正确的上下文(Function.prototype.apply())。在您的代码中,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/

答案 2 :(得分:0)

使用封装来扩展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)";
    };
  }
})();