Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/404.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 记录每种方法?_Javascript_Node.js_Coffeescript - Fatal编程技术网

Javascript 记录每种方法?

Javascript 记录每种方法?,javascript,node.js,coffeescript,Javascript,Node.js,Coffeescript,不必为跟踪创建自定义记录器(例如,遵循调用了哪些方法以及实例化了哪些类),是否有一种简单的方法可以让类日志下的所有方法都记录下来?这适用于node.js应用程序 class MyClass constructor: () -> console.log 'MyClass:constructor' doThat: () -> console.log 'MyClass:doThat' exports.MyClass = MyClass myClass = n

不必为跟踪创建自定义记录器(例如,遵循调用了哪些方法以及实例化了哪些类),是否有一种简单的方法可以让类日志下的所有方法都记录下来?这适用于node.js应用程序

class MyClass

  constructor: () ->
    console.log 'MyClass:constructor'

  doThat: () ->
    console.log 'MyClass:doThat'

exports.MyClass = MyClass

myClass = new MyClass()
myClass.doThat()

如果按照我的方式,您将看到4日志消息,而不是2条(因此必须编写更少的代码来跟踪正在发生的事情)。

我最近需要实现类似的东西来跟踪一些复杂的OO递归内容。基本上,我想让一种方法“可追踪”,而不会造成太多污染;因此,也许这个解决方案也可以在这里应用

首先,添加一个使其他函数可跟踪的函数:

Function::trace = do ->
  makeTracing = (ctorName, fnName, fn) ->
    (args...) ->
      console.log "#{ctorName}:#{fnName}"
      fn.apply @, args
  (arg) ->
    for own name, fn of arg 
      @prototype[name] = makeTracing @name, name, fn
然后,要使用它,只需在要跟踪的每个方法之前添加一个
@trace

class MyClass
  @trace methodA: ->
    @methodB 42

  @trace methodB: ->
    console.log "method b called with #{n}"
或者只添加@trace一次,然后将所有可跟踪方法缩进一个级别:

class MyClass
  @trace 
    methodA: ->
      @methodB 42

    methodB: (n) ->
      console.log "method b called with #{n}"
正如您所看到的,
trace
有点滥用CoffeeScript的语法<代码>方法:->“foo”在
类MyClass中被解释为方法定义。但是
@trace方法:->'foo'
被解释为调用
MyClass
trace
函数(这是一个
function
实例,我们在其中添加了
trace
函数),通过一个
方法
键传递一个文本对象。在JavaScript中,它类似于
this.trace({method:function(){return'foo';}}})

trace
函数只需获取该对象并迭代它的键(方法名称)和值(方法),然后将函数添加到
MyClass
原型中,该原型记录它们的调用,然后调用原始方法

无论如何,
(新MyClass).methodA()的输出将是:

MyClass:methodA
MyClass:methodB
方法b使用42调用
这个解决方案不适用于构造函数,因为它们不仅仅是普通的方法

你可以很喜欢这个。您还可以记录传递给每个方法的参数、返回值,甚至可以根据需要为嵌套调用添加缩进(如果需要调试复杂的问题=D,则生成的跟踪将非常有用)


更新:作为一个更有趣的示例,这里是典型复合模式示例的一个小版本,几何图形和图形组:具有更有趣的跟踪功能。所有图形都理解
move
方法。如果我们有这个合成图并在上面调用
move

f = new Composite [
  new Rectangle 5, 10, 3, 4
  new Composite [
    new Circle 0, 0, 2
    new Circle 0, 0, 4
    new Circle 0, 0, 6
  ]
]

f.move 2, 3
跟踪输出为:

(合成[矩形[5,10,3,4],合成[圆[0,0,2],圆[0,0,4],圆[0,0,6]])。移动(2,3)
|(矩形[5,10,3,4])。移动(2,3)
|->矩形[7,13,3,4]
|(合成[圆[0,0,2],圆[0,0,4],圆[0,0,6]])。移动(2,3)
||(圆[0,0,2])。移动(2,3)
||->圆[2,3,2]
||(圆[0,0,4])。移动(2,3)
||->圆圈[2,3,4]
||(圆[0,0,6])。移动(2,3)
||->圆圈[2,3,6]
|->复合[圆[2,3,2],圆[2,3,4],圆[2,3,6]]
->合成[矩形[7,13,3,4],合成[圆[2,3,2],圆[2,3,4],圆[2,3,6]]

如果您想使用普通的旧javascript来实现这一点,我创建了一个服务,您可以向该服务传递一个对象,该对象将返回一个具有记录每个方法的相同API的对象。请参见应用polyfill的完整示例

基本思想是:

var api = {
   notAMethod: "blah",
   foo: function() {
    console.log("in foo", arguments);
   },

   bar: function(arg) {
    this.foo(arg);
    return this.notAMethod;
   }
}; 

//wrap the api with a logging version
//to watch property changes and keep them in sync, you need the polyfill for Object.watch
//     from https://gist.github.com/eligrey/384583

var createLogger = function(api) {
     var loggingApi = {};

            for (var prop in api) {
                if (typeof api[prop] !== 'function') {
                   loggingApi[prop] = api[prop]; 
                   loggingApi.watch(prop, function(prop, oldVal, newVal){
                       api[prop] = newVal
                       return newVal;
                   });


                } else {

                    loggingApi[prop] = function() {
                        console.log(prop + "() called with args: ", arguments);
                        var returnVal = api[prop].apply(api, arguments);
                         console.log(prop + "() returned: " + returnVal);
                        return returnVal;
                    }
                }
            }
      return loggingApi;
 };
 api.foo('Shhhh... don\'t log me') //no logging
 createLogger(api).foo(); //with logging           

这很酷。记录参数的能力也是我一直在思考的问题。谢谢@FrankLoVecchio很酷。我用一个例子更新了答案,根据递归级别记录参数、返回值并缩进日志=d这将是一个非常有用的StackOverflow问题:)您可能知道这会破坏主干木偶触发器的原因吗@弗兰克洛夫曹,这真是出乎意料!无论如何,这不是木偶的错。JSFiddle使用的CoffeeScript编译器是一个旧版本(1.1.2),它弄乱了那里的语法(我说它有点滥用语法,呵呵)。您可以看到,比较第二个链接中生成的JS代码(在JSFIDLE中显示JS)和使用相同的CS输入在中生成的内容。但是不要担心,如果你使用最新的CS版本,它只是罚款=D