javascript中私有属性的实现。

// 保持所有私有数据的map
var map = new WeakMap();
// 默认的数据存取函数
var defaultFn = {
        has: function(key) {
            return !!this[key];
        },
        get: function(key) {
            return this[key];
        },
        getAll: function() {
            var keys = Object.keys(this);
            var ret = {};
            for (var i = 0; i < keys.length; i++) {
                ret[keys[i]] = this[keys[i]];
            }
            return ret;
        },
        set: function(key, val) {
            this[key] = val;
            return this;
        },
        delete: function() {
            map.delete(this);
            return this;
        }
    }
/*
    封装函数,主要实现this的传递,因为用户执行get/set等函数时,
    this的值是Factory类型的对象,这时候我们需要根据当前this去map中取到真正的this,
    然后传递到最后执行的函数中。用户在函数中只需要直接访问this即可。
    @param {Object} {get: function() {}}
*/
function wrap(protoFns) {
    var ret = {};
    for (key in protoFns) {
        if (protoFns.hasOwnProperty(key)) {
            ret[key] = (function(fn) {
                return function() {return fn.call(map[this],...arguments)};
            })(protoFns[key]);
        }
    }
    return ret;
}
function getFactory(fn, protoFns) {
    function Factory() {}
    // 对象生成器
    Factory.create = function() {
        if (this !== Factory) {
            return Factory.create(...arguments);
        }
        var target = new Factory();
        // 禁止操作Factory类型的对象
        Object.freeze(target);
        map[target] = new fn(...arguments);
        return target;
    }
    // 挂载函数到原型
    Object.assign(Factory.prototype, wrap(Object.assign(defaultFn, protoFns)));
    return  Factory;
};
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined' ) {
    module.exports = getFactory;
}

测试



// ------------- test ---------------//

function fn(x,y){
    this.x = x;
    this.y = y
}

var methods1 = {
    log:function(){
        console.log(this)
    }
}

var methods2 = {
    get:function(key){
        return this[key];
    }
}

// 每次getFactory的调用,都会生成一个独立的对象生成器
var factory1 = getFactory(fn, methods1)
var factory2 = getFactory(fn, methods2)
var fa = factory1.create(2,3);
var fa2 = factory2.create(1,2)

// 获取所有属性的值
var factory = getFactory(fn, methods1)
var obj = factory.create(1,2)
obj.getAll()

// 获取某个值,设置某个值
var factory = getFactory(fn,methods2)
var obj = factory.create(1,2)
//obj.set('x',111111)
console.log(obj.get('x'))

用法
首先调用getFactory函数,传入一个构造函数和一个对象,该对象定义了生成的对象都可以使用哪些方法。调用成功后得到一个函数,可以通过调用他的create函数,可以传入参数,就可以生成一个对象。

你可能感兴趣的:(javascript)