javascript: 在对象之间扩展方法,比如 mixins
javascript: extending methods between objects, like mixins
我想在不同的对象之间共享或重用一些逻辑,它们将非常相似,只是更改 "scope"。
var Mixin = {
show: function () {
this.container.show();
},
hide: function () {
this.container.hide();
},
play: function (data) {
data.map().append();
}
};
var ObjectA = {
container: $('#container_a');
foo: function () {
this.play(otherData); // Mixin common method?
}
};
var ObjectB = {
container: $('#container_b'),
foo: function () {
this.play(data); // Mixin common method?
}
};
ObjectA.show() // show $('#container_a');
ObjectB.show() // show $('#container_b');
我正在尝试使用下划线
_.extend(ObjectA, Mixin);
但似乎我对 Mixin 的引用(对最后一个扩展对象的引用)有问题,比如我是否需要克隆对象并扩展它?
有什么方法可以做类似的事情吗?
谢谢!!
编辑:我对 'this' 的范围有疑问,即引用 window,当传递作为回调函数继承自 mixin 时,就像这样.
PersonMixin = {
mixinFoo: function () {
this.handleResponse();
}
};
Person = {
personMethod: function () {
OtherLibrary.libMehtod(this.mixinFoo);
}
};
Object.assign(Person, PersonMixin);
然后,类似这样的事情会失败,这是一个堆栈跟踪示例
Person.personMethod();
OtherLibrary.libMethod(callbackMixin);
Ajax.post(callbackMixin);
callbackMixin(response); // this.handleResponse() is not defined, because this reference to window object.
编辑 2:我可以使用 bind()
解决这个问题
您可以通过多种方式做到这一点,我的偏好是在创建时调整对象 __proto__
属性,这将导致它通过其原型链继承您的混入。这不需要使用下划线。
我针对 ES6 调整了您的示例并使其更简单一些,但应该明白了这一点。
const PlayerType = (
{ show() {
console.info(`show ${this.name}`)
}
, hide() {
console.info(`hide ${this.name}`)
}
, play: function (data) {
data.map().append();
}
}
)
const objA = { __proto__: PlayerType
, name: 'objA'
, foo(...args) {
this.play(...args)
}
}
const objB = { __proto__: PlayerType
, name: 'objB'
, foo(...args) {
this.play(...args)
}
}
objA.show()
objB.show()
更简单且没有 ES6:
var Mixin = (
{ show() {
console.info('show ' + this.name)
}
, hide() {
console.info('hide ' + this.name)
}
}
)
var a = { __proto__: Mixin, name: 'a' }
var b = { __proto__: Mixin, name: 'b' }
a.show()
b.show()
Alternate - 与 Object.create() 做同样的事情。
var Mixin = (
{ show() {
console.info('show ' + this.name)
}
, hide() {
console.info('hide ' + this.name)
}
}
)
var a = Object.create(Mixin, { name: { value: 'a', enumerable: true } })
var b = Object.create(Mixin, { name: { value: 'b', enumerable: true } })
a.show()
b.show()
有效,还请检查您的语法。
var Mixin = {
show: function() {
console.log(this.tmp);
}
}
var oA = {
tmp: 'tmpA'
}
var oB = {
tmp: 'tmpB'
}
var mA = Object.assign(oA, Mixin);
var mB = Object.assign(oB, Mixin)
mA.show();
mB.show()
我想在不同的对象之间共享或重用一些逻辑,它们将非常相似,只是更改 "scope"。
var Mixin = {
show: function () {
this.container.show();
},
hide: function () {
this.container.hide();
},
play: function (data) {
data.map().append();
}
};
var ObjectA = {
container: $('#container_a');
foo: function () {
this.play(otherData); // Mixin common method?
}
};
var ObjectB = {
container: $('#container_b'),
foo: function () {
this.play(data); // Mixin common method?
}
};
ObjectA.show() // show $('#container_a');
ObjectB.show() // show $('#container_b');
我正在尝试使用下划线
_.extend(ObjectA, Mixin);
但似乎我对 Mixin 的引用(对最后一个扩展对象的引用)有问题,比如我是否需要克隆对象并扩展它?
有什么方法可以做类似的事情吗?
谢谢!!
编辑:我对 'this' 的范围有疑问,即引用 window,当传递作为回调函数继承自 mixin 时,就像这样.
PersonMixin = {
mixinFoo: function () {
this.handleResponse();
}
};
Person = {
personMethod: function () {
OtherLibrary.libMehtod(this.mixinFoo);
}
};
Object.assign(Person, PersonMixin);
然后,类似这样的事情会失败,这是一个堆栈跟踪示例
Person.personMethod();
OtherLibrary.libMethod(callbackMixin);
Ajax.post(callbackMixin);
callbackMixin(response); // this.handleResponse() is not defined, because this reference to window object.
编辑 2:我可以使用 bind()
解决这个问题您可以通过多种方式做到这一点,我的偏好是在创建时调整对象 __proto__
属性,这将导致它通过其原型链继承您的混入。这不需要使用下划线。
我针对 ES6 调整了您的示例并使其更简单一些,但应该明白了这一点。
const PlayerType = (
{ show() {
console.info(`show ${this.name}`)
}
, hide() {
console.info(`hide ${this.name}`)
}
, play: function (data) {
data.map().append();
}
}
)
const objA = { __proto__: PlayerType
, name: 'objA'
, foo(...args) {
this.play(...args)
}
}
const objB = { __proto__: PlayerType
, name: 'objB'
, foo(...args) {
this.play(...args)
}
}
objA.show()
objB.show()
更简单且没有 ES6:
var Mixin = (
{ show() {
console.info('show ' + this.name)
}
, hide() {
console.info('hide ' + this.name)
}
}
)
var a = { __proto__: Mixin, name: 'a' }
var b = { __proto__: Mixin, name: 'b' }
a.show()
b.show()
Alternate - 与 Object.create() 做同样的事情。
var Mixin = (
{ show() {
console.info('show ' + this.name)
}
, hide() {
console.info('hide ' + this.name)
}
}
)
var a = Object.create(Mixin, { name: { value: 'a', enumerable: true } })
var b = Object.create(Mixin, { name: { value: 'b', enumerable: true } })
a.show()
b.show()
有效,还请检查您的语法。
var Mixin = {
show: function() {
console.log(this.tmp);
}
}
var oA = {
tmp: 'tmpA'
}
var oB = {
tmp: 'tmpB'
}
var mA = Object.assign(oA, Mixin);
var mB = Object.assign(oB, Mixin)
mA.show();
mB.show()