我有一种叫做action的对象。它们的构造如下:
const Action = (name, type, cb) => ({
name,
type,
do: cb
})
const dumbtion = Action('dumb', 'system', () => { console.log("I'm dumb")})
它可以满足我的需求,但我更喜欢使用dumbtion()
而不是dumbtion.do()
。反正有没有在JavaScript中实现这一点?
您可以使用closure
并返回一个新函数,在运行时将调用cb
并使用name
和type
作为参数。
function createAction(name, type, cb) {
return function() {
cb(name, type);
};
}
const dumbtion = createAction('dumb', 'system', (name, type) => {
console.log(`I'm '${name}' of type: '${type}'`);
});
dumbtion();
如果您还想访问这些属性(具有不同的名称,因为name
是Function
的现有属性),您可以执行以下操作:
function createAction(name, type, cb) {
const result = function() {
return cb(result._name, result._type);
};
result._name = name;
result._type = type;
return result;
}
const dumbtion = createAction('dumb', 'system', (name, type) => {
console.log(`I'm '${name}' of type: '${type}'`);
});
dumbtion();
dumbtion._name = "not dumb";
dumbtion._type = "not system";
dumbtion();
虽然如果使用Object.defineProperty
你会有更多的控制权:
function createAction(name, type, cb) {
const result = function() {
return cb(name, type);
};
Object.defineProperty(result, "_name", {
get: function() {
return name;
},
set: function(value) {
name = value;
}
});
Object.defineProperty(result, "_type", {
get: function() {
return type;
},
set: function(value) {
type = value;
}
});
return result;
}
const dumbtion = createAction('dumb', 'system', (name, type) => {
console.log(`I'm '${name}' of type: '${type}'`);
});
dumbtion();
dumbtion._name = "not dumb";
dumbtion._type = "not system";
dumbtion();
通过将属性直接分配给函数,然后返回函数,可以:
const Action = (actionName, type, cb) => (
Object.assign(cb, { actionName, type })
)
const dumbtion = Action('dumb', 'system', () => { console.log("I'm dumb")})
dumbtion();
console.log(dumbtion.type);
但这不是一个好主意 - 函数通常不应该添加非标准属性。我更喜欢你目前使用的代码。
(注意,不能使用属性name
,因为它是在函数上保留的 - 它不能被重新赋值)
不是函数的对象不能被视为一个对象。
您可以创建一个函数并将属性赋值给它。
const action = (name, type, cb) => {
const func = function () {
return cb.apply(this, arguments);
};
func.name = name;
func.type = type;
func.do = cb;
return func;
};
const modified = action('a name', 'system', () => { console.log("Foo")})
modified();
console.log(modified.type);
你可以让Action
返回一个关闭参数name
和type
的函数:
const Action = (name, type, cb) => () => cb(name, type);
const dumbtion = Action('dumb', 'system', (name, type) => {
console.log(`I'm dumb, name = ${name}, type = ${type}`);
});
dumbtion();
在这个具体的例子中,Action
并没有真正起到太多作用,但是一般模式非常有用。
如果你想在name
本身访问type
和dumbtion
,函数就是对象,所以你可以为它们添加属性:
const Action = (xname, type, cb) => {
cb.xname = xname;
cb.type = type;
return cb;
};
const dumbtion = Action('dumb', 'system', function cb() {
console.log(`I'm dumb, name = ${cb.xname}, type = ${cb.type}`);
});
dumbtion();
console.log(dumbtion.xname);
console.log(dumbtion.type);
注意我在那里使用了一个命名函数表达式,以便回调可以在调用中按名称访问自己。另请注意,您不能使用name
,它是函数的预定义属性。 (好吧,好吧,你可以通过Object.defineProperty
使用它,但最好不要。)
只需从你的function
函数返回一个Action
,它将.do
称为引擎盖:
const Action = (name, type, cb) => () => ({
name,
type,
do: cb
}).do();
const dumbtion = Action('dumb', 'system', () => { console.log("I'm dumb")})
dumbtion(); // <-- calls `.do()` internally
但是你将失去访问其他属性的可能性。