2011-05-03 10 views
29

Bu, Google Chrome hata ayıklayıcısını kullanarak beni rahatsız eden bir şeydir ve bunu çözmenin bir yolu olup olmadığını merak ettim.Javascript'te bir işlev/nesne adını, Chrome'da görüntülendiği şekliyle dinamik olarak ayarlama

Nesne yönelimli bir çok JS kullanarak (Joose çerçevesini kullanarak) büyük bir Javascript uygulamasında çalışıyorum ve kodumu hata ayıkladığımda tüm sınıflarıma duyarlı olmayan bir ilk görüntü değeri verilir.

var F = function() {}; 
var myObj = new F(); 

console.log(myObj); 

çıktı sen myObj tüm özellikleri görmek için genişleyebilir tek bir satır olmalı, ama gördüğünüz ilk şey sadece ▶ F geçerli: Ne demek istediğimi görmek için Chrome konsolunda bu deneyin.

Sorunum, OO çerçevem ​​nedeniyle, her başlatılan nesnenin aynı adı ' alır. Göründüğü kod sorumludur yüzden gibidir:

ayıklayıcısında, başlangıçtaki görünüm her zaman ▶ f olduğu anlamına gelir
getMutableCopy : function (object) { 
    var f = function() {}; 
    f.prototype = object; 
    return new f(); 
} 

. Joose nesneleri aniden nasıl

Şimdi, gerçekten hakkında bir şey değişiyor gibi istemiyoruz (getMutableCopy ...?), ama kendi verebileceğini de bu yüzden bu eklemek bir şey olsaydı İsim, bu harika olurdu.

ben baktım bazı şeyleri ama hiçbir yere alamadım:

> function foo {} 
> foo.name 
    "foo" 
> foo.name = "bar" 
    "bar" 
> foo.name 
    "foo" // <-- looks like it is read only 
+0

Ayrıca bkz [? Javascript Dinamik işlev adı] (https://stackoverflow.com/questions/ 5905492/dynamic-function-name-in-javascript/41854075 # 41854075) – gimpf

cevap

-1

normalde window[name] gibi bir işlev size yol açacak olan

var name ="bar"; 
window["foo"+name] = "bam!"; 
foobar; // "bam!" 

gibi kullanın:

function getmc (object, name) { 

    window[name] = function() {}; 
    window[name].prototype = object; 
    return new window[name](); 

} 

ama sonra

Eğer bir return ifadesi ( eval("return new name()");) eval olamaz çünkü
foo = function(){}; 
foobar = getmc(foo, "bar"); 
foobar; // ▶ window 
foobar.name; // foo 
x = new bar; x.name; // foo .. not even nija'ing the parameter works 

ve Bence sen çirkin olsa da, eval() üzerinden aldatabildin

+0

lütfen bu downvoting durdurmak .. Cevabını –

+1

değiştirdikten sonra doğru cevap o zaman pls silmek veya cevabınızı güncellemek. –

+0

Duygular için ;-) – lama12345

5

sıkışmış:

function copy(parent, name){ 
    name = typeof name==='undefined'?'Foobar':name; 
    var f = eval('function '+name+'(){};'+name); 
    f.prototype = parent; 
    return new f(); 
} 

var parent = {a:50}; 
var child = copy(parent, 'MyName'); 
console.log(child); // Shows 'MyName' in Chrome console. 

Dikkat : Sadece işlev isimleri olarak geçerli olabilecek isimleri kullanabilirsiniz!

Ek: Her Nesne örnekleme üzerinde eval ing önlemek bir önbellek kullanmak için:

function Cache(fallback){ 
    var cache = {}; 

    this.get = function(id){ 
    if (!cache.hasOwnProperty(id)){ 
     cache[id] = fallback.apply(null, Array.prototype.slice.call(arguments, 1)); 
    } 
    return cache[id]; 
    } 
} 

var copy = (function(){ 
    var cache = new Cache(createPrototypedFunction); 

    function createPrototypedFunction(parent, name){ 
    var f = eval('function '+name+'(){};'+name); 
    f.prototype = parent; 
    return f; 
    } 

    return function(parent, name){ 
    return new (cache.get(name, parent, typeof name==='undefined'?'Foobar':name)); 
    }; 
})(); 
+0

+1 - güzel fikir. Ne yazık ki, her bir nesne örneğinde bir değerlendirme yapmanın performans maliyetinden çok korkuyorum. – nickf

+0

Önbellekli bir sürüm eklendi. – GodsBoss

+0

Dizinin geçtiği işler. Fakat yapıcı işlevini adlandırılmış işleve iletmem gerekiyor. –

2

Bu tamamen sorununuzu çözmez, ama sınıfının prototip üzerinde toString yöntemi geçersiz öneririm. Örneğin:

my_class = function() {} 
my_class.prototype.toString = function() { return 'Name of Class'; } 

Eğer (Ben bu konuda bir şey yapmak mümkün olduğunu sanmıyorum) doğrudan konsoldaki my_class bir örneğini girerseniz Hala orijinal sınıf adını görürsünüz ancak elde edersiniz Çok yardımcı bulduğum hata mesajlarındaki güzel isim.Örneğin: "TypeError:: Sınıfı Nesne Adı 'does_not_exist' hayır yöntemi vardır"

14

Son 3 saat boyunca bu etrafında oynuyorsun ve nihayet got

a = new my_class() 
a.does_not_exist() 

hata mesajı verecek diğer iş parçacığı üzerinde önerildiği gibi en azından biraz şık yeni İşlevini kullanarak:

/** 
* JavaScript Rename Function 
* @author Nate Ferrero 
* @license Public Domain 
* @date Apr 5th, 2014 
*/ 
var renameFunction = function (name, fn) { 
    return (new Function("return function (call) { return function " + name + 
     "() { return call(this, arguments) }; };")())(Function.apply.bind(fn)); 
}; 

/** 
* Test Code 
*/ 
var cls = renameFunction('Book', function (title) { 
    this.title = title; 
}); 

new cls('One Flew to Kill a Mockingbird'); 

yukarıdaki kod çalıştırırsanız, konsola aşağıdaki çıktıyı görmelisiniz:

Book {title: "One Flew to Kill a Mockingbird"} 
+1

Gibi görünüyor [Çalışma zamanı-kararlı bir ad ile bir işlev oluşturmak için eval olmayan bir yolu var mı?] (Http://stackoverflow.com/q/9479046/1048572) :-) – Bergi

+0

Bu sınıf için kullanılabilir mi (es6) Tipik bir Fonksiyon nedir? –

0

Bu dinamik bir fonksiyonun adını ayarlamak için en iyi yol olduğunu düşünüyorum:

Function.prototype.setName = function (newName) { 
     Object.defineProperty(this,'name', { 
      get : function() { 
       return newName; 
      } 
     }); 
    } 

Şimdi sadece setName yöntemini

function foo() { } 
foo.name; // returns 'foo' 

foo.setName('bar'); 
foo.name; // returns 'bar' 

foo.name = 'something else'; 
foo.name; // returns 'bar' 

foo.setName({bar : 123}); 
foo.name; // returns {bar : 123} 
+1

Google Chrome, konsolda hatayı atar "TypeError: Özellik yeniden tanımlanamaz: name" –

37
Object.defineProperty(fn, "name", { value: "New Name" }); 

hile yapacak çağırmanız gerekir ve en performanslı çözümdür. Hiçbir değerlendirme de yok.

+0

Şimdiye kadar en iyi cevap. Aksi takdirde salt okunur olan adlar gibi özellikleri tanımlamak için kullanılan API'yi kullanır. – Michael

+2

Bu benim için çalışmıyor gibi görünüyor: '' 'function caat() {this.legs = 4; } Object.defineProperty (CAAT, "adı," {değeri: "kedi"}) milo = yeni CAAT() CAAT {bacaklar: 4} '' ' I çıkışını kontrol etmek için umut ediyorum Son satırın adını yazabilir, ancak konsola yazdırırken ad özelliğini kullanmaz. – speg

+0

"caat" prototipini "Object.defineProperty (caat.prototype," name ", {value:" cat "})' gibi düzenlemek istediğiniz gibi görünüyor. – Piercey4

0
@ Piercey4 cevaba benzer

, ama ben de mesela name ayarlamak zorunda:

function generateConstructor(newName) { 
    function F() { 
    // This is important: 
    this.name = newName; 
    }; 

    Object.defineProperty(F, 'name', { 
    value: newName, 
    writable: false 
    }); 

    return F; 
} 

const MyFunc = generateConstructor('MyFunc'); 
const instance = new MyFunc(); 

console.log(MyFunc.name); // prints 'MyFunc' 
console.log(instance.name); // prints 'MyFunc' 
İlgili konular