2016-02-12 7 views
0

Я пытаюсь избежать использования глобальной переменной при использовании функций внутри объектов. Я хочу вызвать функцию внутри другой функции и использовать переменную из области первой функции. Например:javascript scope и глобальные переменные

var showForecast = { 
    'init': function() { 
    this.getData(); 
    }, 
    'buildView': function(){ 
    var code = "Hey, you're from " + this.data.city; 
    $('body').append(code); 
    }, 
    'getData': function() { 
    $.getJSON('http://ipinfo.io/', function (data) { 
     console.log(data); 
     showForecast.buildView(); 
    }) 
    } 
} 

Очевидно, что это не работает. Я хочу использовать data внутри buildView, не делая data глобальной переменной. Я думал, что использование this будет правильным действием, потому что я звоню buildView из функции, где задан data. Как это можно достичь? Благодарю.

+0

@Oriol - 'buildView' вызывается из обратного вызова, так быть асинхронными не имеет значения. – Quentin

+0

ОК, я неправильно понял код. – Oriol

ответ

1

Невозможно получить доступ к самой переменной данных. Это локально привязано к анонимной функции, которую вы передаете в getJSONgetJSON передает ее как аргумент, который не поддается контролю).

Вам нужно скопировать значение где-нибудь.

В вашем конкретном примере нет областей, разделенных между getData и buildView, кроме глобальной области. Поэтому, если вы хотите передать значение через области, то глобальный - ваш собственный (ужасный) вариант.

Вы можете просто передать его в качестве аргумента:

showForecast.buildView(data); 

Или вы можете сохранить его как свойство:

showForecast.myData = data; 
2

Вы можете передать информацию вместе:

var showForecast = { 
'init': function() { 
    this.getData(); 
}, 
'buildView': function(data){ 
    var code = 'Hey, you\'re from ' + data.city; 
    $('body').append(code); 
}, 
'getData': function() { 
    $.getJSON('http://ipinfo.io/', function (data) { 
     console.log(data); 
     showForecast.buildView(data); 
    }) 
} 

} 
+0

Nice catch @Paulpro –

1

Мне нравится ответ Винни.

Один раунд-бой способ сделать модуль из него:

var showForecast = function(){ 
    var data; 
    var init = function() { 
     this.getData(); 
    }; 
    var buildView = function(){ 
     var code = 'Hey, you\'re from ' + this.data.city; 
     $('body').append(code); 
    }; 
    var getData = function() { 
     $.getJSON('http://ipinfo.io/', function (data) { 
      console.log(data); 
      this.data = data; 
      showForecast.buildView(); 
     }) 
    }; 
    return { 
     'init': init, 
     'buildView': buildView, 
     'getData': getData 
    }; 
}(); 

Таким образом, объем var data ограничивается функцией. Это похоже на частную переменную.

0

Как вы пытаетесь избежать глобального, вам следует рассмотреть использование пространств имен. В Javascript нет такой вещи, которая называется namespace. Но вы можете определить себя с помощью метода небольшой утилиты, упомянутого здесь.

http://www.zachleat.com/web/namespacing-outside-of-the-yahoo-namespace/

Служебный метод, который помогает создавать пользовательские пространства имен.

jQuery.namespace = function() { 
    var a=arguments, o=null, i, j, d; 
    for (i=0; i<a.length; i=i+1) { 
     d=a[i].split("."); 
     o=window; 
     for (j=0; j<d.length; j=j+1) { 
      o[d[j]]=o[d[j]] || {}; 
      o=o[d[j]]; 
     } 
    } 
    return o; 
}; 

Определение пространства имен

jQuery.namespace('jQuery.showForecast');  

Определение методов с использованием раскрывающий шаблона модуля

https://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript

jQuery.showForecast = (function() { 

    var data; 

    var init = function() { 
    getData(); 
    } 

    var buildView = function() { 
    var code = "Hey, you're from " + data.city; 
    $('body').append(code); 
    } 

    var getData = function() {   
    $.getJSON('http://ipinfo.io/', function(_data) { 
     console.log(data); 
     data = _data; 
     buildView(); 
    }) 

    } 

    return { 
    init: init 
    }; 

})(); // Execute it immediately 

Использование:

Вы можете ускори ss only init, поскольку он подвергается воздействию снаружи.

jQuery.showForecast.init() 

Определить другое пространство имен

jQuery.namespace('jQuery.showForecast.extended'); 

jQuery.showForecast.extended = { 
// Define some more 

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