【问题标题】:Why isn't my object private when my variable is?当我的变量是时,为什么我的对象不是私有的?
【发布时间】:2016-04-28 10:54:05
【问题描述】:

我正在尝试将对象设为私有,但不知道该怎么做。如您所见,名称变量是私有的,我无法对其进行编辑,但是当涉及到我返回的对象时,我可以进行编辑。不过,我不希望这成为可能。 我对javascript中的面向对象和私有方法很陌生,所以有人可以告诉我这里什么是对什么错。 :) 我该如何解决这个问题? 谢谢!

var User = function() {

  var name = 'bob';
  this.getName = function() {
    return name;
  }

  var otherInfo = {
    age: 20,
    human: true,
  }
  this.getOther = function() {
    return otherInfo;
  }

}

var person = new User();

var name = person.getName();
name = 'jenny';
console.log(person.getName()); // bob

var other = person.getOther();
other.age = 'wtf?';
console.log(person.getOther()); // { age: 'wtf?', human: true }

【问题讨论】:

标签: javascript private-members


【解决方案1】:

原始值(例如字符串)按值传递。这意味着当您将字符串分配给变量时,您正在将字符串的实际值设置为变量。

对象通过引用传递。这意味着当您将一个 Object 分配给您的变量时,您只是对 Object 进行 reference,而不是它的实际值。如果您有一个 Object 并将其分配给 6 个不同的变量,则每个变量将具有对同一底层 Object 的 reference。

在您的示例中,您的 getOther 方法将 reference 返回到 otherInfo 对象。因此,当您将age 属性设置为“wtf”时,您将其设置在您的变量所引用的对象上。

【讨论】:

    【解决方案2】:

    您还声明了两次var name。

    当你 var person = new User(); var name 在 User 函数的范围内声明时。

    当您var name = person.getName(); 时,您正在声明一个在 User 函数范围之外具有相同名称的变量。

    因此,当您name = 'Jenny'; 时,解释器将此字符串与用户范围之外的name 变量相关联。

    一般来说,将这些具有通用名称(名称、标题、id、...)的变量用作全局变量是一个坏主意。我将使用this. 引用对象属性并定义setters 以及getters。您也可以忽略setters 并使用person. 引用用户属性,如下所示:

    function User() {
      this.name = 'bob';
      this.getName = function() {
        return this.name;
      }
    
      this.otherInfo = {
        age: 20,
        human: true,
      }
      this.getOther = function() {
        return this.otherInfo;
      }
    
    }
    
    var person = new User();
    
    console.log(person.getName()); // bob
    person.name = 'jenny';
    console.log(person.getName()); // jenny
    
    console.log(person.getOther(); // { age: 20, human: true }
    person.otherInfo.age = 'wtf?';
    console.log(person.getOther()); // { age: 'wtf?', human: true }
    

    【讨论】:

      【解决方案3】:

      在 Javascript 的对象范围内没有“私有”的东西。向外部隐藏事物的唯一方法是使用函数作用域,就像使用 name(函数 User 中的局部变量)所做的那样。

      要每次返回一个内容相同的对象,你可以在函数内部创建对象。比如这样:

      this.getOther = function() {
          var otherInfo = {
              age: 20,
              human: true,
          }
          return otherInfo;
      }
      

      或者只是:

      this.getOther = function() {
          return {
              age: 20,
              human: true,
          };
      }
      

      在这两种情况下,每次调用都会创建一个新对象。

      【讨论】:

        【解决方案4】:

        这是发生的,因为在 JS 对象中通过链接传递 - 没有从源对象处理。

        尝试复制对象:

        var User = function() {
        
          var name = 'bob';
          this.getName = function() {
            return name;
          }
        
          var otherInfo = {
            age: 20,
            human: true,
          }
          this.getOther = function() {
            return Object.assign({}, otherInfo);
          }
        
        }
        
        var person = new User();
        
        var name = person.getName();
        name = 'jenny';
        console.log(person.getName()); // bob
        
        var other = person.getOther();
        other.age = 'wtf?';
        console.log(person.getOther()); // { age: 20, human: true }
        

        【讨论】:

        • 这并没有真正复制对象。相反,它使用this.otherInfo 作为新对象的原型。
        • 谢谢,我已经修好了。
        猜你喜欢
        • 2021-06-15
        • 1970-01-01
        • 1970-01-01
        • 2019-04-21
        • 1970-01-01
        • 2021-07-11
        • 2020-06-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多