javascript元编程?
问题来自于codewars The builder of things
要求我们实现一个Thing类,其中一点要求如下所示:
describe('#can', function(){ describe('jane.can.speak(phrase => `${name} says: ${phrase}!`)', function(){ it('should create a speak method on jane', function(){ const jane = new Thing('Jane'); jane.can.speak(phrase => `${name} says: ${phrase}!`); expect(jane.speak('hello')).to.equal('Jane says: hello!'); }); });
难点是这里的name
的值从哪里找啊?
我想到的一个方案是使用with
,但是codewars上使用的是严格模式,不能使用with
。
class Thing { // TODO: Make the magic happen /* const jane = new Thing('jane'); console.log(jane.name) => 'jane' */ constructor(name) { this.name = name; /* can jane.can.speak(phrase => `${name} says: ${phrase}!`) jane.speak('Hello') => 'jane says: Hello!' where to find name ? => this */ this.can = { speak: (callback) => { this.speak = (...args) => { let res; with(this) { res = callback(...args); }; return res; } } } }
我有一计:
class Thing { constructor(name) { this.name = name; globalThis.name = name; }}
当然更好的做法是通过 Proxy
拦截 can
的 getter
,在得到 speak
属性之前设置 globalThis.name
,speak
函数调用之后还原 globalThis.name
。
也有其它做法:
Github gist:
const funcStr = callback.toString()const finalFunc = eval(funcStr)
在JavaScript中,元编程是一种编程范式,其中一部分代码用来控制另一部分代码的行为。在你给出的例子中,元编程是用来在运行时动态地向对象添加属性和方法的。
在你的代码中,你试图通过元编程的方式动态地给对象添加一个speak
方法,这个方法可以访问对象的name
属性。然而,你遇到了一个问题,那就是在严格模式下,with
语句是不允许使用的。
在这种情况下,你可以使用闭包来解决问题。闭包是一种函数,它可以记住并访问其词法作用域,即使它是在这个作用域之外执行的。在你的例子中,你可以创建一个闭包函数来访问this.name
:
class Thing { constructor(name) { this.name = name; this.can = { speak: (callback) => { this.speak = (...args) => { return callback(this.name, ...args); } } } }}
这样,当你调用jane.can.speak(phrase =>
${name} says: ${phrase}!)
时,你实际上是在创建一个新的函数,这个函数可以访问this.name
。然后,当你调用jane.speak('hello')
时,实际上是在调用这个闭包函数,并传入'hello'
作为参数。因此,闭包函数可以访问this.name
,并使用它来构建你期望的字符串。
技术的学习是一个登山的过程。第一章是最为平坦的山脚道路。而从这一章开始,则是正式的爬坡。无论是我写作还是你阅读,都需要付出比第一章更多的代价。那么问题就是,付出更多的精力学习模板是否值得? 这个问题很功利,但是一针见血。因为技术的根本目的在于解决需求。那C++的模板能做什么? 一个高(树)大(新)上(风)的回答是,C++里面的模板,犹如C中的宏、C#和Java中的自省(restropection)
元编程 避免无谓的元编程。 当编写程序库时,不要使核心类混乱(不要使用 monkey patch)。 对于 class_eval 方法,倾向使用区块形式,而不是字符串插值形式。 当使用字符串插值形式时,总是提供 __FILE__ 及 __LINE__,以使你的调用栈看起来具有意义: class_eval 'def use_relative_model_naming?; true; end', __
Metaprogramming is a programming technique in which computer programs have the ability to treat other programs as their data. It means that a program can be designed to read, generate, analyze or tran
问题内容: 在IE中,我只能从JavaScript调用element.click()-如何在Firefox中完成相同的任务?理想情况下,我希望有一些跨浏览器同样可以正常工作的JavaScript,但是如果需要,我将为此使用不同的逐浏览器JavaScript。 问题答案: 该文件说:“ 该 _createEvent_方法已被弃用。使用事件构造来代替。 ” 因此,您应该改用以下方法: 并在这样的元素上
我希望根据Get/SetProperty的文档,在Spock测试中重写方法。这在正常的Groovy类中是微不足道的,但在Spock规范中似乎不起作用。 此示例不调用方法。看来斯波克在绕过它。有没有一种方法可以钩入Spock的属性解析机制,或者告诉Spock使用我的重写方法?
问题1 此问题改编自Dave Thomas的屏播Episode 5: Nine Examples of Metaprogramming。 众所周知,RubyLearnin.org的Core Ruby课程已经开办8周了。每周我们都有一个满分10分的测验。8周结束后,学生可以知道他的分数百分比。例如,有一个学生,在过去的8周里,他的得分情况为:5、10、10、10、10、10、10、10。那么,他的得