2011-05-03 20 views
29

這是Google Chrome調試器一直在困擾我的東西,我想知道是否有辦法解決它。如何在Javascript中動態設置功能/對象名稱,因爲它顯示在Chrome中

我正在使用大量面向對象的JS(使用Joose框架),並且當我調試我的代碼時,我的所有類都被賦予非感性的初始顯示值。要明白我的意思,試試這個在Chrome控制檯:

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

console.log(myObj); 

輸出應該是一個單一的線,你可以擴展看到myObj所有屬性,但你看到的第一件事就是▶ F

我的問題是,因爲我的面向對象框架,每個單個對象實例化得到相同的'名稱'。這看起來的代碼負責,這是像這樣:

getMutableCopy : function (object) { 
    var f = function() {}; 
    f.prototype = object; 
    return new f(); 
} 

這意味着在調試器,初始視圖始終是▶ f

現在,我真的不希望被改變了人們什麼 Joose如何實例化對象(getMutableCopy ...?),但好像有什麼事我可以添加到這個,這樣我可以提供我自己的名字,那會很棒。

,我已經看了一些東西,但不能隨地獲取:

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

參見[?在JavaScript動態函數名(https://stackoverflow.com/questions/ 5905492 /動態功能名稱在JavaScript/41854075#41854075) – gimpf 2017-12-06 08:35:35

回答

-1

正常使用window[name]

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

這將導致你的功能,如:

function getmc (object, name) { 

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

} 

但是然後

foo = function(){}; 
foobar = getmc(foo, "bar"); 
foobar; // ▶ window 
foobar.name; // foo 
x = new bar; x.name; // foo .. not even nija'ing the parameter works 

因爲你不能EVAL return語句(eval("return new name()");),我想,你就完蛋了

+0

請停止downvoting this ..我的回答是正確的,然後他改變了問題 – 2015-02-01 16:09:02

+1

然後請刪除或更新您的答案。 – 2016-05-14 22:02:02

+0

Upvote的感覺;-) – lama12345 2017-05-10 06:16:33

5

雖然這是醜陋的,你可以通過eval()函數騙:

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. 

當心:你只能使用與函數名一樣有效的名字!

附錄:爲了避免對每一個對象實例化eval ING,使用緩存:

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 - 好主意。不幸的是,我太害怕在每個對象實例化上執行eval的性能成本。 – nickf 2011-05-06 09:28:58

+0

增加了一個緩存版本。 – GodsBoss 2011-05-07 12:23:04

+0

適用於數組傳遞。但我需要將構造函數傳遞給指定的函數。 – 2013-08-13 14:50:50

2

這並不能完全解決問題,但我會建議重寫對類的原型toString方法。例如:

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

您仍然會看到原來的類名,如果你直接在控制檯輸入my_class的一個實例(我不認爲這是可能做到這事),但你會得到錯誤消息中的好名字,我覺得這很有幫助。例如:

a = new my_class() 
a.does_not_exist() 

會給出錯誤信息:「類型錯誤:類對象名稱沒有方法‘does_not_exist’」

14

我一直在玩這個圍繞在過去3小時,終於拿到了它至少幾分優雅使用新功能的其他線程的建議:

/** 
* 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'); 

如果你運行上面的代碼,你應該看到下面的輸出到您的控制檯:

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

看起來像[有什麼非eval的方式來創建一個運行時間確定的名稱功能?](http://stackoverflow.com/q/9479046/1048572):-) – Bergi 2015-04-04 21:28:31

+0

是否可用於類(es6)這是一種功能? – 2016-12-05 03:48:38

0

我覺得這是動態設定函數的名稱的最好方式:

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

現在你只需要調用setName方法

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在控制檯中拋出錯誤「TypeError:無法重新定義屬性:名稱」 – 2015-10-25 20:21:28

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

會做的伎倆並且是最高性能的解決方案。沒有評估。

+0

迄今爲止最好的答案。它使用旨在定義屬性的API,例如以其他方式只讀的名稱。 – Michael 2016-06-06 03:20:38

+2

這似乎不適合我: '''function caat(){this.legs = 4; } Object.defineProperty(CAAT, 「姓名」,{值: 「貓」}) 蜀黍=新CAAT() CAAT {腿:4}''' 我希望控制的輸出名稱在最後一行,但在打印到控制檯時似乎沒有使用name屬性。 – speg 2016-07-21 12:09:55

+0

看起來像你想像'Object.defineProperty(caat.prototype,「name」,{value:「cat」})''編輯'caat'原型''。 – Piercey4 2016-07-22 00:47:17

0

到@ Piercey4答案相似,但我不得不設置name爲實例,以及:

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' 
相關問題