javascript - Javascript:编写一个高阶函数以使用调用它的对象的上下文
问题描述
我正在尝试编写一个将日志记录添加到任何函数的函数。就像是:
function loggerise(f) {
return function() {
const r = f(...arguments)
console.log(r)
return r
}
}
除了以上不起作用。
在此对象上测试:
const oracle = {
question:'',
ask: function(q) {this.question=q},
answer: function() {return 'Answer to '+this.question+' is 42'},
answerLog: loggerise(function() {return 'Answer to '+this.question+' is 42'})
}
oracle.ask('the universe');
alert(oracle.answer()); // correct result, no logging
alert(loggerise(()=>(42))()) // correct result and logging, not in object
alert(oracle.answerLog()); // wrong result and logging, in object
该函数给出的结果Answer to undefined is 42
表明对象的上下文丢失了。我试图明确定义上下文,但我弄错了:
function loggerise(f) {
const that = this
return function() {
const r = f.apply(that,arguments)
console.log(r)
return r
}
}
给出了同样的错误结果,同样的一些变体也是如此。
解决方案
您还需要在调用函数时传递值this
,否则在调用对象中的方法时会丢失上下文。
您可以将arguments
对象用于:
Function#apply()
function loggerise(f) {
return function() {
const r = f.apply(this, arguments);
console.log(r)
return r;
}
}
function loggerise(f) {
return function() {
const r = f.apply(this, arguments);
console.log(r)
return r;
}
}
const oracle = {
question:'',
ask: function(q) {this.question=q},
answer: function() {return 'Answer to '+this.question+' is 42'},
answerLog: loggerise(function() {return 'Answer to '+this.question+' is 42'})
}
oracle.ask('the universe');
console.log(oracle.answer());
console.log(loggerise(()=>(42))());
console.log(oracle.answerLog());
Function#call()
function loggerise(f) {
return function() {
const r = f.call(this, ...arguments);
console.log(r)
return r;
}
}
function loggerise(f) {
return function() {
const r = f.call(this, arguments);
console.log(r)
return r;
}
}
const oracle = {
question:'',
ask: function(q) {this.question=q},
answer: function() {return 'Answer to '+this.question+' is 42'},
answerLog: loggerise(function() {return 'Answer to '+this.question+' is 42'})
}
oracle.ask('the universe');
console.log(oracle.answer());
console.log(loggerise(()=>(42))());
console.log(oracle.answerLog());
Reflect.apply()
function loggerise(f) {
return function() {
const r = Reflect.apply(f, this, arguments);
console.log(r)
return r;
}
}
function loggerise(f) {
return function() {
const r = Reflect.apply(f, this, arguments);
console.log(r)
return r;
}
}
const oracle = {
question:'',
ask: function(q) {this.question=q},
answer: function() {return 'Answer to '+this.question+' is 42'},
answerLog: loggerise(function() {return 'Answer to '+this.question+' is 42'})
}
oracle.ask('the universe');
console.log(oracle.answer());
console.log(loggerise(()=>(42))());
console.log(oracle.answerLog());
这些之间没有太大区别。这取决于您选择哪一个。
推荐阅读
- angular - Angular 2 异步验证器
- ios - 从越狱的 Iphone 4 读取传出的短信
- unity3d - Unity 中的 Vuforia 开发协议问题
- javascript - 绝对定位不滚动
- docker - Docker 共享常用的 bins 和 libs?
- javascript - Slack oauth.access API 返回 bad_redirect_uri 而不请求 redirect_uri
- python - 如何扩展损失函数 Pytorch
- javascript - ionic v4 angular-router,如何在视图导航之间隐藏恢复谷歌地图
- python - 如何从使用 python 解析的 yaml 文件中调用和迭代值?
- c - Linux 内核模块:printk 消息不在我期望的缓冲区日志中