Javascript 在这种情况下,如何避免声明全局变量?

Javascript 在这种情况下,如何避免声明全局变量?,javascript,jquery,ajax,Javascript,Jquery,Ajax,如果我有一个带有ajax调用的函数,它从数据库中获取一些值,然后我需要将该值发送回php脚本等等,那么我应该如何声明这个变量 function call(id){ $.ajax({ . . . data: {id: id}, success: function(res){ window.id = res.id } }); } //first call the function with a value call(10); //the

如果我有一个带有ajax调用的函数,它从数据库中获取一些值,然后我需要将该值发送回php脚本等等,那么我应该如何声明这个变量

function call(id){
  $.ajax({
    . . .
    data: {id: id},
    success: function(res){
       window.id = res.id
     }
  });
}


//first call the function with a value
 call(10);

//then call it with the returned value every time the btn gets clicked

$('#btn').click(function(){
 call(window.id);
})

根据我的理解,像这样使用全局变量是不好的做法,因为全局范围已经很拥挤,脚本查找变量需要更长的时间。我是否可以定义这个值,让我在不全局的情况下将其发回

由于
id
在语义上与
#btn
绑定,您可以将返回的
id
值存储为
#btn
属性:

function call(id){
  $.ajax({
    . . .
    data: {id: id},
    success: function(res){
       $('#btn').prop('response_id', res.id);
     }
  });
}

//first call the function with a value
 call(10);

//then call it with the returned value every time the btn gets clicked

$('#btn').click(function(){
 call(this.prop('response_id'));
})

避免全局性的最简单方法是首先不要在全局范围内工作。这样做的方法是创建一个(立即调用的函数表达式),这是一个全局范围内的匿名函数,但由于它是匿名的,所以它不可能与另一个同名函数发生冲突。它会被立即调用,以便其中的代码可以执行(比如
init
类操作)。然后,在这个函数中,你做你通常会做的任何事情。在这里,您将创建IIFE范围(非全局范围)变量

// IIFE wrapper
(function(){

  let mainID = null; // IIFE scoped variable

  function call(id){
    $.ajax({
      . . .
      data: {id: id},
      success: function(res){
         mainID = res.id; // Set the IIFE scoped variable to the AJAX result
       }
    });
  }

  // Set up the event
  $('#btn').click(function(){
    all(res.id);  // <-- And, you can use it anywhere in the IIFE
  });

  call(10);        // first call the function with a value

})();  // <-- The extra set of parenthesis is what invokes the expression 

只需将
window.id
替换为
call.id
(即,将其存储为函数的属性):


虽然这可以工作,但按钮没有
response\u id
属性。因此,解决方案有点“黑客式”。如果你想这样做,正确的方法是将信息存储在一个数据库中,这个数据库就是为这种事情创建的。更好的是,不要将任何代码放在全局范围内,而使用IIFE。请参阅我的答案。这仍然是一个全局变量-仅在DOM上。@ScottMarcus,谢谢您的评论。但是任何
HTMLElement
首先是一个
对象,因此可以设置任何属性。使用
data-
属性几乎是相同的方法,但我不喜欢它的实现。关于IILife,你完全正确——这是一种更好的方法(如果适用)。@KoshVery这就是为什么我说你的建议可行,但向DOM对象添加自定义属性是一种反模式,原因是添加了
data-*
属性。我不知道你在实施上有什么问题。它们很容易使用,而且(如我所说),如果你要走这条路,它们是正确的使用方法。在
成功
回调中声明
单击
绑定至少在我看来是很好的方法,您确信,只有在上下文已打开时,用户才能单击OK@PatrickFerreira这不仅是个好办法,也是唯一的办法。在异步操作完成之前,您无法使用该操作的结果,并且您可以确定的唯一位置是在成功回调中。但是,如果我在成功回调中设置事件处理程序,是否意味着每次单击按钮时都会设置它,我不确定它是如何工作的,但是多次设置同一事件处理程序不是一个问题吗?@ScottMarcus,如果您想在回调中设置事件侦听器,则需要分离上一个事件侦听器。或者您将使用之前所有的
id
多次调用
call()
函数attached@Uiot如果使用标准的
onclick
属性而不是JQuery
。单击
,旧的处理程序将替换为新的处理程序。是的,您可以执行您提到的成功检查,但似乎您之前说过,您确实希望在每次单击时注册一个新的事件处理程序。在这种情况下,你不会这么做。可能是
function call(id){
  $.ajax({
    . . .
    data: {id: id},
    success: function(res){
       call.id = res.id
     }
  });
}


//first call the function with a value
call(10);

//then call it with the returned value every time the btn gets clicke
$('#btn').click(function(){
  call(call.id);
})