2009-01-07 61 views
5

为了让我的Javascript不显眼,我使用onLoad s来为<input> s等添加功能。对于Dojo,这看起来是这样的:是否有Ruby的andand的Javascript等价物?

var coolInput = dojo.byId('cool_input'); 
if(coolInput) { 
    dojo.addOnLoad(function() { 
    coolInput.onkeyup = function() { ... }; 
    }); 
} 

或近似等价:

dojo.addOnLoad(function() { 
    dojo.forEach(dojo.query('#cool_input'), function(elt) { 
    elt.onkeyup = function() { ... }; 
    }); 
}); 

有没有人写Ruby的andand,这样我可以做以下的实现?

dojo.addOnLoad(function() { 
    // the input's onkeyup is set iff the input exists 
    dojo.byId('cool_input').andand().onkeyup = function() { ... }; 
}); 

dojo.byId('cool_input').andand(function(elt) { 
    // this function gets called with elt = the input iff it exists 
    dojo.addOnLoad(function() { 
    elt.onkeyup = function() { ... }; 
    }); 
}); 

回答

2

你想要的确切语法是不可能在JavaScript中。 JavaScript执行的方式需要以非常基本的方式进行更改。例如:

var name = getUserById(id).andand().name; 
//      ^
//      |------------------------------- 
// if getUserById returns null, execution MUST stop here | 
// otherwise, you'll get a "null is not an object" exception 

但是,JavaScript不能这样工作。它根本没有。

以下行执行几乎完全你想要的。

var name = (var user = getUserById(id)) ? user.name : null; 

但可读性不会扩展到更大的例子。例如:

// this is what you want to see 
var initial = getUserById(id).andand().name.andand()[0]; 
// this is the best that JavaScript can do 
var initial = (var name = (var user = getUserById(id)) ? user.name : null) ? name[0] : null; 

而且还有那些不必要的变量的副作用。我使用这些变量来避免双重查找。这些变量弄脏的背景下,如果这是一个巨大的交易,你可以使用匿名函数:现在

var name = (function() {return (var user = getUserById(id)) ? user.name : null;})(); 

,用户变量被清理的正确,并且每个人都高兴。但哇!多少打字! :)

+3

或者使用[CoffeeScript](http://jashkenas.github.com/coffee-script/#operators):查看“存在操作符的访问器变体”?`。:) – 2011-10-29 22:51:17

0

据我所知,没有一个内置的是具有相同功能的JavaScript功能。我认为最好的解决方案是通过类而不是id查询,并使用dojo.forEach(...),因为您将在forEach闭包中保证非空元素。

你总是可以使用JavaScript等价的:

dojo.byId('cool_input') && dojo.byId('cool_input').whateverYouWantToDo(...); 
+0

双向查找正是我想要避免的。它不仅仅适用于dojo.byId;其他功能可能会变慢。 – 2009-01-07 23:28:50

0

我从来没有用过道场,但大多数的JavaScript框架(与DOM打交道时)返回调用元素时的方法从元件对象调用(可怜的措辞,对不起)。所以andand()将是隐含的。

dojo.addOnLoad(function() { 
    dojo.byId('cool_input').onkeyup(function(evt) { /*event handler code*/ 
    }); 
}); 
+0

除了byId找不到请求的元素。 Andand将不做任何事情,但是你的代码会试图在不存在的对象上调用onkeyup。 – 2009-01-07 22:38:56

1

怎么是这样的:

function andand(elt, f) { 
    if (elt) 
    return f(elt); 
    return null; 
} 

这样调用:

andand(dojo.byId('cool_input'), function(elt) { 
    // this function gets called with elt = the input iff it exists 
    dojo.addOnLoad(function() { 
    elt.onkeyup = function() { ... }; 
    }); 
}); 
3

我不知道道场,但不应该你的第一个例子读

dojo.addOnLoad(function() { 
    var coolInput = dojo.byId('cool_input'); 
    if(coolInput) 
     coolInput.onkeyup = function() { ... }; 
}); 

否则,你可能会最终tryi在构建DOM之前访问元素。

回到你的问题:在JavaScript中,我实现andand()作为

function andand(obj, func, args) { 
    return obj && func.apply(obj, args || []); 
} 

你的榜样然后可以写成

dojo.addOnLoad(function() { 
    andand(dojo.byId('cool_input'), function() { 
     this.onkeyup = function() { ... }; 
    }); 
}); 

这是不是真的比使用更短明确的if声明 - 那为什么要麻烦?

0

有关列表:

Array.prototype.andand = function(property, fn) { 

    if (this.filter(property).length > 0) this.map(fn); 
} 
+0

这不起作用。 andand应该在数组为空时停止执行。当然,如果数组为空,它不再是数组。因此,和和方法不再可用。 – 2009-04-14 21:06:41

2

你想要dojo.behavior

dojo.behavior.add({ 
    '#cool_input': { 
     onKeyUp: function(evt) { ... } 
    } 
});