2013-08-12 45 views
0

我想爲基於Json文件的對象編寫getter和setter函數。我複製了John Resig的書(Appress Pro JavaScript Techniques)的下面的代碼,但它不起作用,並且這些函數不會添加到對象中。您能否告訴我爲什麼以及什麼是正確的代碼?爲什麼這些JavaScript函數不會添加到此對象中?

// Create a new user object that accepts an object of properties 
function User(properties) { 
// Iterate through the properties of the object, and make sure 
// that it's properly scoped (as discussed previously) 
    for (var i in properties) { 
    (function() { 
     // Create a new getter for the property 
     this["get" + i] = function() { 
      return properties[i]; 
     }; 

     // Create a new setter for the property 
     this["set" + i] = function (val) { 
      properties[i] = val; 
     }; 
    })(); 
    } 
} 

// Create a new user object instance and pass in an object of 
// properties to seed it with 
var user = new User({ 
name: "Bob", 
age: 44 
}); 

// Just note that the name property does not exist, as it's private 
// within the properties object 
//alert(user.name == null); 

// However, we're able to access its value using the new getname() 
// method, that was dynamically generated 
alert(user.getname()); 

回答

3

你使用的函數來創建一個封閉,但你忘了通過i進去。您還需要在函數內的this的不同參考,因爲上下文在其中更改爲window

function User(properties) { 
    var i, me = this; 
    for (i in properties) (function (i) { 
     // Create a new getter for the property 
     me["get" + i] = function() { // using `me` because `this !== me` 
      return properties[i]; 
     }; 

     // Create a new setter for the property 
     me["set" + i] = function (val) { 
      properties[i] = val; 
     }; 
    }(i)); // i passed into function closure 
} 
2

在你IIFE,this實際上是window。您可以通過使用Function.prototype.call指定上下文:

function User(properties) { 
    // Iterate through the properties of the object, and make sure 
    // that it's properly scoped (as discussed previously) 
    for (var i in properties) { 
     (function(i) { 
      // Create a new getter for the property 
      this["get" + i] = function() { 
       return properties[i]; 
      }; 

      // Create a new setter for the property 
      this["set" + i] = function(val) { 
       properties[i] = val; 
      }; 
     }).call(this, i); 
    } 
} 

或者保持對它的引用與另一個變量:

function User(properties) { 
    var that = this; 

    // Iterate through the properties of the object, and make sure 
    // that it's properly scoped (as discussed previously) 
    for (var i in properties) { 
     (function(i) { 
      // Create a new getter for the property 
      that["get" + i] = function() { 
       return properties[i]; 
      }; 

      // Create a new setter for the property 
      that["set" + i] = function(val) { 
       properties[i] = val; 
      }; 
     })(i); 
    } 
} 

如果你是在嚴格模式下,您的代碼將拋出一個錯誤,而不是誤導繼承:

TypeError: Cannot set property 'getname' of undefined 
+0

調用'foo.call'比'foo'慢,所以我試圖避免它在一個循環中;如果我想要這種行爲,我會提前_bind_函數,然後調用循環中的bound函數 –

+1

@PaulS .:只是提供一種替代解決方案。微代碼優化是在你的代碼實際工作之後出現的。 – Blender

相關問題