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ı?
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ı?
Yanıtlar:
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 augment
ek davranışa sahip olmamasıdır .
fn.apply(this, arguments);
içinreturn fn.apply(this, arguments);
return
en içteki işleve a eklemek gerekiyordu .
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);
};
}());
JS'de bu işlevselliği elde etmek için Proxy kullanmanın yeni bir yolu var . console.log
belirli 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 .
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);
İş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.
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);
}