JS创建对象的私有变量的方法(并不是真正的私有,只是不能通过 . 获取该属性或方法)

119 阅读2分钟

1.在构造函数中定义私有属性或私有函数(闭包)

function Person(name,uid){
    var id=uid;
    this.name=name;
    this.getId=function(){
        return id;
    }
}
var p1=new Person("zhangsan",1);
console.log(p1.name);		//zhangsan
console.log(p1.id);			//undefined
console.log(p1.getId());	//1

变量id只能通过特权方法getId来获取,而无法通过p1.id获取。
**优点:**每个对象的的私有属性都是独立的,不会共享(和下面的方法比)
**缺点:**每个对象上的私有方法都是独立的,不会共享,从而无法实现复用,其次无法定义所有对象共享的私有属性

2.在一个自执行的函数内定义私有属性和私有方法(闭包)

(function(){
    var numberOfEyes=2;
    Person=function(name){
        this.name=name;
    };
    Person.prototype.getNumberOfEyes=function(){
        return numberOfEyes;
    }
})();
var p1=new Person("zhangsan");
console.log(p1.name);			//zzhangsan
console.log(p1.numberOfEyes);	//undefined
console.log(p1.getNumberOfEyes());	//2

在自执行的函数内部没有使用函数声明的方式(使用function functionName(){})的形式声明构造函数,而是使用函数表达式(functionName=function(){})的形式声明构造函数,因为变量前面不加var会被认为是绑定到window上的,所以在自执行函数的外部也能访问该构造函数。需要注意的是如果使用"use strict"则无法使用该方法。
**优点:**对象上的私有方法是共有的,从而避免了方法的重复声明,其次可以定义所有对象共享的私有属性
**缺点:**没法定义每个对象独有的私有属性

3.使用Symbol创建私有变量(Symol+闭包)

var Person=function(name,id){
    var _id=Symbol("id");
    return new function (){
        this.name=name;
        this._id=id;
        this.getId=function(){
            return this._id;
        };
    };
};
var p1=new Person("zhangsan",2);
console.log(p1.name);		//zhangsan
console.log(p1.id);			//undefined
console.log(p1.getId());	//2

每个Symbol实例都是唯一的,且由于在函数内部声明的所以只能在函数内部使用,无论p1.id还是p1._id都无法获取id的值。
**优点:**每个对象的的私有属性都是独立的,不会共享
**缺点:**无法使用instanceof来判断对象是否是Person的实例

4.使用proxy

5.使用WeakMap实现真正的私有变量

var Person=function(name,id){
    var _id=Symbol("id");
    var item=new WeakMap();
    return new function (){
        this.name=name;
        item.set(this,id);
        this.getId=function(){
            return item.get(this);
        };
    };
};
var p1=new Person("zhangsan",2);
console.log(p1.name);		//zhangsan
console.log(p1.id);			//undefined
console.log(p1.getId());	//2

**优点:**每个对象的的私有属性都是独立的,不会共享,真正的私有变量
**缺点:**无法使用instanceof来判断对象是否是Person的实例,可读性不强,无法继承私有属性