是否有类似Object.defineProperty的方法来定义变量

Is there an analogue to Object.defineProperty to define variables?

本文关键字:方法 定义 变量 defineProperty Object 是否      更新时间:2023-09-26

很容易通过导出模块的公共方法访问私有变量:

var makeAModule = function() {
    var _secret = 'Ssh!';
    var module = {
        tellMeYourSecret: function() {
            console.log(_secret);
        }
    };
    return module;
}
//  > var m = makeAModule();
//  > m.tellMeYourSecret();
//  Ssh!

有时我需要使用Object.defineProperty定义属性,这些属性是由getter使用其他私有变量的值计算的。不过,这些东西必须放在一个物体上,所以我最终制作了一个私人物体来装它们。如果我不把我所有的私人成员都存储在那个物体上,就会很难记住上面有哪些道具,没有,所以我把所有东西都放在那里:

var makeAModule = function() {
    var priv = {};
    priv._secret = 'Ssh!';
    Object.defineProperty(priv, 'secretLength', {
        get: function() { 
            return priv._secret.length; 
        }
    });
    var module = {
        tellMeYourSecret: function() {
            console.log(priv._secret);
        },
        howLongIsYourSecret: function() {
            console.log(priv._secretLength);
        }
    }
    return module;
}
//  > var m = makeAModule();
//  > m.howLongIsYourSecret();
//  4 

有没有办法定义一个变量(不附加到对象),它的值是通过getter计算的?类似这样的东西:

var makeAModule = function() {
    var _secret = 'Ssh!';
    Object.defineVariable('_secretLength', {
        get: function() {
            return _secret.length;
        }
    })
    var module = {
        tellMeYourSecret: function() {
            console.log(_secret);
        },
        howLongIsYourSecret: function() {
            console.log(_secretLength);
        }
    }
    return module;
}

不直接。

但是,您可以将其设置为window的属性,从而使其成为全局变量。但是使用全局变量是不推荐的,特别是如果它们是秘密的。

var makeAModule = function() {
  var priv = {};
  priv._secret = 'Ssh!';
  Object.defineProperty(window, '_secretLength', {
    get: function() { 
      return priv._secret.length; 
    }
  });
  return {
    tellMeYourSecret: function() {
      return _secret;
    },
    howLongIsYourSecret: function() {
      return _secretLength;
    }
  };
};
document.body.innerHTML =
  "Secret length: " + makeAModule().howLongIsYourSecret();

或者,您可以将getter定义为对象的属性,并使用with语句。请注意,with语句不能在严格模式下使用。

var makeAModule = function() {
  var priv = {};
  priv._secret = 'Ssh!';
  Object.defineProperty(priv, '_secretLength', {
    get: function() { 
      return priv._secret.length; 
    }
  });
  with(priv) {
    return {
      tellMeYourSecret: function() {
        return _secret;
      },
      howLongIsYourSecret: function() {
        return _secretLength;
      }
    };
  }
};
document.body.innerHTML =
  "Secret length: " + makeAModule().howLongIsYourSecret();