在不实际扩展原型的情况下拥有扩展原型的优点
Have the niceties of extended prototype without actually extending the prototype
我想做的是有一个接口,您可以在其中将元素包装到具有扩展原型的实例中,例如。
const wrappedButton = new WrappedElem(document.getElementById('some-button'))
// we have access to our custom added method:
console.log(`I am the ${wrappedButton.siblingIndex()}th button`)
// but we still have access to the original methods
wrappedButton.addEventListener('click', function(e){
console.log('I clicked on', e.target)
// right here we won't have access to siblingIndex, because the prototype of the element itself was not changed.
})
我可以像这样扩展原始原型
HTMLElement.prototype.siblingIndex = function() {
if(this.parentNode == null) {
return -1
}
return Array.prototype.indexOf.call(this.parentNode.children, this)
}
但是扩展原型是不好的做法,而且性能很差。
所以可以做这样的事情吗?
通过使用代理,我们可以在不更改原型的情况下添加新方法:
const siblingIndex = () => {}
const handler = {
get(target, property) {
if(property === 'siblingIndex') {
return siblingIndex;
}
return target[property];
}
}
const proxyButton = new Proxy(button, handler);
// we can also call the siblingIndex function
proxyButton.siblingIndex();
// we can access the properties of the underlying object
proxyButton.tagName;
e.target 但是不会 return 代理而是原始对象,
但你可以只使用 proxyButton 而不是 e.target
如果需要,您还可以在调用回调时将 addEventListener 方法重写为 return 代理版本
这似乎工作正常。非常感谢Lk77。
var wrappedElMethods = {
siblingIndex() {
if(this.parentNode == null) {
return -1
}
return Array.prototype.indexOf.call(this.parentNode.children, this)
}
}
function wrappedEl(el) {
return proxyInherit(el, wrappedElMethods)
}
function proxyInherit(item, overwrites) {
const handler = {
get(target, property) {
let value
const overwriteVal = overwrites[property]
if(overwriteVal != undefined) {
value = overwriteVal
} else {
value = target[property]
}
if(value instanceof Function) {
return value.bind(item)
}
return value
},
set(target, property, value) {
target[property] = value
}
}
return new Proxy(item, handler)
}
// Usage:
var button = wrappedEl(e.target)
button.onclick = function() {
console.log(button.siblingIndex())
}
我想做的是有一个接口,您可以在其中将元素包装到具有扩展原型的实例中,例如。
const wrappedButton = new WrappedElem(document.getElementById('some-button'))
// we have access to our custom added method:
console.log(`I am the ${wrappedButton.siblingIndex()}th button`)
// but we still have access to the original methods
wrappedButton.addEventListener('click', function(e){
console.log('I clicked on', e.target)
// right here we won't have access to siblingIndex, because the prototype of the element itself was not changed.
})
我可以像这样扩展原始原型
HTMLElement.prototype.siblingIndex = function() {
if(this.parentNode == null) {
return -1
}
return Array.prototype.indexOf.call(this.parentNode.children, this)
}
但是扩展原型是不好的做法,而且性能很差。
所以可以做这样的事情吗?
通过使用代理,我们可以在不更改原型的情况下添加新方法:
const siblingIndex = () => {}
const handler = {
get(target, property) {
if(property === 'siblingIndex') {
return siblingIndex;
}
return target[property];
}
}
const proxyButton = new Proxy(button, handler);
// we can also call the siblingIndex function
proxyButton.siblingIndex();
// we can access the properties of the underlying object
proxyButton.tagName;
e.target 但是不会 return 代理而是原始对象, 但你可以只使用 proxyButton 而不是 e.target
如果需要,您还可以在调用回调时将 addEventListener 方法重写为 return 代理版本
这似乎工作正常。非常感谢Lk77。
var wrappedElMethods = {
siblingIndex() {
if(this.parentNode == null) {
return -1
}
return Array.prototype.indexOf.call(this.parentNode.children, this)
}
}
function wrappedEl(el) {
return proxyInherit(el, wrappedElMethods)
}
function proxyInherit(item, overwrites) {
const handler = {
get(target, property) {
let value
const overwriteVal = overwrites[property]
if(overwriteVal != undefined) {
value = overwriteVal
} else {
value = target[property]
}
if(value instanceof Function) {
return value.bind(item)
}
return value
},
set(target, property, value) {
target[property] = value
}
}
return new Proxy(item, handler)
}
// Usage:
var button = wrappedEl(e.target)
button.onclick = function() {
console.log(button.siblingIndex())
}