2017-08-12 57 views
1

我可能是錯的內部功能(不是箭頭)是不明確的,但我的理解是,這「這」在對象

var foo = {                                       
    'bar': x => x + 1,                                     
    'baz': function(y){ return this.bar(y); }                               
};                                          

foo.baz(1); 

應該可以正常工作,因爲我照顧不來定義foo.baz如箭功能等this內部baz等於foo。當然,當我在控制檯上測試它時,它會按我的預期工作。

現在,我有一個非常類似的設置與React,其中this由於某種原因未定義。這是代碼:

const MapRoom = {                                      
    'getStyleFromCoords': coords => {                                 
     return { // account for borders                                
      'left': coords[0] + 1,                                
      'top': coords[1] + 1,                                
      'width': (coords[2] - coords[0]) - 2,                           
      'height':(props.coords[3] - props.coords[1]) - 2,                           
     };                                        
    },                                         
    'Disabled': function(props){                                  
     console.log('this', this); // undefined                                  
     const style = this.getStyleFromCoords(props.coords); // error                           

     return (                                      
      <div                                      
       className="room-selected"                                
       style={style}                                   
       title={props.number}                                  
       ></div>                                     
     );                                        
    } 
} 

然後

renderRooms(){                                       
    // stuff                        

    return this.state.coords.map((coords, index) => {                             
     // more stuff 
     if(disabled){                                         
      return (                                          
       <MapRoom.Disabled                                       
        key={roomNumber}                                  
        number={roomNumber}                                      
        coords={coords}                                  
        />                                     
      );                                       
     } else if(...){} 
    }); 
} 

render(){ 
    return (
     <stuff> 
      {this.renderRooms()} 
     </stuff> 
    ); 
}                                                                    

我說,他們應該是analagous,但似乎並非如此。當然這不是什麼大問題,因爲我可以將該函數移動到對象之外,因此不需要this來引用它,但是我很想知道實際發生了什麼,因爲我無法重現錯誤。

如果它的事項,我transpiling與巴貝爾代碼和輸出

var MapRoom = {                                      
    'getStyleFromCoords': function getStyleFromCoords(coords) {                          
     return { // account for borders                                
      'left': coords[0] + 1,                                
      'top': coords[1] + 1,                                
      'width': coords[2] - coords[0] - 2,                           
      'height': coords[3] - coords[1] - 2                           
     };                                        
    },                                         
    'Disabled': function Disabled(props) {                                
     console.log('this', this);                                  
     var style = this.getStyleFromCoords(props.coords);                             

     return __WEBPACK_IMPORTED_MODULE_0_react___default.a.createElement('div', {                     
      className: 'room-selected',                                
      style: style,                                    
      title: props.number                                  
     });                                       
    } 
} 

這是的WebPack編譯器創建一個匿名函數裏面。

+2

你告訴我們你是如何調用'foo.baz',但是不知道是哪位'MapRoom .Disabled'。當使用一個普通的'function'時,函數是如何調用'this'的_called_,而不是它被定義的地方,所以沒有辦法回答這個問題。 – loganfsmyth

+0

@loganfsmyth你是完全正確的,我的壞。讓我知道現在是否夠了。 – cronos2

+0

編譯結果不再使用'this'。 – melpomene

回答

1

正常function中的this值是根據函數的調用方式設置的。對象聲明的結構沒有任何影響,只是foo.baz(1);設置了thisfoo

要打破它,

foo.baz(1); 

相當於

let _tmp = foo; 
_tmp.baz.call(_tmp, 1); 

其中在這種情況下,_tmp可能是非常到位只是用foo的跳過。

在您的JSX情況下

<MapRoom.Disabled /> 

declareComponent(MapRoom.Disabled); 

如該函數只是得到的功能,例如

function declareComponent(someFunc){ 
    someFunc(); 
} 

該函數被調用的時候,它只是一個功能,沒有obj.someFunc會導致thisobj,所以它最終被undefined

爲了闡明,事實上你的函數被聲明爲一個對象的屬性對任何東西都沒有影響,它仍然只是一個函數,它是由你來確保函數被調用正確的this值如果你有一定的期望。例如,你可以做

const MapRoomDisabled = MapRoom.Disabled.bind(MapRoom); 

<MapRoomDisabled /> 

而且由於功能已經綁定了一個明確的情況下,它會像您期望的工作。

var obj = { 
    prop: function(){} 
}; 

是沒有什麼不同

var obj = { 
    prop: null 
}; 
obj.prop = function(){}; 

var someFunc = function someFunc(){} 

var obj = { 
    prop: someFunc, 
};