我正在寻找如何使用JavaScript淡化元素,我遇到了这个函数(对象)。我开始想知道它是如何工作的?
var fadeEffect=function(){
return{
init:function(id, flag, target){
this.elem = document.getElementById(id);
clearInterval(this.elem.si);
this.target = target ? target : flag ? 100 : 0;
this.flag = flag || -1;
this.alpha = this.elem.style.opacity ? parseFloat(this.elem.style.opacity) * 100 : 0;
this.si = setInterval(function(){fadeEffect.tween()}, 20);
},
tween:function(){
if(this.alpha == this.target){
clearInterval(this.elem.si);
}else{
var value = Math.round(this.alpha + ((this.target - this.alpha) * .05)) + (1 * this.flag);
this.elem.style.opacity = value / 100;
this.elem.style.filter = 'alpha(opacity=' + value + ')';
this.alpha = value
}
}
}
}();
我知道这是自调用的,只返回一个带有两个方法的对象。我主要担心的是它为什么使用this关键字?我假设'this'关键字是对象名称“fadeEffect”的占位符。我会理解,如果'this'用于创建多个对象......但为什么在这里使用它?
困扰我的另一件事是这个三元运算符......
this.target = target ? target : flag ? 100 : 0;
这是怎么回事?这就像两个三元运算符组合成一个我从未想过可能的运算符?
答案 0 :(得分:4)
至于你的第二个问题。这可能会更清楚:
this.target = (target ? target : (flag ? 100 : 0));
是的,一个嵌套的三元运算符!用文字写出:
this.target =(目标为真值?然后使用目标。如果没有,则使用最后一部分的结果 - &gt;(标记为真值?使用100.否则,使用0))。< / p>
答案 1 :(得分:3)
将其视为命名空间。 this
关键字引用自调用函数返回的对象文字。这意味着this.target
可以在全局命名空间(或fadeEffect
定义的任何范围)中作为对象属性fadeEffect.target
访问,但它不会干扰其他变量可能存在于外部范围内。
这两个方法设置了返回对象的新属性,这就是它的全部属性。就个人而言,我发现这是一个错误的代码...在这个例子中,闭包将是更好的选择:
var fadeEffect=function(){
var elem,target,flag,alpha,si;//make private
return{
init:function(id, flag, target){
elem = document.getElementById(id);
clearInterval(elem.si);
target = target ? target : flag ? 100 : 0;
flag = flag || -1;
alpha = elem.style.opacity ? parseFloat(elem.style.opacity) * 100 :0;
si = setInterval(function(){fadeEffect.tween()}, 20);
},
tween:function(){
if(alpha == target){
clearInterval(si);//this.elem.si doesn't add up, init defines it as this.si
}else{
var value = Math.round(alpha + ((target - alpha) * .05))+ (1 * flag);
elem.style.opacity = value / 100;
elem.style.filter = 'alpha(opacity=' + value + ')';
alpha = value
}
}
}
}();
这可以做同样的事情,但是其他代码不能干扰目标的值,或者扰乱间隔等等......你说this
关键字不是&#39;在这种情况下需要,但我认为写这篇文章的人要么不熟悉JS闭包,要么至少不确定它们是如何工作的。此代码有效地模拟单例模式,或者至少将对象文字视为类的实例。我的猜测是,作者熟悉经典的OOP,但不熟悉原型继承。无论如何,上面的代码更安全,更安全是更好的恕我直言
关于嵌套三元组的问题,我使用JSLint检查了下面的代码,它提出了一个更短但更清晰的替代方法:使用默认运算符,然后是三元运算符:
//JSLint recommends this
target = argTarget || argFlag ? 100 : 0;
//over nested ternary
target = argTarget ? argTarget : argFlag ? 100 : 0;
无论如何,这里的代码相同,只是没有使用危险的this
构造,而是使用一个闭包,一个JavaScripts令人惊讶的强大功能BTW,值得仔细看看你能做些什么他们!
var fadeEffect=(function()
{
var elem,target,flag,alpha,si;//make private
//define private 'methods': functions will be available, but only to return object
//tween shouldn't be callable, it's a callback for the interval, which is set in init
function tween()
{
if(alpha === target)
{
clearInterval(si);//this.elem.si doesn't add up, init defines it as this.si
}
else
{
alpha = Math.round(alpha + ((target - alpha) * 0.05))+ (1 * flag);
//don't know why 1*flag is needed here, suggest:
//alpha = Math.round(alpha + ((target - alpha) * 0.05)) + (+flag); +flag coerces to numeric
elem.style.opacity = alpha / 100;
elem.style.filter = 'alpha(opacity=' + alpha + ')';
}
}
return{
init:function(id, argFlag, argTarget)//arguments !== closure scope
{
if (si !== undefined && si !== null)
{
clearInterval(si);
}
elem = document.getElementById(id);
//JSLint recommends this:
target = argTarget || argFlag ? 100 : 0;
//over nested ternary
target = argTarget ? argTarget : argFlag ? 100 : 0;
flag = argFlag || -1;
alpha = elem.style.opacity ? parseFloat(elem.style.opacity) * 100 :0;
si = setInterval(tween, 20);//just a reference to the tween function will do
}
};
})();
fadeEffect.init('someId',1,50);//will set things in motion
fadeEffect.tween();//undefined
console.log(fadeEffect.target);
fadeEffect.target = document.getElementById('someOtherId');//no problem, but won't change the value of var target
这样,tween
方法不能被调用,而是按区间调用,对象及其方法/函数正在运行的元素永远不能被覆盖外部操作,它们是对象固有的。这样可以实现更安全的构造,更重要的是,你只能弄乱1个方法:覆盖.init
方法,对象变得无用,但无害。将它与你的代码进行比较,你可以把这两种方法都搞砸了,但是留出间隔......这是个坏消息:间隔最终会找到一个很可能被删除的回调函数,导致你的代码惨遭失败:
//asume your code using this.tween();
fadeEffect.init('id',1,123);
delete fadeEffect.tween;
//inside fadeEffect:
setInterval(function(){fadeEffect.tween()}, 20);
//should be written as:
setInterval(fadeEffect.tween,20);
// === setInterval(undefined,20); === :-(
答案 2 :(得分:2)
this.target = target ? target : flag ? 100 : 0;
的另一个解释:
if(target){
this.target = target;
}
else{
if(flag){
this.target = 100;
} else {
this.target = 0;
}
}