我正在寻找满足以下要求的 JavaScript 实现:
- 原型(prototype)实现了 next 和 run 方法。如果调用 next,则迭代函数 once 被调用一次。如果调用 run,则无限频繁地调用 once(也必须可以通过用户请求中止,但目前未反射(reflect)在源代码中)。
- once 接受一个完成参数,一旦完成就会调用该参数。
- 迭代函数once在原型(prototype)中定义,但可以并且将会被子Child覆盖。
- run 中的无限迭代必须是可能的,因此堆栈必须丢失(当 setTimeout 调用函数时会发生这种情况。
我当前的源代码问题:调用了Parent的一次,而不是Child的调用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>JS test</title>
<script type="text/javascript">
function write(msg) {
var t = document.createTextNode(msg);
var li = document.createElement("li");
li.appendChild(t);
document.querySelector("ul").appendChild(li);
}
var Parent = function () {
var running = 0;
var run = function () {
running = Infinity;
invokeNextIter();
};
var next = function () {
running = 1;
invokeNextIter();
};
var invokeNextIter = function () {
if (running > 0) {
running -= 1;
setTimeout(function () { once(invokeNextIter); }, 1);
}
};
var once = function (done) {
var time = Math.random() * 3 + 1;
write(time + " sec");
setTimeout(done, time * 1000);
};
return {
run: run,
once: once
};
};
var Child = function () {
var once = function (done) {
write("2 sec as always");
setTimeout(done, 2000);
};
var p = new Parent();
return Object.create(p, { once : once });
};
function main() {
var c = new Child();
c.run();
}
</script>
</head>
<body onload="main()">
<ul>
</ul>
</body>
</html>
无法使用 Function.prototype.bind 或相关技术运行它。任何帮助感激不尽😎
最佳答案
好吧,就您的情况而言,Parent
和 Child
之间唯一不同的函数是您的 once() 函数。
所以你必须从你的Parent
类开始,构建核心,然后你将实例方法添加到Parent
和child
,以覆盖 once()
函数。
我们将使用原型(prototype)继承。规则是您可以为使用 new
关键字初始化的任何对象创建原型(prototype),其中包括 native JavaScript 对象。
function write(msg) {
var t = document.createTextNode(msg);
var li = document.createElement("li");
li.appendChild(t);
document.querySelector("ul").appendChild(li);
}
var Parent = function(){
//Retrieve context
var self = this;
var running = 0
//Create a `run` function which will refer to the current context
self.run = function(){
running = Infinity;
invokeNextIter();
}
//Declare our private function
var next = function () {
running = 1;
invokeNextIter();
};
var invokeNextIter = function () {
if (running > 0) {
running -= 1;
setTimeout(function () {
//Call once method which is in the prototype of the current context
self.once(invokeNextIter);
}, 1);
}
};
}
//Add a "once" instance method to Parent
Parent.prototype.once = function(done){
var time = Math.random() * 3 + 1;
write(time + " sec");
setTimeout(function(){
done();
}, time * 1000);
}
//Create our Child 'class'
var Child = function(){
}
//Declare Child as a subclass of the first
Child.prototype = new Parent();
//Add a "once" instance method to Child and override the "once" parent method
Child.prototype.once = function(done){
write("1.5 sec as always");
setTimeout(function(){
done();
}, 1500);
}
function main(){
// Create instances and see the overridden behavior
var c = new Child();
var p = new Parent();
//c.run() will call child once() method
c.run();
//p.run() will call parent once() method
p.run();
}
在这里,您可以看到 self.run()
和 self.once()
。 Self
变量将引用当前实例。
关于Javascript:原型(prototype)提供了无限调用对象方法的接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32203313/