2012-01-19 88 views
10

我正在使用對象命名空間我的JavaScript代碼。這些對象通常包含稱爲映射this-使用apply指向對象本身的函數。但是,我發現每次我想要訪問對象的其他功能或屬性時都會使用this指針,這很不方便,特別是因爲在很多情況下,我使用new-操作符來使用函數對象。如果new this.Line(),我寧願寫new Line()你能動態添加局部變量到一個函數嗎?

這將是巨大的,如果你可以添加本地變量函數PHP的方式做它用extract(以下僞代碼,這是一個更復雜一點)

var sample_object = { 
    "some_function": function() {} 
} 

test() { 
    extract(sample_object); 
    some_function(); // imported from sample_object 
} 

是,即使可能嗎?

+3

你*可以*使用'with'塊,但是,我不建議這樣做。我也認爲它在ES5嚴格模式下被刪除。 –

+1

@火箭如果我可以這樣做的話,我會高興的不建議它的一部分:-)這是事實,它會起作用,但「與」是混亂和怪異的。此外,我很確定它會導致性能問題,但我不記得對此的解釋。 – Pointy

+0

如果你傳遞一個數組作爲參數會怎麼樣? – elvenbyte

回答

3

存在爭議with,其中有一些great applications,但速度很慢並且容易出錯。它會在嚴格模式下拋出一個錯誤(您應該始終選擇),並且將被棄用。

var sampleObject = { 
    someFunction: function() {}, 
    b: 10 
} 

with (sampleObject) { 
    typeof someFunction // "function" 

    var a = 42 
    var b = 20 
} 

sampleObject.a // undefined 
sampleObject.b // 20 

注意,在with - 塊定義的新變量將不會被添加到該對象。儘管如此,如果對象已經擁有同名屬性,該屬性將被修改(謝謝,@ Rocket)。

只是爲了好玩,這裏的an implementation of extract使用eval(這是更惡,比with)。你可以用它做不可說的事情,例如,如果你的對象有像sampleObject['x; while (true) { alert("Hi!") }']這樣的屬性。

+1

您不能將變量添加到'with'中的對象,但可以修改它們。檢查這個例子:http://jsfiddle.net/HkEVW/ –

+0

@火箭,有價值的說明,謝謝! – katspaugh

4

我很肯定eval是你唯一的答案;但你要知道,如果有涉及您的控制範圍之外的任何輸入時,它是不是安全

function dynamicArgs (varName, varValue) { 
    eval("var " + varName + "=" + JSON.encode(varValue)); 
    alert(a); 
} 

dynamicArgs("a", "value"); 

你可以看到問題與此有關。如果你的函數不知道它的名字,它應該如何調用動態變量?我將它硬編碼爲一個變量,因爲我在調用它時將其傳入,但這不是一個好的解決方案。唯一的解決辦法是另一個eval。你真的應該考慮你需要做什麼以及這是否有用。但它是可行的。

這是在行動:http://jsfiddle.net/mendesjuan/GG3Wu/

function dynamicArgs (varName, varValue) { 
    eval('var ' + varName + "='" + varValue + "';"); 
    alert(eval(varName)); 
} 

dynamicArgs("f", "Here I am"); 

現在這裏就像你正在做的事情爲例,從this.MyConstructor http://jsfiddle.net/mendesjuan/AK3WD/

var ns = { 
    MyConstructor: function(val) { 
     this.prop = val; 
    }, 

    runConstructor: function(val) { 
     var Ctor = "MyConstructor"; 
     eval('var ' + Ctor + ' = this.' + Ctor); 
     return new MyConstructor(val); 
    } 
} 


alert(ns.runConstructor("Hello").prop); 

創建一個變量,在這裏,如果你想有一個例子將對象中的所有值導入範圍;

http://jsfiddle.net/mendesjuan/AK3WD/1/

var ns = { 
    MyConstructor: function(val) { 
     this.val= val; 
    }, 

    anotherProperty: 5, 

    runConstructor: function(val) { 
     // Bring all the variables from this into this scope 
     for (var prop in this) { 
      eval('var ' + prop + ' = this.' + prop); 
     } 
     alert('Testing var anotherProperty: ' + anotherProperty); 
     var obj = new MyConstructor(val); 
     alert('Created MyConstructor: its prop is ' + obj.val) 
    } 
} 


ns.runConstructor("Hello"); 
2

這是我做的:

function smObject (object) { 
    return function() { 
     function getter(prop) { 
      return function() { 
       return this[prop]; 
      } 
     } 

     function setter(prop) { 
      return function(data) { 
       this[prop]=data; 
      } 
     } 

     for (var o = 0; o < object.length; o++) { 
      this[object[o]] = {}; 
      this['get' + object[o]] = getter(object[o]); 
      this['set' + object[o]] = setter(object[o]); 
     } 
    } 
} 

現在你可以實例化這樣的功能:

var fields = ['Name', 'Id', 'Other', '....' ] 
var MyFunction = smObject(fields); 
var myObject = new MyFunction(); 

// getter/setters 
myObject.setId(5); 
myObject.getId(); // will return 5 

問候, Emanouil

相關問題