使用显式接收器调用 ColdFusion 方法
Call ColdFusion method with explicit receiver
我正在尝试在 ColdFusion 中编写一个 mixin。
ExampleMixin.cfc:
component {
remote void function mixin(component, methodName) {
var original = component[methodName];
component[methodName] = function() {
writeOutput("Mixin!");
return original(arguments);
};
}
}
test.cfc:
component {
new ExampleMixin().mixin(this, 'foo');
remote string function foo() {
return getOutput();
}
private string function getOutput() {
return "Hello, World!";
}
}
运行 foo
产生错误,Variable GETOUTPUT is undefined.
。如果我注释掉 new ExampleMixin().mixin(this, 'foo');
,它 运行 没问题。
看起来当 foo
是来自包装器的 运行 时,它不是 运行ning 在正确的上下文中。在 JavaScript 中,可以写 foo.call(component, ...arguments)
来纠正这一点。 ColdFusion 中是否有等效项?
ColdFusion 同时使用 this
和 variables
范围来存储函数
参考。使用的引用取决于调用函数的方式。如果
该函数是从同级调用的,使用了 variables
引用。如果
该函数正在外部调用,然后使用 this
引用。
以下代码使用基数 class 来提供混合功能。这
$mixin
函数接受一个组件实例并注入它的所有函数。
如果发生名称冲突,包装器将首先调用 mixin,然后
原来的功能。我正在为原始函数和
mixin 函数,因此可以在两个范围内设置引用。
这是在 Lucee 5.2.8.50 上测试的。
mixable.cfc
component {
function $mixin(obj) {
var meta = getComponentMetadata(obj);
for(var func in meta.functions) {
if(structKeyExists(this, func.name)) {
var orig = func.name & replace(createUUID(), '-', '', 'all');
var injected = func.name & replace(createUUID(), '-', '', 'all');
this[orig] = this[func.name];
variables[orig] = this[func.name];
this[injected] = obj[func.name];
variables[injected] = obj[func.name];
var wrapper = function() {
this[injected](argumentCollection=arguments);
return this[orig](argumentCollection=arguments);
};
this[func.name] = wrapper;
variables[func.name] = wrapper;
} else {
this[func.name] = obj[func.name];
return variables[func.name] = obj[func.name];
}
}
}
}
test.cfc
component extends="mixable" {
remote function foo() {
writeOutput("foo(), calling bar()<br>");
bar();
}
private function bar() {
writeOutput("bar()<br>");
}
}
mixin.cfc
component {
function foo() {
writeOutput("foo mixin, calling bar()<br>");
bar();
}
function myfunc() {
writeOutput("myfunc()<br>");
}
}
index.cfm
<cfscript>
t = new test();
t.$mixin(new mixin());
t.myfunc();
t.foo();
</cfscript>
输出
myfunc()
foo mixin, calling bar()
bar()
foo(), calling bar()
bar()
我正在尝试在 ColdFusion 中编写一个 mixin。
ExampleMixin.cfc:
component {
remote void function mixin(component, methodName) {
var original = component[methodName];
component[methodName] = function() {
writeOutput("Mixin!");
return original(arguments);
};
}
}
test.cfc:
component {
new ExampleMixin().mixin(this, 'foo');
remote string function foo() {
return getOutput();
}
private string function getOutput() {
return "Hello, World!";
}
}
运行 foo
产生错误,Variable GETOUTPUT is undefined.
。如果我注释掉 new ExampleMixin().mixin(this, 'foo');
,它 运行 没问题。
看起来当 foo
是来自包装器的 运行 时,它不是 运行ning 在正确的上下文中。在 JavaScript 中,可以写 foo.call(component, ...arguments)
来纠正这一点。 ColdFusion 中是否有等效项?
ColdFusion 同时使用 this
和 variables
范围来存储函数
参考。使用的引用取决于调用函数的方式。如果
该函数是从同级调用的,使用了 variables
引用。如果
该函数正在外部调用,然后使用 this
引用。
以下代码使用基数 class 来提供混合功能。这
$mixin
函数接受一个组件实例并注入它的所有函数。
如果发生名称冲突,包装器将首先调用 mixin,然后
原来的功能。我正在为原始函数和
mixin 函数,因此可以在两个范围内设置引用。
这是在 Lucee 5.2.8.50 上测试的。
mixable.cfc
component {
function $mixin(obj) {
var meta = getComponentMetadata(obj);
for(var func in meta.functions) {
if(structKeyExists(this, func.name)) {
var orig = func.name & replace(createUUID(), '-', '', 'all');
var injected = func.name & replace(createUUID(), '-', '', 'all');
this[orig] = this[func.name];
variables[orig] = this[func.name];
this[injected] = obj[func.name];
variables[injected] = obj[func.name];
var wrapper = function() {
this[injected](argumentCollection=arguments);
return this[orig](argumentCollection=arguments);
};
this[func.name] = wrapper;
variables[func.name] = wrapper;
} else {
this[func.name] = obj[func.name];
return variables[func.name] = obj[func.name];
}
}
}
}
test.cfc
component extends="mixable" {
remote function foo() {
writeOutput("foo(), calling bar()<br>");
bar();
}
private function bar() {
writeOutput("bar()<br>");
}
}
mixin.cfc
component {
function foo() {
writeOutput("foo mixin, calling bar()<br>");
bar();
}
function myfunc() {
writeOutput("myfunc()<br>");
}
}
index.cfm
<cfscript>
t = new test();
t.$mixin(new mixin());
t.myfunc();
t.foo();
</cfscript>
输出
myfunc()
foo mixin, calling bar()
bar()
foo(), calling bar()
bar()