2012-03-04 51 views
8

裏面約翰Resig的書「臨的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 
}); 

alert(user.getname()); 

運行上面的代碼會引發此錯誤「user.getname不是函數」。

爲每個實例化對象生成動態函數的正確方法是什麼?

+7

我相信約翰Resig的使用正確的縮進。 – 2012-03-04 02:58:18

+1

這看起來不對。在匿名函數中,'this'是'window'。 – 2012-03-04 02:59:22

+0

答案是* not * indentation,但是它是indentation **。討論。 – 2012-03-04 03:02:28

回答

11

這是本書的代碼嗎?我有這本書,但我沒有讀過它。

這是書中的錯誤。檢查勘誤:http://www.apress.com/9781590597279

裏面的匿名函數,this是全球window

你可以把它通過後加入.call(this, i)工作。

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); 
    } 
} 
+2

*我有這本書,但我還沒有閱讀它。*那麼你有什麼**你一直在用它呢?圖書驛站?木質纖維的來源?牆紙? – 2012-03-04 03:06:32

+2

+1也用於修復捕獲的「i」問題。 – ruakh 2012-03-04 03:06:39

+0

@JaredFarrish:它被用來保持書架對稱。不,但嚴重的是,我只需要一些時間來真正閱讀它:-P – 2012-03-04 03:07:48

3

this中的內部自我執行功能與外部User功能中的此不相同。正如你注意到的,它指的是全球的window

如果稍有通過添加是指外this可變修改代碼的問題是固定的。

function User(properties) { 
    var self = this; 
    for (var i in properties) { 
    (function() { 
     self["get" + i] = function() { /* ... */ }; 
     self["set" + i] = function() { /* ... */ }; 
    })(); 
    } 
} 

這就是說,我不知道爲什麼連這裏需要匿名自動執行功能,讓你擁有的只是留了簡單的選擇完全,像這樣:

function User(properties) { 
    for (var i in properties) { 
     this["get" + i] = function() { /* ... */ }; 
     this["set" + i] = function() { /* ... */ }; 
    } 
} 
1

以下是如何操作。您需要將上下文保存到另一個變量中。另一種選擇是不要執行你在for循環中做的這個內部函數。

// 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) 
    var that = this; 
    for (var i in properties) { (function(){ 
     // 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; 
     }; 
    })(); } 
} 

選項2:

// 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) { 
     // 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; 
     }; 
    } 
} 
+0

這兩個選項都不起作用,因爲它們使用捕獲的版本的「i」,它會在循環執行時發生變化並將'i'作爲最後一個屬性名稱。約翰的例子就是如何避免這個問題。選項1可以很容易地被修復,但是,通過傳遞'i'作爲參數。要修復選項2,您可以將其轉化爲選項1的固定版本。 – chuckj 2012-03-04 03:36:33

1

你總是可以強制另一this任何函數調用,使用apply方法。

(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; 
    }; 
}).apply(this); 
相關問題