2013-08-12 4 views
0

Я хочу написать функции getter и setter для объекта, основанного на Json-файлах. Я скопировал приведенный ниже код книги Джона Ресига (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 в него. Вам также понадобится другая ссылка на внутри функции , так как контекст изменяется в ней до 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', поэтому я постараюсь избежать его в цикле; если бы я захотел этого поведения, я бы опередил функцию раньше, а затем вызовет связанную функцию в цикле –

+1

@PaulS .: просто предоставляя альтернативное решение. Микро-оптимизации возникают после того, как ваш код действительно работает. – Blender

Смежные вопросы