2011-12-13 21 views
5

Birçok nesne ve işlevlerden (nesne yöntemleri) oluşan bir javascript uygulaması geliştiriyorum. Uygulamanın yaşam döngüsünde birçok olayı günlüğe kaydedebilmek istiyorum. Benim sorunum, logger'ın içinde hangi fonksiyonun log girişini çağırdığını bilmek istiyorum, böylece bu verileri log mesajıyla birlikte kaydedebilirim. Bu, her fonksiyonun bir şekilde kendini referans göstermesi gerektiği anlamına gelir, bu yüzden bu referansı kaydediciye iletebilirim. Javascript sıkı modunu kullanıyorum, bu yüzden işlev içinde arguments.callee kullanılmasına izin verilmiyor.Bir işlev kendi uygulamasından nasıl referans alınır?

Çalıştırabileceğiniz çok basitleştirilmiş bir kod örneği. Ben sadece basitlik için logger'ım yerine alert kullanıyorum. İlk uyarısında

(function(){ 
"use strict"; 

window.myObject = { 
    id : 'myObject', 
    myFunc : function(){ 
     alert(this.id); // myObject 
     alert(this.myFunc.id); // myFunc - I don't want to do this. I want something generic for all functions under any object 
     alert('???') // myFunc 
     alert(arguments.callee.id); // Will throw an error because arguments.callee in not allowed in strict mode 
    } 
} 
myObject.myFunc.id = 'myFunc'; 

myObject.myFunc(); 
})(); 
  1. - this ikinci Ben uyarısında myFunc
  2. için myObject değil ilişkin - Ben I olarak, yapmak istemiyorum Adından tarafından fonksiyonunu başvurulan Bir işlevi kendi uygulamasından referans göstermenin genel bir yolunu arıyorum.
  3. Üçüncü uyarı - fikirlerinizi açık.
  4. Dördüncü uyarı - "use stict"; kullanmamış olsaydım çalışırdı. Daha iyi performans sağladığından ve iyi kodlama uygulaması oluşturduğundan katı modda kalmak istiyorum.

Herhangi bir girdi takdir edilecektir.

siz "Katı modda" ile ilgili bilgi sahibi değilseniz, bu konuda okumak iyi bir yerdir: JavaScript Strict Mode

cevap

4

İşte bunu yapmanın bir çok hacky yolu şudur:

(function(){ 
    "use strict"; 
    window.myObject = { 
     id: 'myObject', 
     myFunc: function() { 
      // need this if to circumvent 'use strict' since funcId doesn't exist yet 
      if (typeof funcId != 'undefined') 
       alert(funcId); 
     }, 
     myFunc2: function() { 
      // need this if to circumvent 'use strict' since funcId doesn't exist yet 
      if (typeof funcId != 'undefined') 
       alert(funcId); 
     } 
    } 
    // We're going to programatically find the name of each function and 'inject' that name 
    // as the variable 'funcId' into each function by re-writing that function in a wrapper 
    for (var i in window.myObject) { 
     var func = window.myObject[i]; 
     if (typeof func === 'function') { 
      window.myObject[i] = Function('var funcId = "' + i + '"; return (' + window.myObject[i] + ')()'); 
     } 
    } 

    window.myObject.myFunc(); 
    window.myObject.myFunc2(); 
})(); 

Esasen, biz bu işlevin adını bulduktan sonra bir karakter dizisinden her işlevi yeniden derlenerek 'kullanmak sıkı' beyanı engellemeyi edilmektedir. Bunu yapmak için, hedef fonksiyonumuzun ismine eşit bir 'funcId' string değişkenini bildiren her bir fonksiyonun etrafında bir sarıcı yaratırız, böylece değişken artık kapama yoluyla fonksiyona maruz kalır.

Eh, işleri yapmanın en iyi yolu değil, ama işe yarıyor. Alternatif, sadece içinden olmayan bir katı işlevini çağırabilirsiniz: yardımcı

(function(){ 
    "use strict"; 

    window.myObject = { 
     id: 'myObject', 
     myFunc: function() { 
      alert(getFuncName()) 
     }, 
     myFunc2: function() { 
      alert(getFuncName()); 
     } 
    } 
})(); 

// non-strict function here 
function getFuncName(){ 
    return arguments.callee.caller.id; // Just fyi, IE doesn't have id var I think...so you gotta parse toString or something 
} 

Umut.

+0

Teşekkürler! Bunlar güzel çözümler :) –

0
myFunc : function _myFunc(){ 
    alert(_myFunc); // function 
} 

adı fonksiyonları ve günlük amacını çözmek için doğrudan

bunlara başvuruda , gerçek mantıklı benzersiz kayıt mesajları kullanın. Hat bilgisi istiyorsanız, bir istisna atın.

+1

Daha genel bir şey arıyorum, bu yüzden her işlevi kendi adına göre göndermem gerekmiyor. 'Bu' bağlamı ifade eder ve içeriğin adını kullanmak zorunda değilim. –

+0

@OrrSiloni mevcut değil. Fonksiyon ismini kullan. Ayrıca, tüm fonksiyonlarınızın bir ismi olmalı, hatırlayın. – Raynos

+0

Fonksiyonun ismini kaydediciden geçirmekten kaçış olmayacağını düşünüyorum. Hala birinin beni zarif bir çözümle şaşırtacağını umuyordum. –

0

Ne yapmak istediğinizi düşünmüyorum (geçerli işlevin adını bulmak) çok kolay.

function logger(id){ return function(msg){ 
    return console.log(id, msg); 
};} 

window.myObject = { 
    id : 'myObject', 
    myFunc : function(){ 
     var log = logger('myFunc'); 

     log(1); //prints "Myfunc, 1" 
     log(2); //prints "Myfunc, 2" 
    } 
}; 

Bu bir polis türüdür dışarı ama şudur: (gibi C __line__ gibi şeyler için yapılır) ama belki biraz OO/sihirli currying hile yapan bir ön işleme adımını ekleyerek içine bakmak isteyebilirsiniz Çok basit ve sadece kimlikleri ve işlev isimlerini yolunda tutmayı unuttuysanız makul şekilde yönetilebilir.

+0

Bu güzel bir yaklaşım, ama her işlevin başlangıcında her zaman logger'ı çağırmak ve fonksiyonun adını string olarak iletmek zorundayım. –

+0

@OrrSiloni: Biliyorum, ama en azından bir kere bunu yapman gerekiyor ve aynı işlevde isimsiz ve isimsiz isimlerle de çalışıyor. – hugomg

İlgili konular