Skip to content
On this page

运算符

运算符优先级

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

bash
.
[]
! ~ + -
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-+~

stylus
!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 运算符优先级较低,因此下面的示例可以替换为

stylus
a = 0
b = 1

!a and !b
// => false
// 解析为:(!a) and (!b)
a = 0
b = 1

!a and !b
// => false
// 解析为:(!a) and (!b)

替换为:

stylus
not a or b
// => false
// 解析为:not (a or b)
not a or b
// => false
// 解析为:not (a or b)

二元运算符

下标 []

下标运算符允许我们通过索引(从零开始)获取表达式中的值。 负索引值从表达式的最后一个元素开始。

stylus
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))。

下面是一个使用元组进行错误处理的示例(展示了这种结构的多功能性):

stylus
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() 函数并传入错误消息。

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

范围 .. ...

提供了包含(..)和排除(...)两种范围运算符,扩展为表达式:

stylus
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

加法:+ -

乘法和加法二元运算符的工作方式如预期。在单位类型类中应用类型转换,或默认为字面值。例如 5s - 2px 结果为 3s

stylus
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"

乘法:/ * %

stylus
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):

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

但下面的表达式为 14px 除以 1.5

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

这_仅_适用于 / 运算符。

简写运算符:+= -= *= /= %=

简写运算符的工作方式与其他常见语言相同。对于列表变量,第一个值将用于执行运算并覆盖列表以将其转换为单值变量。对于字符串,仅 += 作为追加函数。对于数字类型值,所有运算符都像普通数学运算一样工作。颜色值也类似。

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

int-list = 12 23 0 32
int-list %= 2
// => 12 % 2 = 0(模运算)
// => int-list = 0

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

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(模运算)
// => int-list = 0

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

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

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

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

指数:**

指数运算符:

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

相等和关系运算符:== != >= <= > <

相等运算符可用于比较单位、颜色、字符串,甚至标识符。这是一个强大的概念,即使是任意标识符(如 wahoo)也可以用作原子。函数可以返回 yesno 而不是 truefalse(尽管不建议这样做)。

stylus
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

别名:

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

真值

Stylus 中几乎所有内容都解析为 true,包括带后缀的单位。即使 0%0px 等也会解析为 true(因为在 Stylus 中,混合器或函数通常接受单位作为有效值)。

然而,0 本身在算术上是 false

长度大于 1 的表达式(或"列表")被视为真值。

true 示例:

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

false 示例:

stylus
0 
null
false
''
0 
null
false
''

逻辑运算符:&& || and or

逻辑运算符 &&|| 有别名 and / or,它们具有相同的优先级。

stylus
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

检查左操作数是否存在于右操作数表达式中。

简单示例:

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

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

5 in nums
// => false

一些未定义的标识符:

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

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

HEY in words
// => false

也适用于元组:

stylus
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

混合器中的示例用法:

stylus
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)

生成:

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

条件赋值:?= :=

条件赋值运算符 ?=(别名为 :=)允许我们定义变量而不覆盖旧值(如果存在)。这个运算符扩展为三元运算符中的 is defined 二元运算。

例如,以下是等效的:

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

使用普通 = 时,我们简单地重新赋值:

stylus
color = white
color = black

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

color
// => black

但使用 ?= 时,第二次尝试失败(因为变量已经定义):

stylus
color = white
color ?= black

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

color
// => white

实例检查:is a

Stylus 提供了一个名为 is a 的二元运算符,用于类型检查。

stylus
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() 内置函数:

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

注意:color 是唯一的特殊情况,当左操作数是 RGBAHSLA 节点时,求值为 true

变量定义:is defined

这是一个伪二元运算符,不接受右操作数,并且不求值左操作数。这允许我们检查变量是否已赋值。

stylus
foo is defined
// => false

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

#fff is defined
// => '在非变量 #fff 上进行"is defined"检查无效'
foo is defined
// => false

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

#fff is defined
// => '在非变量 #fff 上进行"is defined"检查无效'

另外,可以使用 lookup(name) 内置函数来执行此操作——或执行动态查找:

stylus
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

这个运算符很重要,因为未定义的标识符仍然是真值。例如:

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

_将_在未定义时生成以下 CSS:

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

但这将是安全的:

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

三元运算符

三元运算符的工作方式与大多数语言中的一样。它是唯一具有三个操作数的运算符(_条件_表达式、_真_表达式和_假_表达式)。

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

类型转换

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

stylus
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 进行操作:

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

另一个例子是通过添加或减去百分比来调整亮度值。要变亮,添加;要变暗,减去。

stylus
#888 + 50%
// => #c3c3c3

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

#888 - 50%
// => #444

通过添加或减去度数也可以调整色调。例如,向这个红色值添加 50deg 会得到黄色:

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

值会适当地限制。例如,我们可以将色调"旋转"180度,如果当前值是 320deg,它将解析为 140deg

我们还可以通过使用 rgb()rgba()hsl()hsla() 同时调整多个值(包括 alpha):

stylus
#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

字符串 sprintf 类似的运算符 % 可用于生成字面值,内部通过 s() 内置函数传递参数:

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

多个值应该用括号括起:

stylus
'-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%)

Released under the MIT License.