2012-01-19 35 views
10

Tôi đang sử dụng các đối tượng để không gian tên mã JavaScript của mình. Các đối tượng này thường chứa các hàm được gọi là ánh xạ con trỏ this tới chính đối tượng đó bằng cách sử dụng apply. Tuy nhiên, tôi thấy bất tiện khi sử dụng this -pointer mỗi lần tôi muốn truy cập các chức năng hoặc thuộc tính khác của đối tượng, đặc biệt là vì trong nhiều trường hợp tôi sử dụng máy chủ new để sử dụng các đối tượng chức năng theo cách bạn sử dụng các lớp. Tôi muốn viết new Line() thay vì nếu new this.Line().Bạn có thể tự động thêm các biến cục bộ vào một hàm không?

Nó sẽ là tuyệt vời nếu bạn có thể thêm các biến địa phương để một chức năng đường php hiện điều đó với extract (sau đây giả, đó là một chút phức tạp hơn)

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

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

Là thậm chí có thể?

+3

Bạn *có thể* sử dụng một khối 'with', nhưng, tôi không đề nghị nó. Tôi cũng nghĩ rằng nó bị loại bỏ trong chế độ nghiêm ngặt ES5. –

+1

@Rocket Tôi uparrow không đề xuất nó một phần nếu tôi có thể :-) Đó là sự thật nó muốn làm việc, nhưng 'with' là khó hiểu và kỳ lạ. Ngoài ra tôi khá chắc chắn nó gây ra vấn đề hiệu suất nhưng tôi không thể nhớ lời giải thích cho điều đó. – Pointy

+0

Nếu bạn vượt qua một mảng làm đối số thì sao? – elvenbyte

Trả lời

3

Có tranh cãi with, có một số great applications, nhưng hơi chậm và dễ bị lỗi. Nó ném một lỗi trong chế độ nghiêm ngặt (mà bạn nên luôn luôn chọn tham gia) và sẽ không được chấp nhận.

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

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

    var a = 42 
    var b = 20 
} 

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

Lưu ý rằng các biến mới được xác định trong khóa with sẽ không được thêm vào đối tượng. Tuy nhiên, nếu đối tượng đã có một thuộc tính cùng tên trong đó, thuộc tính này sẽ được sửa đổi (cảm ơn, @Rocket).

Chỉ để giải trí, đây là an implementation of extract sử dụng eval (thậm chí còn độc ác hơn with). Bạn có thể làm những điều không thể nói ra với nó, ví dụ nếu đối tượng của bạn có các thuộc tính như sampleObject['x; while (true) { alert("Hi!") }'].

+1

Bạn không thể thêm biến vào một đối tượng trong 'with', nhưng bạn có thể sửa đổi chúng. Kiểm tra ví dụ này: http://jsfiddle.net/HkEVW/ –

+0

@Rocket, làm rõ giá trị, cảm ơn! – katspaugh

4

Tôi chắc chắn eval là câu trả lời duy nhất của bạn; nhưng bạn cần phải lưu ý rằng nếu có bất kỳ đầu vào ngoài tầm kiểm soát của bạn có liên quan, nó không phải là an toàn

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

dynamicArgs("a", "value"); 

Bạn có thể thấy vấn đề với điều này. Hàm của bạn được gọi là biến động như thế nào nếu nó không biết tên của nó? Tôi hardcoded nó vào một biến kể từ khi tôi vượt qua nó trong khi gọi nó, nhưng đó không phải là một giải pháp tốt. Giải pháp duy nhất sẽ là eval khác. Bạn thực sự nên suy nghĩ về những gì bạn cần làm và cho dù điều này là hữu ích. Nhưng nó có thể thực hiện được.

Đây là nó trong hành động: http://jsfiddle.net/mendesjuan/GG3Wu/

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

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

Bây giờ đây là một ví dụ như những gì bạn đang làm, tạo ra một biến từ 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); 

Và đây là một ví dụ nếu bạn muốn để nhập tất cả các giá trị từ một đối tượng vào phạm vi;

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

Đây là cách tôi đã làm nó:

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]); 
     } 
    } 
} 

bây giờ bạn có thể nhanh chóng một chức năng như thế này:

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

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

Kính trọng, Emanouil

Các vấn đề liên quan