闭包中的局部变量从外部改变。这是javascript错误还是我做错了什么?

闭包中的局部变量从外部改变。这是javascript错误还是我做错了什么?,javascript,Javascript,我使用闭包保护隐私。 我不明白为什么以及如何从闭包外部更改局部变量 我写了一个脚本向你们解释这个问题 var MyAjax=(function(){ //Create a local variable for privacy var _opts={ cache:true } ,getDefaultOptions=function(){ return _opts }; //return only getDefaultOptions funct

我使用闭包保护隐私。 我不明白为什么以及如何从闭包外部更改局部变量

我写了一个脚本向你们解释这个问题

var MyAjax=(function(){
  //Create a local variable for privacy
  var _opts={ 
       cache:true
   }
  ,getDefaultOptions=function(){
      return _opts
  };

  //return only getDefaultOptions function
  return { 
     getDefaultOptions:getDefaultOptions
  }
})()


//I am merging new ajax options with default options.
var defaults=MyAjax.getDefaultOptions();
var reqOptions= $.extend(defaults,{cache:false});

// I am getting expected result
console.log("extended var",reqOptions) //{cache:false}

// I am getting non expected result
// I should get {cache:true} but I am getting { cache:false }
console.log("defaults",MyAjax.getDefaultOptions()) //{cache:false} 
发生这种情况的原因和方式?

函数
$.extend()
修改第一个参数。如果您不想这样做,请执行以下操作:

var reqOptions = $.extend({}, defaults, {cache: false});
详细说明:将对对象的引用作为第一个参数传递。即使它是闭包的私有变量,getter函数也返回了对它的引用,因此它是“可见”的。jQuery函数的编写方式总是直接更新作为第一个参数传递的对象。因此,为了确保不更改该对象,只需传入一个新创建的对象作为第一个参数。

函数
$.extend()
修改第一个参数。如果您不想这样做,请执行以下操作:

var reqOptions = $.extend({}, defaults, {cache: false});

详细说明:将对对象的引用作为第一个参数传递。即使它是闭包的私有变量,getter函数也返回了对它的引用,因此它是“可见”的。jQuery函数的编写方式总是直接更新作为第一个参数传递的对象。因此,为了确保不更改该对象,只需传入一个新创建的对象作为第一个参数。

$.extend使用false覆盖
defaults.cache
,extend就是这样做的。更改默认值变量正常。但我再次调用MyAjax.getDefaultOptions(),但将cache返回为false。“Javascript总是按值传递,但当变量引用对象(包括数组)时,“值”是对对象的引用。”$.extend将覆盖
defaults.cache
,extend就是这样做的。默认变量的更改是正常的。但我再次调用MyAjax.getDefaultOptions(),但将cache返回为false。”Javascript总是按值传递,但当变量引用对象(包括数组)时,“值”是对对象的引用。“closure只返回一个只包含getDefaultOptions函数的json对象。如何访问并更改它?。我如何看到closure包含的变量?您的“getDefaultOptions”函数返回对该“_opts”对象的引用。通过返回对对象的引用,它允许外部代码修改对象;对象引用就是这样工作的。外部代码不能通过调用函数以外的任何其他方式访问“_opts”,因为它是私有的,但一旦引用被公开,任何其他代码都可以像处理任何其他对象一样操作该对象。好的。如果默认变量引用_opts,为什么我不能使用
var1=true获得相同的结果;var2=var1;var2=假;console.log(var2)
?有什么不同?。它不一样吗
var1=true;和var1=getTrue()这与PHP中的use&character相同?区别在于“_opts”引用了一个对象。这些其他值是基元标量值。closure仅返回一个仅包含getDefaultOptions函数的json对象。如何访问并更改它?。如何查看包含的闭包变量?您的“getDefaultOptions”函数返回对该“_opts”对象的引用。通过返回对对象的引用,它允许外部代码修改对象;对象引用就是这样工作的。外部代码不能通过调用函数以外的任何其他方式访问“_opts”,因为它是私有的,但一旦引用被公开,任何其他代码都可以像处理任何其他对象一样操作该对象。好的。如果默认变量引用_opts,为什么我不能使用
var1=true获得相同的结果;var2=var1;var2=假;console.log(var2)
?有什么不同?。它不一样吗
var1=true;和var1=getTrue()这与PHP中的use&character相同?区别在于“_opts”引用了一个对象。这些其他值是基本标量值。