严格来讲,js没有私有成员的概念,所有的对象属性都是共有的。不过,倒是有私有变量的概念。在任何定义在函数或块中的变量,都可以认为是私有的,因为在这个函数或块的外部无法访问其中的变量。私有变量包括函数参数、局部变量,以及函数内部定义的其他函数
私有变量定义
- 如果函数中创建了一个闭包,则这个闭包能够通过其作用域链访问其外部的变量,利用这个原理可以创建特权方法(是能够访问函数私有变量的公共方法)。
function Person(name) {
//特权方法
this.getName = function () {
return name
}
this.setName = function (value) {
name = value
}
}
let person = new Person("七里长汀")
console.log(person.getName())//七里长汀
person.setName("七里长亭")
console.log(person.getName())//七里长亭
利用原型链或renturn功能也可以实现特权方法的编写,不再赘述。
使用weakMap保护私有变量
//使用WeakMap(版本3)
const testFn = (function () {
let data = new WeakMap()
class Test {
constructor(val) {
data.set(this, val)
}
getData() {
return data.get(this)
}
}
return Test;
})();
let test1 = new testFn(3);
let test2 = new testFn(4);
console.log(test1.getData());//3
console.log(test2.getData());//4
const User = (() => {
const wm = new WeakMap()
class User {
constructor(id) {
this.idProperty = Symbol('id')
this.setId(id)
}
stePrivate(property, value) {
const privateMebers = wm.get(this) || {}
privateMebers[property] = value
wm.set(this, privateMebers)
}
getPrivate() {
return wm.get(this[property])
}
setId(id) {
this.stePrivate(this.idProperty, id)
}
getId() {
return this.getPrivate(this.idProperty)
}
}
})
内存泄漏
在内存有限的设备上,或者在函数会被调用很多次的情况下,内存泄漏可能是一个大问题。
//1.意外生成全局变量,只要window本身不会被清除就不会消失
function setName() {
name = "Jack"
}
//2.只要定时器一直在执行,回调函数中引用的name就会一直占用内存,所以当定时器记得及时清除clearinterval()
let name = 'jake'
setInterval(() =>{
console.log(name)
},1000)
//3.闭包很容易在不知不觉中泄漏内存
let outer = function () {
let name = "Jack";
return function () {
return name
}
}
//调用outer函数会导致分配给name的内存泄漏。以上代码执行后创建了一个闭包,只要返回的函数存在就不能清理name,因为闭包一直引用着它。
防止内存泄漏的最佳方案
使用weakmap防止内存泄漏。weakMap也是生成键值对的组合,但是只接受对象作为键名(不包括null)。这些键不属于正式的引用,不会阻止垃圾回收