Skip to content

运算符(Operators)

运算符优先级

下表运算符优先级表,从最高到最低:

.
[]
! ~ + -
is defined
** * / %
+ -
... ..
<= >= < >
in
== is != is not isnt
is a
&& and || or
?:
= := ?= += -= *= /= %=
not
if unless
.
[]
! ~ + -
is defined
** * / %
+ -
... ..
<= >= < >
in
== is != is not isnt
is a
&& and || or
?:
= := ?= += -= *= /= %=
not
if unless

一元运算符

以下一元运算符可用, !, not, -, +, and ~.

!0
// => true

!!0
// => false

!1
// => false

!!5px
// => true

-5px
// => -5px

--5px
// => 5px

not true
// => false

not not true
// => true
!0
// => true

!!0
// => false

!1
// => false

!!5px
// => true

-5px
// => -5px

--5px
// => 5px

not true
// => false

not not true
// => true

逻辑运算符not的优先级较低,因此,下面这个例子可以被替换:

a = 0
b = 1

!a and !b
// => false
// parsed as: (!a) and (!b)
a = 0
b = 1

!a and !b
// => false
// parsed as: (!a) and (!b)

为:

not a or b
// => false
// parsed as: not (a or b)
not a or b
// => false
// parsed as: not (a or b)

二元运算符

下标运算符([])

下标运算符允许我们通过索引(从零开始)在表达式中获取值。

负索引值从表达式中的最后一个元素开始。

list = 1 2 3
list[0]
// => 1

list[-1]
// => 3
list = 1 2 3
list[0]
// => 1

list[-1]
// => 3

括号表达式可以充当元组(如(15px 5px), (1, 2, 3))。

下面这个例子使用错误处理的元组(并展示了该结构的多功能性):

add(a, b)
  if a is a 'unit' and b is a 'unit'
    a + b
  else
    (error 'a and b must be units!')

body
  padding add(1,'5')
  // => padding: error "a and b must be units";

  padding add(1,'5')[0]
  // => padding: error;

  padding add(1,'5')[0] == error
  // => padding: true;

  padding add(1,'5')[1]
  // => padding: "a and b must be units";
add(a, b)
  if a is a 'unit' and b is a 'unit'
    a + b
  else
    (error 'a and b must be units!')

body
  padding add(1,'5')
  // => padding: error "a and b must be units";

  padding add(1,'5')[0]
  // => padding: error;

  padding add(1,'5')[0] == error
  // => padding: true;

  padding add(1,'5')[1]
  // => padding: "a and b must be units";

这儿有个更复杂的例子。现在,我们调用内置的error()函数,当标识符(第一个值)等于error的时候返回错误信息。

if (val = add(1,'5'))[0] == error
  error(val[1])
if (val = add(1,'5'))[0] == error
  error(val[1])

范围运算符(.. ...)

同时提供包含界线操作符(..)和范围操作符(...),见下表达式:

1..5
// => 1 2 3 4 5

1...5
// => 1 2 3 4

5..1
// => 5 4 3 2 1
1..5
// => 1 2 3 4 5

1...5
// => 1 2 3 4

5..1
// => 5 4 3 2 1

### 加减运算符(+ -)

Multiplicative and additive binary operators work as expected. Type conversion is applied within unit type classes, or default to the literal value. For example 5s - 2px results in 3s.

15px - 5px
// => 10px

5 - 2
// => 3

5in - 50mm
// => 3.031in

5s - 1000ms
// => 4s

20mm + 4in
// => 121.6mm

"foo " + "bar"
// => "foo bar"

"num " + 15
// => "num 15"
15px - 5px
// => 10px

5 - 2
// => 3

5in - 50mm
// => 3.031in

5s - 1000ms
// => 4s

20mm + 4in
// => 121.6mm

"foo " + "bar"
// => "foo bar"

"num " + 15
// => "num 15"

乘除运算符(/ * %)

2000ms + (1s * 2)
// => 4000ms

5s / 2
// => 2.5s

4 % 2
// => 0
2000ms + (1s * 2)
// => 4000ms

5s / 2
// => 2.5s

4 % 2
// => 0

当在属性值内使用/时候,你必须用括号包住。否则/会根据其字面意思处理(支持CSS的line-height)。

font: 14px/1.5;
font: 14px/1.5;

但是,下面这个却等同于14px ÷ 1.5:

font: (14px/1.5);
font: (14px/1.5);

只有/操作符的时候需要这样。

简略赋值操作符(+= -= *= /= %=)

Shorthand operators works like other common language. With list variable, the first value will be use to execute the operators and overwrite the list to turn it to a single-value variable. With string, node values only += works as an appending function. With number type value, all operators work exactly like a normal math. Similar for color value.

n = 12
n += 8
// => n = 20

int-list = 12 23 0 32
int-list %= 2
// => 12 % 2 = 0 (mod operator)
// => int-list = 0

mixed-list = node 23 'str'
mixed-list %= 2
// => error

mixed-list = node 23 'str' #2e7
mixed-list += 2
// => mixed-list = node2

s = 'str'
s += 2
// => s = 'str2'

c = #0e0
c -= #0e0
// => c = #000
n = 12
n += 8
// => n = 20

int-list = 12 23 0 32
int-list %= 2
// => 12 % 2 = 0 (mod operator)
// => int-list = 0

mixed-list = node 23 'str'
mixed-list %= 2
// => error

mixed-list = node 23 'str' #2e7
mixed-list += 2
// => mixed-list = node2

s = 'str'
s += 2
// => s = 'str2'

c = #0e0
c -= #0e0
// => c = #000

指数运算符(**)

指数运算符:

2 ** 8
// => 256
2 ** 8
// => 256

相等与关系运算(== != >= <= > <)

相等运算符可以被用来等同单位、颜色、字符串甚至标识符。这是个强大的概念,甚至任意的标识符(例如wahoo)可以作为原子般使用。函数可以返回yesno代替truefalse(虽然不建议)。

5 == 5
// => true

10 > 5
// => true

#fff == #fff
// => true

true == false
// => false

wahoo == yay
// => false

wahoo == wahoo
// => true

"test" == "test"
// => true

true is true
// => true

'hey' is not 'bye'
// => true

'hey' isnt 'bye'
// => true

(foo bar) == (foo bar)
// => true

(1 2 3) == (1 2 3)
// => true

(1 2 3) == (1 1 3)
// => false
5 == 5
// => true

10 > 5
// => true

#fff == #fff
// => true

true == false
// => false

wahoo == yay
// => false

wahoo == wahoo
// => true

"test" == "test"
// => true

true is true
// => true

'hey' is not 'bye'
// => true

'hey' isnt 'bye'
// => true

(foo bar) == (foo bar)
// => true

(1 2 3) == (1 2 3)
// => true

(1 2 3) == (1 1 3)
// => false

只有精确值才匹配,例如,0 == falsenull == false均返回false.

别名:

==    is
!=    is not
!=    isnt
==    is
!=    is not
!=    isnt

真与假

Stylus近乎一切都是true, 包括有后缀的单位,甚至0%, 0px等都被认作true(because it's common in Stylus for mixins or functions to accept units as valid)。

不过,0在算术上本身是false.

表达式(或“列表”)长度大于1被认为是真.

true示例:

      0%
      0px
      1px
      -1
      -1px
      hey
      'hey'
      (0 0 0)
      ('' '')
      0%
      0px
      1px
      -1
      -1px
      hey
      'hey'
      (0 0 0)
      ('' '')

false示例:

0
null
false
''
0
null
false
''

逻辑运算符(&& || and or)

逻辑操作符&&||的别名是and / or。它们的优先级相同。

5 && 3
// => 3

0 || 5
// => 5

0 && 5
// => 0

#fff is a 'rgba' and 15 is a 'unit'
// => true
5 && 3
// => 3

0 || 5
// => 5

0 && 5
// => 0

#fff is a 'rgba' and 15 is a 'unit'
// => true

存在操作符(in)

检查左边内容是否在右边的表达式中。

简单例子:

nums = 1 2 3
1 in nums
// => true

5 in nums
// => false
nums = 1 2 3
1 in nums
// => true

5 in nums
// => false

一些未定义标识符:

words = foo bar baz
bar in words
// => true

HEY in words
// => false
words = foo bar baz
bar in words
// => true

HEY in words
// => false

元组同样适用:

vals = (error 'one') (error 'two')
error in vals
// => false

(error 'one') in vals
// => true

(error 'two') in vals
// => true

(error 'something') in vals
// => false
vals = (error 'one') (error 'two')
error in vals
// => false

(error 'one') in vals
// => true

(error 'two') in vals
// => true

(error 'something') in vals
// => false

混合书写适用例子:

pad(types = padding, n = 5px)
  if padding in types
    padding n
  if margin in types
    margin n

body
  pad()

body
  pad(margin)

body
  pad(padding margin, 10px)
pad(types = padding, n = 5px)
  if padding in types
    padding n
  if margin in types
    margin n

body
  pad()

body
  pad(margin)

body
  pad(padding margin, 10px)

等同与:

body {
  padding: 5px;
}
body {
  margin: 5px;
}
body {
  padding: 10px;
  margin: 10px;
}
body {
  padding: 5px;
}
body {
  margin: 5px;
}
body {
  padding: 10px;
  margin: 10px;
}

条件赋值(?= :=)

条件赋值操作符?=(别名:=)让我们无需破坏旧值(如果存在)定义变量。该操作符可以扩展成三元内is defined的二元操作。

例如,下面这些都是相同的:

color := white
color ?= white
color = color is defined ? color : white
color := white
color ?= white
color = color is defined ? color : white

如果我们使用等号=, 就只是简单地赋值

color = white
color = black

color
// => black
color = white
color = black

color
// => black

但当使用?=,第二个相当就嗝屁了(因为变量已经定义了):

color = white
color ?= black

color
// => white
color = white
color ?= black

color
// => white

实例检查(is a)

Stylus提供一个二元运算符叫做is a, 用做类型检查。

15 is a 'unit'
// => true

#fff is a 'rgba'
// => true

15 is a 'rgba'
// => false
15 is a 'unit'
// => true

#fff is a 'rgba'
// => true

15 is a 'rgba'
// => false

另外,我们可以使用type()这个内置函数:

type(#fff) == 'rgba'
// => true
type(#fff) == 'rgba'
// => true

注意: color是唯一的特殊情况,当左边是RGBA或者HSLA节点时,都为true.

变量定义检查(is defined)

此伪二元运算符右边空荡荡,左边无计算。用来检查变量是否已经分配了值。

foo is defined
// => false

foo = 15px
foo is defined
// => true

#fff is defined
// => 'invalid "is defined" check on non-variable #fff'
foo is defined
// => false

foo = 15px
foo is defined
// => true

#fff is defined
// => 'invalid "is defined" check on non-variable #fff'

另外,我们可以使用内置lookup(name)方法做这个活动态查找:

name = 'blue'
lookup('light-' + name)
// => null

light-blue = #80e2e9
lookup('light-' + name)
// => #80e2e9
name = 'blue'
lookup('light-' + name)
// => null

light-blue = #80e2e9
lookup('light-' + name)
// => #80e2e9

该操作符必不可少,因为一个未定义的标识符仍是真值。如:

body
  if ohnoes
    padding 5px
body
  if ohnoes
    padding 5px

当未定义的时候,产生的是下面的CSS

body {
  padding: 5px;
}
body {
  padding: 5px;
}

显然,这不是我们想要的,如下书写就安全了:

body
  if ohnoes is defined
    padding 5px
body
  if ohnoes is defined
    padding 5px

三元运算符

三元运算符的运作正如大部分语言里面的那样。三个操作对象的操作符(条件表达式、真表达式以及假表达式)。

num = 15
num ? unit(num, 'px') : 20px
// => 15px
num = 15
num ? unit(num, 'px') : 20px
// => 15px

Casting

作为替代简洁的内置unit()函数,语法(expr) unit可用来强制后缀。

body
  n = 5
  foo: (n)em
  foo: (n)%
  foo: (n + 5)%
  foo: (n * 5)px
  foo: unit(n + 5, '%')
  foo: unit(5 + 180 / 2, deg)
body
  n = 5
  foo: (n)em
  foo: (n)%
  foo: (n + 5)%
  foo: (n * 5)px
  foo: unit(n + 5, '%')
  foo: unit(5 + 180 / 2, deg)

颜色运算符

颜色操作提供了一个简洁,富有表现力的方式来改变其组成。例如,我们可以对每个RGB:

#0e0 + #0e0
// => #0f0
#0e0 + #0e0
// => #0f0

另外一个例子是通过增加或减少百分值调整颜色亮度。颜色亮,加;暗,则减:

#888 + 50%
// => #c3c3c3

#888 - 50%
// => #444
#888 + 50%
// => #c3c3c3

#888 - 50%
// => #444

我们也可以通过增加或减去色度调整色调。例如,红色增加65deg就变成了黄色:

#f00 + 50deg
// => #ffd500
#f00 + 50deg
// => #ffd500

值适当固定。例如,我们可以"旋转"180度的色调,如果目前的值是320deg, 将变成140deg.

我们也可能一次调整几个值(包括alpha),通过使用rgb(), rgba(), hsl(), 和 hsla():

#f00 - rgba(100,0,0,0.5)
// => rgba(155,0,0,0.5)
#f00 - rgba(100,0,0,0.5)
// => rgba(155,0,0,0.5)

格式化字符串(Sprintf)

格式化字符串模样的字符串%可以用来生成字面量值,通过传参给内置s()方法:

'X::Microsoft::Crap(%s)' % #fc0
// => X::Microsoft::Crap(#fc0)
'X::Microsoft::Crap(%s)' % #fc0
// => X::Microsoft::Crap(#fc0)

多个值需要括起来:

'-webkit-gradient(%s, %s, %s)' % (linear (0 0) (0 100%))
// => -webkit-gradient(linear, 0 0, 0 100%)
'-webkit-gradient(%s, %s, %s)' % (linear (0 0) (0 100%))
// => -webkit-gradient(linear, 0 0, 0 100%)