导致JS闭包变量暴露的原因是什么?

时间:2017-11-03 20:26:21

标签: javascript closures

我有一个闭包我用来设置和检索几个方法需要的对象的状态。

不幸的是我遇到了一些奇怪的行为。在某些情况下,我想修改闭包中返回的信息,同时仍然将闭包中的变量保持在预期的状态。换句话说,我不想使用闭包的set方法,我只想检索对象,进行简短的临时修改,并让闭包为其他任何可能需要信息的方法保持其先前的状态。

然而,这不起作用,我的临时更改导致闭包对象改变,尽管没有使用set方法。我完全承认我不理解范围等级问题。这是代码:

<script>

 var closureTest= {
     filterState: (function () {
         var filterObject = {
             'model': 'ford',
             'year': '2010'

         };

         return {

             setFilterObject: function (input) {
                     filterObject.model = input;
             },

             getFilterObject: function () {
                 return filterObject;
             }

         };
     })()

 };
    //lets retrieve the default values
    var resultsToModify = closureTest.filterState.getFilterObject();
    //now lets attempt to change the model for a one time use
    resultsToModify.model = 'chevy';
    //now lets grab the object again (assuming it will return ford and 
    //2010 because we didn't use the setFilterObject method to change the object 
    var defaultClosureAgain = closureTest.filterState.getFilterObject();
    //expected would show model type as chevy
    console.log('resultsToModify: ',resultsToModify);
    //but why does this show chevy too? 
    //The setFilterObject was never used to modify the object? what am I missing?
    console.log('defaultClosureAgain: ',defaultClosureAgain);

</script>

2 个答案:

答案 0 :(得分:0)

在函数外返回getter和setter方法将导致

暴露功能变量。在你的代码中......

  return {

         setFilterObject: function (input) {
                 filterObject.model = input;
         },

         getFilterObject: function () {
             return filterObject;
         }

     };

答案 1 :(得分:0)

以下是对代码的最小更改 - 返回container-id-json.log的副本。这将允许您在不影响原件的情况下对副本进行更改。原始版本应该只在filterObject API中公开,这是(我可以收集的)你打算改变该对象的唯一方法。

&#13;
&#13;
set
&#13;
&#13;
&#13;

注意var closureTest= { filterState: (function () { var filterObject = { 'model': 'ford', 'year': '2010' }; return { setFilterObject: function (input) { filterObject.model = input; }, getFilterObject: function () { return Object.assign({}, filterObject); // ---------------------^^^^^^^^^^^^^^^^ copy filterObject } }; })() }; //lets retrieve the default values var resultsToModify = closureTest.filterState.getFilterObject(); //now lets attempt to change the model for a one time use resultsToModify.model = 'chevy'; //now lets grab the object again (assuming it will return ford and //2010 because we didn't use the setFilterObject method to change the object var defaultClosureAgain = closureTest.filterState.getFilterObject(); //expected would show model type as chevy console.log('resultsToModify: ',resultsToModify); //but why does this show chevy too? //The setFilterObject was never used to modify the object? what am I missing? console.log('defaultClosureAgain: ',defaultClosureAgain);仅限ES6 +。您需要使用polyfill或者转发器来获得完整的浏览器支持。

我将补充一点,你在这里玩的范例并没有太多真实世界的应用,很可能有更好的方法来实现最终目标&#34;是,如果有的话。但是,如果你只是在玩耍,那么这总是一件好事!