有没有办法在不修改Object.prototype的情况下为所有对象提供方法?

时间:2015-08-13 17:58:37

标签: javascript

我想使用日志记录功能扩充我的Node.js应用程序中的所有对象,这样每个对象都可以调用this.loglog引用thatObject.log函数。我认为这样做有很多好处:

  • 我可以修改每个对象的log函数,以便生成特殊输出和
  • 如果没有提供特定于对象的log函数,它可以在其原型链上找到log函数,并且
  • 在全球范围内,this.log引用Object.prototype.log,在任何其他情况下,this.log引用该对象的log

例如:

Object.prototype.log = function(message) {
    console.log(message);
};

function Person(name) {
    this.name = name;
};

Person.prototype.log = function(message) {
    console.log(this.name + " says " + message);
};

function Ghost() {
};

var joe = new Person("joe");
joe.log("Hi!"); //"Joe says Hi!"
var boo = new Ghost();
boo.log("Boo!"); //"Boo!"

//I can call this in any object context, and get a context-specific message
//This includes the global context, like so
this.log("Log!"); //"Log!"

不幸的是,由于外部依赖的限制,我无法修改Object.prototype(不仅仅是命名空间问题)。 有没有办法在不修改Object.prototype的情况下执行此操作?

最重要的是,我希望保留从任何地方调用this.log的行为。

更新:我找到了针对此特定问题的解决方法。 See my answer below.

2 个答案:

答案 0 :(得分:1)

正如Oriol已经指出的那样,不可能。以下是几种选择:

var log = function(message) {
  var msg = message || '';
  console.log(JSON.stringify(this) + msg);
}

//later in the code
log.call(this, 'Log!'); //prints the stringified Object plus 'Log!'

另一个替代方案,如果你使用构造函数将使所有这些函数都使用所需的方法从构造函数继承(尽管这并不能满足你甚至是全局上下文的要求)。

答案 1 :(得分:0)

虽然我已经接受了Oriol的答案作为原始问题的最佳答案,但我找到了针对我的具体问题的可用解决方法,从任何上下文启用log

  • 在全局范围内定义log函数,在this.log引用全局对象时启用this
  • 创建一个Logger类,其原型上定义了log函数。
  • 使任何具有log功能的类在某个原型链中都有Logger

这并不理想,因为现在类必须在其原型链中的某个位置具有Logger,无论是手动添加还是继承,但它确实确保该类存在log函数。在原始示例中实现,

function log(message) {
    console.log(message);
}

function Logger() {};

Logger.prototype.log = function(message) {
    console.log(message);
};

function Person(name) {
    this.name = name;
};

Person.prototype = Object.create(Logger.prototype);

Person.prototype.log = function(message) {
    console.log(this.name + " says " + message);
};

function Ghost() {
};

Ghost.prototype = Object.create(Logger.prototype);

var joe = new Person("joe");
joe.log("Hi!"); //"Joe says Hi!"
var boo = new Ghost();
boo.log("Boo!"); //"Boo!"
this.log("Log!"); //"Log!"