Her işleve otomatik olarak console.log ekleme


97

Herhangi bir işlevin bir yere global bir kanca kaydedilerek (yani, gerçek işlevin kendisini değiştirmeden) veya başka bir yolla çağrıldığında bir console.log ifadesi çıktısı oluşturmanın bir yolu var mı?


mükemmel bir soru, bunun mümkün olup olmadığını bilmek isterim ama kesinlikle olmadığına eminim ... En sevdiğiniz tarayıcınız için js motoruna eklenmesi için bir özellik isteği ekleyebilirsiniz. :-)
Endophage

Mükemmel soru, buna benzer bir şeye ihtiyacım var
mjimcua

Yanıtlar:


62

Seçtiğiniz işlevle genel ad alanındaki tüm işlevleri artırmanın bir yolu:

function augment(withFn) {
    var name, fn;
    for (name in window) {
        fn = window[name];
        if (typeof fn === 'function') {
            window[name] = (function(name, fn) {
                var args = arguments;
                return function() {
                    withFn.apply(this, args);
                    return fn.apply(this, arguments);

                }
            })(name, fn);
        }
    }
}

augment(function(name, fn) {
    console.log("calling " + name);
});

Bir dezavantajı, çağırmadan sonra oluşturulan hiçbir işlevin augmentek davranışa sahip olmamasıdır .


İşlevin dönüş değerlerini doğru şekilde işliyor mu?
SunnyShah

2
@SunnyShah Hayır öyle değil: jsfiddle.net/Shawn/WnJQ5 Ama bu yapar: jsfiddle.net/Shawn/WnJQ5/1 değilim rağmen emin ... fark değişiyor TÜM durumlarda çalışacak fn.apply(this, arguments);içinreturn fn.apply(this, arguments);
Shawn

2
@Shawn @SunnyShah Düzeltildi. Sadece returnen içteki işleve a eklemek gerekiyordu .
Wayne

neredeyse iyi çalışıyor ancak bu jquery ile bir hata alıyorum: call: if (jQuery.isFunction (lSrc)) ve şöyle diyor: TypeError: jQuery.isFunction bir işlev değil
fekiri malek

4
Bu çözüm jQuery kullanmıyor
Wayne

10

Bana gelince, bu en zarif çözüm gibi görünüyor:

(function() {
    var call = Function.prototype.call;
    Function.prototype.call = function() {
        console.log(this, arguments); // Here you can do whatever actions you want
        return call.apply(this, arguments);
    };
}());

7

İşlev çağrılarını günlüğe kaydetmek için Proxy Yöntemi

JS'de bu işlevselliği elde etmek için Proxy kullanmanın yeni bir yolu var . console.logbelirli bir sınıfın bir işlevi çağrıldığında bir a sahip olmak istediğimizi varsayalım :

class TestClass {
  a() {
    this.aa = 1;
  }
  b() {
    this.bb = 1;
  }
}

const foo = new TestClass()
foo.a() // nothing get logged

sınıf somutlaştırmamızı bu sınıfın her bir özelliğini geçersiz kılan bir Proxy ile değiştirebiliriz. yani:

class TestClass {
  a() {
    this.aa = 1;
  }
  b() {
    this.bb = 1;
  }
}


const logger = className => {
  return new Proxy(new className(), {
    get: function(target, name, receiver) {
      if (!target.hasOwnProperty(name)) {
        if (typeof target[name] === "function") {
          console.log(
            "Calling Method : ",
            name,
            "|| on : ",
            target.constructor.name
          );
        }
        return new Proxy(target[name], this);
      }
      return Reflect.get(target, name, receiver);
    }
  });
};



const instance = logger(TestClass)

instance.a() // output: "Calling Method : a || on : TestClass"

bunun Codepen'de gerçekten çalıştığını kontrol edin


Kullanmanın Proxy, yalnızca konsol adlarını günlüğe kaydetmekten çok daha fazla işlevsellik sağladığını unutmayın.

Ayrıca bu yöntem Node.js'de de çalışır .


Bunu örnekleri ve sınıfları kullanmadan da yapabilir misiniz? Özellikle node.js ile mi konuşuyorsunuz?
Revadike

@Revadike bunun yardımcı olması gerekir: stackoverflow.com/a/28708700/5284370
Soorena

1

Daha hedefli günlük kaydı istiyorsanız, aşağıdaki kod belirli bir nesne için işlev çağrılarını günlüğe kaydedecektir. Tüm yeni örneklerin de günlüğe kaydedilmesi için Nesne prototiplerini bile değiştirebilirsiniz. For ... in yerine Object.getOwnPropertyNames kullandım, bu yüzden numaralandırılabilir yöntemleri olmayan ECMAScript 6 sınıflarıyla çalışıyor.

function inject(obj, beforeFn) {
    for (let propName of Object.getOwnPropertyNames(obj)) {
        let prop = obj[propName];
        if (Object.prototype.toString.call(prop) === '[object Function]') {
            obj[propName] = (function(fnName) {
                return function() {
                    beforeFn.call(this, fnName, arguments);
                    return prop.apply(this, arguments);
                }
            })(propName);
        }
    }
}

function logFnCall(name, args) {
    let s = name + '(';
    for (let i = 0; i < args.length; i++) {
        if (i > 0)
            s += ', ';
        s += String(args[i]);
    }
    s += ')';
    console.log(s);
}

inject(Foo.prototype, logFnCall);

-1

İşte Javascript'teki her işleve console.log ekleyen bazı Javascript; Üzerinde onunla oynamak Regex101 :

$re = "/function (.+)\\(.*\\)\\s*\\{/m"; 
$str = "function example(){}"; 
$subst = "$& console.log(\"$1()\");"; 
$result = preg_replace($re, $subst, $str);

Bu 'hızlı ve kirli bir hack'tir, ancak hata ayıklama için yararlı buluyorum. Çok fazla işleviniz varsa, dikkatli olun çünkü bu çok fazla kod ekleyecektir. Ayrıca, RegEx basittir ve daha karmaşık işlev adları / bildirimi için çalışmayabilir.


-10

Aslında, yüklenen her şey için console.log dosyasına kendi işlevinizi ekleyebilirsiniz.

console.log = function(msg) {
    // Add whatever you want here
    alert(msg); 
}

2
doğru ya da değil, soruyu cevaplamıyor. hiç. (kimsenin hala kafası karışmışsa)
redfox05
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.