// 保持所有私有数据的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函数,可以传入参数,就可以生成一个对象。