JavaScript 声明私有变量的两种方式

作者:纸飞机时间:2026-10-24 07:45:39浏览:625

JavaScript 原生缺乏私有变量关键字,本文介绍两种实现方式:利用闭包封装内部状态,以及利用 WeakMap 的 key 不可枚举特性。通过具体代码示例,展示了如何在对象操作中限制外部访问,从而强化类型控制并保护数据完整性。

前言

JavaScript 语言机制不同于其他编程语言,它没有直接的关键字用于声明私有变量。目前了解到的实现私有变量的主要手段包括利用闭包机制以及使用 WeakMap 对象。

闭包

关于闭包的定义有多种表述,例如:能够访问其他函数作用域的函数;或者是连接内部函数与外部函数作用域的桥梁等。

利用闭包构建私有变量的核心逻辑如下: 1. 在外部函数中定义变量及内部函数; 2. 通过内部函数读取或修改这些变量; 3. 在外部函数中返回内部函数,从而暴露访问接口。


function outside(){
	let val = 123;
	function inside(){
		return val;
	}
	return inside;
}
console.log(outside()());//123

上述示例展示了闭包构建私有变量的基本逻辑,但这并不能完全体现私有变量的核心价值,因为一个 const 常量也能实现类似的数据访问效果。


//同样的能访问,但是不能修改,达到了上述代码的效果
const val = 123;
console.log(val);//123

接下来的代码将具体展示私有变量在数据保护方面的重要性。


function person(){ 
 let _name = 'unknown';
 let _age = 18;
 let _sex = 'man';

 function setName(name){
  _name = name || 'unknown';
 }

 function getName(){
  return _name;
 }

 function setAge(age){
  if(typeof age === 'number'){
   _age = Math.floor(age);
  }else{
   throw Error("typeof age !== 'number'");
  }
 }

 function getAge(){
  return _age;
 }

 function setSex(sex){
  if(sex === 'man' || sex === 1){
   _sex = 'man';
  }else if(sex === 'woman' || sex === 0){
   _sex = 'woman';
  }else{
   throw Error('input error');
  }
 }

 function getSex(){
  return _sex;
 }

 return {
  setName : setName,
  getName : getName,
  setAge : setAge,
  getAge : getAge,
  setSex : setSex,
  getSex : getSex
 }
}

let xiaoming = person();
let xiaohong = person();
xiaoming.setName('xiaoming');
xiaohong.setName('xiaohong');
console.log('xiaoming name : ' + xiaoming.getName());//xiaoming name : xiaoming
console.log('xiaohong name : ' + xiaohong.getName());//xiaohong name : xiaohong

xiaoming.setAge(19.3333);
xiaohong.setAge('16');//Uncaught Error: typeof age !== 'number'
console.log('xiaoming age : ' + xiaoming.getAge());//xiaoming age : 19
console.log('xiaohong age : ' + xiaohong.getAge());//xiaohong age : 18


xiaoming.setSex(1);
xiaohong.setSex('woman');
console.log('xiaoming sex : ' + xiaoming.getSex());//xiaoming sex : man
console.log('xiaohong sex : ' + xiaohong.getSex());//xiaohong sex : woman

从上述代码可以看出,若要设置或获取 _name、_age、_sex 这三个变量的值,必须通过特定的 setName、getName、setAge、getAge、setSex、getSex 等方法进行。所有 setter 方法均对传入参数进行了类型或范围校验。这意味着对象的所有操作均处于受控状态,这在一定程度上缓解了 JavaScript 作为弱类型语言可能带来的负面影响。

WeakMap

若对 WeakMap 不熟悉,建议先查阅其详细介绍。此处主要利用 WeakMap 的 key 不可枚举这一特性来实现私有变量。


let nameWeakMap = new WeakMap();
let ageWeakMap = new WeakMap();
let sexWeakMap = new WeakMap();

function person(){
 let _hash = Object.create(null);
 nameWeakMap.set(_hash,'unknown');
 ageWeakMap.set(_hash,18);
 sexWeakMap.set(_hash,'man');
 function setName(name){
  nameWeakMap.set(_hash,name || 'unknown');
 }

 function getName(){
  return nameWeakMap.get(_hash);
 }

 function setAge(age){
  if(typeof age === 'number'){
   ageWeakMap.set(_hash,Math.floor(age));
  }else{
   throw Error("typeof age !== 'number'");
  }
 }

 function getAge(){
  return ageWeakMap.get(_hash);
 }

 function setSex(sex){
  if(sex === 'man' || sex === 1){
   sexWeakMap.set(_hash,'man');
  }else if(sex === 'woman' || sex === 0){
   sexWeakMap.set(_hash,'woman');
  }else{
   throw Error('input error');
  }
 }

 function getSex(){
  return sexWeakMap.get(_hash);
 }

 return {
  setName : setName,
  getName : getName,
  setAge : setAge,
  getAge : getAge,
  setSex : setSex,
  getSex : getSex
 }
}

let xiaoming = person();
let xiaohong = person();
xiaoming.setName('xiaoming');
xiaohong.setName('xiaohong');
console.log('xiaoming name : ' + xiaoming.getName());//xiaoming name : xiaoming
console.log('xiaohong name : ' + xiaohong.getName());//xiaohong name : xiaohong

xiaoming.setAge(19.3333);
xiaohong.setAge('16');//Uncaught Error: typeof age !== 'number'
console.log('xiaoming age : ' + xiaoming.getAge());//xiaoming age : 19
console.log('xiaohong age : ' + xiaohong.getAge());//xiaohong age : 18


xiaoming.setSex(1);
xiaohong.setSex('woman');
console.log('xiaoming sex : ' + xiaoming.getSex());//xiaoming sex : man
console.log('xiaohong sex : ' + xiaohong.getSex());//xiaohong sex : woman

这种方法同样实现了构建私有变量的效果。值得一提的是,ES6 class 中构建私有变量时使用的正是 WeakMap 机制。

结尾

本文仅记录我所了解的 JavaScript 构建私有变量的方法及作用。如有错误或遗漏,欢迎指正,不胜感激。

以上就是 JavaScript 声明私有变量的两种方式的详细内容,更多关于 JavaScript 声明私有变量的资料请关注本站其它相关文章!

作者最新文章