JavaScript中是如何定义私有变量的
前言
JavaScript并不像别的语言,能使用关键字来声明私有变量。
我了解的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的详细介绍。
这里主要是利用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
同样达成了构建私有变量的效果。顺便提一句,class中构建私有变量用的就是WeakMap。
结尾
这篇文章只是记录我知道的关于JavaScript构建私有变量的方法以及作用,如有错误和遗漏,欢迎指出,不胜感谢。
JavaScript中是如何定义私有变量的的更多相关文章
- ES6 class类中定义私有变量
		ES6 class类中定义私有变量 class类的不足 看起来, es6 中 class 的出现拉近了 JS 和传统 OOP 语言的距离.但是,它仅仅是一个语法糖罢了,不能实现传统 OOP 语言一样的 ... 
- (转载)php的类中可以不定义成员变量,直接在构造方法中使用并赋值吗?
		(转载)http://s.yanghao.org/program/viewdetail.php?i=184313 php的类中可以不定义成员变量,直接在构造方法中使用并赋值吗? class block ... 
- JavaScript中函数的定义
		JavaScript中函数的定义 制作人:全心全意 在JavaScript中,函数是由关键字function.函数名加一组参数以及置于大括号中需要执行的一段代码定义的.定义函数的基本语法格式如下: f ... 
- 第8.12节  Python类中使用__dict__定义实例变量和方法
		上节介绍了使用实例的__dict__查看实例的自定义属性,其实还可以直接使用__dict__定义实例变量和实例方法. 一. 使用__dict__定义实例变量 语法: 对象名. dict[属性名] = ... 
- 第8.28节 Python中使用__setattr__定义实例变量和实例方法
		一. 引言 根据前面章节介绍的内容,我们知道实例变量.实例方法的定义可以通过以下方法进行: 在类体中直接定义实例变量.实例方法: 在实例方法中定义实例变量.实例方法: 在类体外调用方使用赋值语句赋值定 ... 
- JavaScript中函数的定义!
		JavaScript中函数的定义! 1 自定义函数(命名函数) function fun() {}; 2 函数表达式(匿名函数) var fun = function () {}; 3 利用 new ... 
- JavaScript中的作用域以及this变量
		原文:Scope and this in JavaScript 今天我想简单讨论下关于JavaScript的作用域和this变量."作用域"的概念就是说.我们的代码能够从哪里去訪问 ... 
- JavaScript 中函数的定义和调用
		3种函数定义方式: 1.使用关键字 function 来声明并定义函数 function myFunction(a, b) { return a * b; } 调用函数: var x = myFunc ... 
- 解读JavaScript中的Hoisting机制(js变量声明提升机制)
		hoisting机制:javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面. 知识点一:javascript是没有 ... 
随机推荐
- 风炫安全web安全学习第三十三节课 文件包含漏洞基础以及利用伪协议进行攻击
			风炫安全web安全学习第三十三节课 文件包含漏洞基础以及利用伪协议进行攻击 文件包含漏洞 参考文章:https://chybeta.github.io/2017/10/08/php文件包含漏洞/ 分类 ... 
- 基于LDAP&&Role-based Authorization Strategy实现Jenkins团队权限管理
			在实际工作中,存在多个团队都需要Jenkins来实现持续交付,但是又希望不同团队之间进行隔离,每个项目有自己的view, 只能看到自己项目的jenkins job. 但是,jenkins默认的权限管理 ... 
- 路由器开启远程控制(ssh或telent)
			• 远程控制 ○ 开启远程控制 § conf t § line vty 0 4 □ 0 4 意思是最多允许5个 ... 
- 【Spring】Spring IOC
			Spring IOC IOC 的常用注解 小节源码 之前的 XML 配置: <bean id="accountService" class="cn.parzulpa ... 
- 【Web】实现动态文章列表
			简单记录 -慕课网- 步骤二:动态文章列表效果 实现这个 一个网页中常见的文章列表效果. 怎么实现文章列表案例 分解一波,CSS来改变样式 标题标签 HTML的无序列表 去掉项目符号 符号所占空间 列 ... 
- 【ORA】ORA-00371: not enough shared pool memory
			今天rac中有一个节点asm实例起不来包了ora-000371的错误,错误贴在下面: [oracle@rac2 dbs]$ srvctl start asm -n rac2 PRKS-1009 : F ... 
- 【RAC】11gRAC 搭建(VMware+裸设备)
			安装环境与网络规划 安装环境 主机操作系统:windows 7虚拟机VMware12:两台Oracle Linux R6 U5 x86_64 Oracle Database software: Ora ... 
- [usaco2008 Oct]Pasture Walking 牧场旅行
			题目描述 n个被自然地编号为1..n奶牛(1<=n<=1000)正在同样被方便的编号为1..n的n个牧场中吃草.更加自然而方便的是,第i个奶牛就在第i个牧场中吃草. 其中的一些对牧场被总共 ... 
- 2V转5V输出,2.4V转5V输出,DC-DC同步整流升压电路
			PW5100可以适用于2V转5V和2.4V转5V的应用电路中,PW5100是一颗DC-DC的同步升压转换器芯片. PW5100特点: 1, 低输入,宽范围:0.7V-5V 2, 输出电压固定,外围少: ... 
- FreeWheel核心业务团队混沌工程实践之路
			https://mp.weixin.qq.com/s/0monDPkAlMk7Yhq9swW7gQ 原创 郭彦梅 InfoQ 2020-11-17 
