Javascript 将对象封装为当调用类似“set”的方法时,它';s执行,并返回对象本身(与JQuery非常相似)
我试图抽象JQuery的常见行为,这使我能够更轻松地编写代码:将对象封装到调用类似Javascript 将对象封装为当调用类似“set”的方法时,它';s执行,并返回对象本身(与JQuery非常相似),javascript,closures,Javascript,Closures,我试图抽象JQuery的常见行为,这使我能够更轻松地编写代码:将对象封装到调用类似set的方法、执行该方法并返回对象本身时(非常像JQuery) 看: 测试用例是: // works let date = new Date(); console.log(date.setDate(10)); // logs 1494447383428 console.log(date.getDate()); // logs 10 console.log(Date.prototype.setDate.apply(d
set
的方法、执行该方法并返回对象本身时(非常像JQuery)
看:
测试用例是:
// works
let date = new Date();
console.log(date.setDate(10)); // logs 1494447383428
console.log(date.getDate()); // logs 10
console.log(Date.prototype.setDate.apply(date, [20])); // logs 1494447383428
console.log(date.getDate()); // logs 20
// does not work
let ED = encapsulate(Date);
let date1 = new ED();
console.log(date1.setDate(10)); // should log date1 object but throws an error
在不兼容的接收器[对象对象]上调用的方法Date.prototype.setDate会引发错误
你能帮我吗?D:(更新)来自Bergi的新建议:
let encapsulate = function (guy) {
return function () {
this.inner = new (Function.prototype.bind.apply(guy, arguments))
let prototype =
Object.getOwnPropertyNames(guy.prototype)
.reduce((proto, propName) => {
let method = propName.match(/^set/g) ?
(function () {
guy.prototype[propName].apply(this.inner, [].slice.apply(arguments))
return this
}).bind(this) :
(function () {
return guy.prototype[propName].apply(this.inner, [].slice.apply(arguments))
}).bind(this)
return Object.defineProperty(proto, propName, {
value: method,
enumerable: false,
writable: false,
configurable: false
})
}, {})
Object.defineProperty(prototype, 'applyFunction', {
value: fn => { fn(this); return this },
enumerable: false,
writable: false,
configurable: false
})
Object.setPrototypeOf(this, prototype)
}
}
(已弃用)按照Bergi所说的,我已经使用合成完成了这项工作:
let encapsulate = function (guy) {
return function () {
let argumentsWrapper =
[].slice.apply(arguments)
.reduce((aw, argument, idx) => {
aw['a' + idx] = argument;
return aw;
}, {})
this.inner = eval('new guy(' +
Object.keys(argumentsWrapper)
.reduce((string, argumentName, idx, arr) =>
string + 'argumentsWrapper.'
+ argumentName
+ (idx != arr.length - 1 ? ',' : ''),
'')
+ ')')
let setProperties = Object.getOwnPropertyNames(guy.prototype)
.filter(propName => propName.match(/^set/g))
setProperties.forEach(function (propName) {
this[propName] = (function () {
guy.prototype[propName].apply(this.inner, [].slice.apply(arguments))
return this
}).bind(this)
}, this)
Object.getOwnPropertyNames(guy.prototype)
.filter(propName => !propName.match(/^set/g))
.forEach(function (propName) {
this[propName] = (function () {
return guy.prototype[propName].apply(this.inner, [].slice.apply(arguments))
}).bind(this)
}, this)
this.applyFunction = fn => {
fn(this)
return this
}
}
}
它不漂亮://它的意思正是它所说的
Date
不是真正的子类,当然也不像您那样。尝试使用组合而不是继承(就像jQuery那样)!当然但是这个错误,为什么在我调用guy.prototype[propName].apply(这个,[].slice.apply(参数))
时出现,而不是在调用Date.prototype.setDate.apply(Date[20])
时出现?我很困惑。因为date
是一个具有适当内部插槽的真实日期实例,而this
不是-一个继承自date.prototype
的对象是不够的。我明白了!我正在用我所做的来回答我自己的问题。关于如何避免评估
,请看一看。另外,您不应该将所有这些属性放在返回函数的.prototype
上吗?谢谢,@Bergi!现在可以了吗?不可以,不要在每次调用时重新创建那些prototype
对象并使用Object.setPrototypeOf(this)
,而应该将它们分配给封装
返回的函数的.prototype
。
let encapsulate = function (guy) {
return function () {
let argumentsWrapper =
[].slice.apply(arguments)
.reduce((aw, argument, idx) => {
aw['a' + idx] = argument;
return aw;
}, {})
this.inner = eval('new guy(' +
Object.keys(argumentsWrapper)
.reduce((string, argumentName, idx, arr) =>
string + 'argumentsWrapper.'
+ argumentName
+ (idx != arr.length - 1 ? ',' : ''),
'')
+ ')')
let setProperties = Object.getOwnPropertyNames(guy.prototype)
.filter(propName => propName.match(/^set/g))
setProperties.forEach(function (propName) {
this[propName] = (function () {
guy.prototype[propName].apply(this.inner, [].slice.apply(arguments))
return this
}).bind(this)
}, this)
Object.getOwnPropertyNames(guy.prototype)
.filter(propName => !propName.match(/^set/g))
.forEach(function (propName) {
this[propName] = (function () {
return guy.prototype[propName].apply(this.inner, [].slice.apply(arguments))
}).bind(this)
}, this)
this.applyFunction = fn => {
fn(this)
return this
}
}
}