简体   繁体   English

JavaScript范围和全局变量

[英]javascript scope and global variables

I'm trying to avoid using global variable when using functions within objects. 我试图避免在对象中使用函数时使用全局变量。 I want to invoke a function inside other function and use a variable from the first function's scope. 我想在其他函数中调用一个函数,并使用第一个函数作用域中的变量。 For example: 例如:

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();
    })
  }
}

Clearly it's not working. 显然,它不起作用。 I want to use data inside buildView without making data a global variable. 我想在buildView使用data而不将data buildView全局变量。 I thought using this would be the right course of action because I'm calling buildView from a function where data is defined. 我认为使用this方法是正确的做法,因为我是从定义data的函数中调用buildView How can this be achieved? 如何做到这一点? Thanks. 谢谢。

You can pass the information along: 您可以沿以下方向传递信息:

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

}

There is no way to access the data variable itself. 无法访问数据变量本身。 That is locally scoped to the anonymous function you pass to getJSON (and getJSON passes it as an argument, which is beyond your control). 这在本地范围内是您传递给getJSON的匿名函数(并且getJSON将其作为参数传递,这超出了您的控制范围)。

You have to copy the value somewhere. 您必须将值复制到某个地方。

In your particular example, there are no scopes shared between getData and buildView other than the global scope. 在您的特定示例中,除了全局作用域之外,没有在getDatabuildView之间共享任何作用域。 So if you want to pass the value through scopes, then a global is your own (terrible) option. 因此,如果要通过范围传递值,则全局变量是您自己的(糟糕)选项。

You can simply pass it as an argument: 您可以简单地将其作为参数传递:

showForecast.buildView(data);

Or you can store it as a property: 或者,您可以将其存储为属性:

showForecast.myData = data;

I like Vinny's answer. 我喜欢温尼的回答。

One round-bout way is to make a module out of it: 一种全面的方法是用它制作一个模块:

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
    };
}();

This way the scope of var data is limited to the function. 这样, var data的范围就限于该函数。 It's like a private variable. 这就像一个私有变量。

As you are trying to avoid global, you should consider using namespaces. 当您尝试避免全局时,应考虑使用名称空间。 There is no such thing called namespace in Javascript. Javascript中没有所谓的名称空间。 But you can define yourself using small utility method mentioned here. 但是您可以使用此处提到的小型实用程序方法来定义自己。

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

A utility method which helps creating custom namespaces. 一种实用程序方法,可帮助创建自定义名称空间。

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;
};

Define name space 定义名称空间

jQuery.namespace( 'jQuery.showForecast' );    

Define methods using revealing module pattern 使用显示模块模式定义方法

https://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript 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

Usage: 用法:

You can access only init method as it is exposed to outside. 您只能访问init方法,因为它暴露在外部。

jQuery.showForecast.init()

Define another namespace 定义另一个名称空间

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

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

};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM