以下文章由 Vendethiel 撰写。你也可以提交客座文章,只需发送一个 pull request 即可。
LiveScript 拥有许多你可能不知道的技巧和窍门。
在这篇博文中,我们将了解如何利用它们!
LiveScript 为数组和字符串提供了一些基本的操作符重载功能。
# when the left one is an array literal ['a' 'b'] * 2 # array repetition # when the right one is a string literal <[ foo bar ]> * ', ' # array joining # or when the left one is a string y = 2 'z' * y # string repetition words = text / ' ' # string division # or even when the right one is either a string or a regexp unspaced = text - /\s+/ [\a to \e] * '' - 'b'
var y, words, unspaced, split$ = ''.split, replace$ = ''.replace; ['a', 'b', 'a', 'b']; ['foo', 'bar'].join(', '); y = 2; repeatString$('z', y); words = split$.call(text, ' '); unspaced = replace$.call(text, /\s+/, ''); ["a", "b", "c", "d", "e"].join('').replace('b', ''); function repeatString$(str, n){ for (var r = ''; n > 0; (n >>= 1) && (str += str)) if (n & 1) r += str; return r; }
你可以使用 ?
动态标记 Heregex。
在这种情况下,将使用最后的插值。
// my? #normal #{[interpolation]} #flag //?
RegExp('my?' + normal + [interpolation], flag);
new
创建上下文你可以单独使用 new
来创建一个新的上下文。
paul = new @name = 'paul' @age = 25 # LiveScript has real object comprehensions flip = (obj) -> new for own k, v of obj then @[v] = k
var paul, flip; paul = new function(){ this.name = 'paul'; return this.age = 25; }; flip = function(obj){ return new function(){ var k, ref$, v, own$ = {}.hasOwnProperty, results$ = []; for (k in ref$ = obj) if (own$.call(ref$, k)) { v = ref$[k]; results$.push(this[v] = k); } return results$; }; };
JavaScript 不允许动态键,因为它们不像 JSON 中那样用引号括起来。
使用 LiveScript,你可以使用圆括号来获取动态属性。
foo = 'key' bar = {(foo): 5, "dyna#foo": 6} #=> {'key': 5, 'dynakey': 6} # in destructuring {(+* .>>. 1): middle} = [1 to 7] # middle = 4
var foo, bar, ref$, middle; foo = 'key'; bar = (ref$ = {}, ref$[foo] = 5, ref$["dyna" + foo] = 6, ref$); middle = [1, 2, 3, 4, 5, 6, 7][+[1, 2, 3, 4, 5, 6, 7].length >> 1];
在解构时,你可能需要默认值。使用 LiveScript,你可以使用任何逻辑运算符、存在运算符(别名为 =
),甚至可以像在其他任何情况下一样将它们链接起来。
{username ? 'root', password || '', secure && 'https' || 'http'} = config<[ USERNAME PASSWORD SECURE ]>
var ref$, username, ref1$, password, secure; ref$ = [config['USERNAME'], config['PASSWORD'], config['SECURE']], username = (ref1$ = ref$.username) != null ? ref1$ : 'root', password = ref$.password || '', secure = ref$.secure && 'https' || 'http';
在 LiveScript 中,参数接受的不仅仅是简单的字面量。你可以分配属性,还可以做更复杂的事情,例如半自动激活。
class Person # defaults @name to [], and assigns the first element set-first-name: (@[]names.0) -> # defaults @name to [], and adds the element (* being the array's length) add-name: (@[]names[*]) -> # defaults @hair to {}, and assigns color set-hair-color: (@{}hair.color) -> p = new Person p.hair # undefined p.set-hair-color "#8b0000" p.hair.color # "#8b0000" p.names # undefined p.add-name 'George' p.add-name 'Jean' p.names # ["George", "Jean"] p.set-first-name "Paul" p.names # ["Paul", "Jean"]
var Person, p; Person = (function(){ Person.displayName = 'Person'; var prototype = Person.prototype, constructor = Person; prototype.setFirstName = function($0){ (this.names || (this.names = []))[0] = $0; }; prototype.addName = function(arg$){ var ref$; (ref$ = this.names || (this.names = []))[ref$.length] = arg$; }; prototype.setHairColor = function(color){ (this.hair || (this.hair = {})).color = color; }; function Person(){} return Person; }()); p = new Person; p.hair; p.setHairColor("#8b0000"); p.hair.color; p.names; p.addName('George'); p.addName('Jean'); p.names; p.setFirstName("Paul"); p.names;
数组和对象可以以多种方式进行切片。你可能知道 a[0 1]
,我们也看到了 a<[foo bar]>
,但你还可以做更多的事情。例如,你可以使用展开符。
posts['op' ...'replies'] = thread # even with objects extended = {...base, +extended}
var the, end, extended, ref$, slice$ = [].slice; posts['op'] = thread[0], posts['replies'] = slice$.call(thread, 1); extended = (ref$ = {}, import$(ref$, base), ref$.extended = true, ref$); function import$(obj, src){ var own = {}.hasOwnProperty; for (var key in src) if (own.call(src, key)) obj[key] = src[key]; return obj; }
低优先级反管道可以用于函数求值,不仅可以用来在没有圆括号的情况下链接参数,而且还可以做更多的事情,例如允许你使用 do。
# basic backpipe usage toCase \up <| \hello # let's say that, if we have no page, we need to create an un element # with a li element containing 1 pages.appendChild <| do node 'ul' className: 'ui-pagination' ..appendChild node 'li' innerHTML: '1'
var x$; toCase('up')('hello'); pages.appendChild((x$ = node('ul', { className: 'ui-pagination' }), x$.appendChild(node('li', { innerHTML: '1' })), x$));
Do 可以用来改变顺序或提供更多空间来编写一些复杂的表达式。
td = node 'td' class: 'informations' innerHTML: do i18n.get-translation 'informations' .format-for @user # use do and backcall promises = value: do <- $.get 'a'
var td, promises; td = node('td', { 'class': 'informations', dataType: 'info', innerHTML: i18n.getTranslation('informations').formatFor(this.user) }); promises = { value: $.get('a', function(){}) };
你经常需要将对函数的调用延迟,并保持相同的上下文和参数。你可以为此使用 thisplat。
call = -> call-instead ...
var call; call = function(){ return callInstead.apply(this, arguments); };
如果需要使用标签,可以使用块或表达式。
# labeling a function gives it a name :refresh let wait '10s' !-> console.log 'timeout !' refresh! # label a for :serie for i to 100 for j to 100 if (Math.floor Math.random! * 11) > 8 continue serie console.log "#i:#j"
var i$, i, j$, j; (function refresh(){ wait('10s', function(){ console.log('timeout !'); refresh(); }); }.call(this)); serie: for (i$ = 0; i$ <= 100; ++i$) { i = i$; for (j$ = 0; j$ <= 100; ++j$) { j = j$; if (Math.floor(Math.random() * 11) > 8) { continue serie; } console.log(i + ":" + j); } }
你可以使用 ,
表示无操作字面量。
以及展开数组或参数。
[a, b, c, ,, d] = foo [the, ..., end] = my-friend a = (, b) -> b # b is a's second argument # forces the closure's argument list to be empty test 'it works' (...) -> it # it wasn't shadowed
var a, b, c, d, the, end; a = foo[0], b = foo[1], c = foo[2], d = foo[5]; the = myFriend[0], end = myFriend[myFriend.length - 1]; a = function(arg$, b){ return b; }; test('it works', function(){ return it; });
有关 LiveScript 的更多信息,请查看 LiveScript 网站。
有关 LiveScript 和 prelude.ls 的更多信息,请 关注 @gkzahariev。
评论由 Disqus 提供支持