把它看成是一个命名空间。关键字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
关键字不是必需的,但我认为写这个的人不熟悉JS关闭,或者至少对他们的方式不安全工作。此代码有效地模拟单例模式,或者至少将对象字面量视为类的实例。我的猜测是,作者熟悉古典的面向对象,但不是原型继承。总之,上面的代码更安全,更安全的最好恕我直言
在您的嵌套三元的事情,我已经检查下面使用的JSLint的代码,并提出更短的,但更清晰的选择:使用默认的运营商,其次是三元:
//JSLint recommends this
target = argTarget || argFlag ? 100 : 0;
//over nested ternary
target = argTarget ? argTarget : argFlag ? 100 : 0;
不管怎么说,这是相同的代码,只是不使用危险this
结构,但使用封闭,JavaScript的一个令人惊讶的强大功能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); === :-(
是的,这正是我的想法。在这种情况下这不是必需的,但是我上面看过,它用于在这个命名空间中创建变量(属性)。 this.elem.si是我认为的一个错误,因为它不会加在我身上。它被定义为this.si.我喜欢你的代码方式比编写此代码的人使用的更好。我有暴露于封闭和命名空间。我无法舒适地谈论这些主题。 – W3Geek 2012-08-07 09:54:43
你说得对,说'这'不是必要的。你发布的代码创建一个对象字面值,但被写为一个构造函数。这只是令人困惑和不好的做法。如果你知道你将需要什么变量,请使用闭包。你的对象现在的工作方式,你可能会意外地改变'target'属性,导致间隔在一个不同的元素上突然淡出,从而结束了2个半褪色元素。使用闭包可以保护你免受此影响。我会将这段代码更加深入到一个可用的,安全的版本(这个版本仍然有一些问题需要解决) – 2012-08-07 10:11:40
不知道这个答案是否太好,无法被接受... – ted 2012-08-07 20:01:40