【问题标题】:Using IIFEs in JS for protecting data by creating private variables在 JS 中使用 IIFE 通过创建私有变量来保护数据
【发布时间】:2018-04-30 12:54:13
【问题描述】:

我创建了一个小程序,用于在单击 DOM 中的按钮时在控制台中打印一些消息。

代码-

<!DOCTYPE html>
<html>
<body>
    <button onClick="printName()">Click</button>
</body>
<script>
    const personDetails = (function() {
        let name = 'john';
        function displayMsg() {
            console.log(name);
        }
        return {
            displayName: displayMsg
        }
    })();
    function printName() {
        personDetails.displayName(); 
    }
</script>
</html>

在上面的代码中,为了保护 name,我使用 IIFE 并在 personDetails 中返回一个方法 displayName。单击按钮时,将执行 printName,进而执行 personDetails.displayName。这是我的担忧 -

  1. 这是使用 IIFE 保护数据的正确方法吗? 如果不是,请提供解决方案。这每天都在变得令人困惑。
  2. 即使我们只保留 1 个全局变量,其他暴露的 变量可以通过像 displayName 这样的全局变量来访问 方法。
  3. 假设我已成功保护数据,但我仍然能够 通过更改控制台中的函数定义 personDetails.displayName 应该避免。

    旧方法: 函数 displayMsg() { console.log(name); }
    新方法: personDetails.displayName = function() { console.log('Hiiii'); }

【问题讨论】:

    标签: javascript private private-members iife


    【解决方案1】:
    1. 是的
    2. 是的,但只有一个全局变量。这大大降低了其他代码意外覆盖它的风险。
    3. 是的。一旦代码离开您的控制并到达客户端,您就无法停止对代码的刻意修改。

    尽量减少全局变量的使用是一种减少其他代码引起错误可能性的策略。它不是 DRM 的一种形式。

    【讨论】:

      【解决方案2】:

      假设我已成功保护数据,但我仍然能够 通过更改控制台中的函数定义 应该避免的 personDetails.displayName。

      这可以通过更改返回对象的writable 属性的值来避免。

      修改personDetails的函数赋值如下:

      "use strict";
      const personDetails = (function() {
          let name = 'john';
          function displayMsg() {
              console.log(name);
          }
          var obj = {};
          Object.defineProperty(obj, 'displayName', {
              value: displayMsg,
              writable: false
          });
      
          return obj;
      })();
      

      现在,如果有人试图覆盖属性值,

      function printName() {
          personDetails.displayName = 10; 
      }
      printName();
      

      你会收到这样的错误:

      Uncaught TypeError: Cannot assign to read only property 'displayName' of object '#<Object>'
          at printName (<anonymous>:17:35)
      

      查看this writeup了解更多详情。

      注意:这只会在严格模式下抛出错误,否则会默默拒绝任何更改。

      【讨论】:

        【解决方案3】:

        欢迎来到 StackOverflow。请乘坐 tour 并访问 help center


        1。这是正确的方法吗?

        对于这个主要基于意见的问题,至少有一个“接近”投票。那位选民是正确的,这部分问题很难明确回答。

        所以我只想说,这至少是一种合适的方式。还有很多其他的。如果您愿意,您可以将其简化为

        const personDetails = (function() {
          let name = 'john';
          return {
            displayName: function() {
              console.log(name);
            }
          }
        })()
        

        您还可以使用箭头函数进一步简化它。

        2。为什么其他变量仍然暴露?

        这就是此类代码的重点:创建一个引用某些私有数据的公共接口。你也可以跳过personDetails,只公开displayName,方法是返回函数而不是具有该函数作为属性的对象。

        但如果您希望能够使用这些数据,那么您至少需要一些公共接口!

        3。这个函数引用怎么还能改?

        techniques 可以让您保护此变量不被更改。但是,也许,用户会将personDetails 重新定义为其他东西。你能保护这个吗?也许。但是,如何阻止某人在浏览器解释您的 Javascript 之前拦截它,从而更改这些定义?

        关键是你永远只有这么多的控​​制权。如果你不信任用户,你就不应该向他们发送代码......这意味着你不应该为网络写作。

        使用 IIFE 保护数据免遭意外更改,甚至是善意但危险的故意更改,都可以。然而,一旦代码离开你的手,试图假装你完全负责代码是愚蠢的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-01-12
          • 2015-08-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-05-23
          • 2011-01-16
          • 2017-01-20
          相关资源
          最近更新 更多