三元表达式或::我如何学会停止担心和热爱?:

大约三个月前,我决定摆脱近十年来的一个旧梦,然后重新开始编程。 我以前的编码经验是C ​​++,而我目前的学习语言是JavaScript,但是很高兴,计算机似乎仍然以早期的方式思考。 他们变得越来越瘦弱,越来越快,并且不断尝试窃取您的个人信息,就像您公司的新实习生正在谋求您的工作,并一直试图向老板流言about语。 该死,科林,我雇用了你!

在学习语言的早期,您会感到很费事,例如, “如何获取此函数以嵌套数组的形式返回数字总和?”,我们理所当然地认为很多规则和逻辑正在以编程语言悄悄地为我们工作,因此我们可以继续学习。 超过此初始阶段的令人兴奋的事情之一就是您可以返回并微调对特定细节的理解。 例如,三元运算符。 有点奇怪的语法,前几天,我意识到虽然可以识别和使用三元表达式,但我对它们的工作方式并不是100%的。 是时候深潜了!

什么是三元?

三元运算符?:是唯一接受三个操作数的JavaScript运算符。 既然我们要深入探讨,让我们定义一些术语:

运算符: 应指示一些特定的数学,关系或逻辑运算的符号以产生值

操作数: 要操作的对象或数量

对于MDN,三元表达式的语法如下:

  条件exprTexprF 

condition操作数是一个表达式,其值用作条件,而exprTexprF操作数是任何类型的表达式。 伙计,那句话中的“表达”这个词还能多出来吗? 最好调查一下!

什么是表情?

表达式是计算为某个值的任何有效代码。 让我们看一个非常简单的例子:

 让x 
x = 10

在此, x = 10是一种称为赋值表达式的表达式类型 。 它使用赋值运算符= ,它接受两个操作数并遵循以下规则:

  1. 将其左操作数的值分配给其右操作数的值
  2. 评估其正确操作数的值
  3. 是右关联的(我们将回到本章)。

因此,在我们的x = 10示例中,左侧操作数为x 。 右边的操作数是10 。 根据上述规则,我们可以观察到以下行为:

  console.log(x = 12) 
//由于规则2,预期输出:12
  console.log(x) 
//由于规则1,预计输出:12

这种表达具有所谓的副作用 。 就是说,发生的事情不是表达式计算的一部分。 在这种情况下,它是将值12分配给我们的x变量。 有趣的是, x本身就是一个没有副作用的纯表达式! 它只是评估其价值。

现在,让我们谈谈规则3:赋值表达式是右关联的。 但是,这是什么意思?

x = 10是一个非常简单的表达式,只有一个运算符。 但是,您可能知道,表达式可以具有许多运算符,甚至可以在不同位置使用相同的运算符。

  x = 12/4/2 * 3 +1 
console.log(x)
//预期输出:5.5
  x =(11-1)+(5-1)/ 2 
console.log(x)
//预期输出:12
  x + = 1-1 
console.log(x)
//预期输出:12

如果上述预期输出不是您期望的,那么您已经发现了为什么编译器(解释您的代码的程序)需要规则来处理运算符。 像…这样的规则

运算符优先级: 运算符相对于彼此的处理方式。

关联性: 如何处理相同优先级的运算符。 从左到右或从右到左。

有一个漂亮的表格,您可以在此处检查不同运算符的关联性和优先级。

现在,让我们为简单的小朋友x = 10的生活增添趣味:

 令x = 10 
令y = 5
令z = 1
console.log(x = y = z)
//预期输出:1

赋值运算符是右关联的,这意味着它们是从右到左解析的。 因此,该表达式的第一部分是y = z ,我们现在知道它的计算结果是右侧操作数z的值1 。 值1成为下一个赋值运算符的右侧操作数,其中x为左侧操作数,我们知道这也将取值为1 。 副作用是, x, yz现在也都保持值为1

这个例子非常简单,但是深入研究一个超级简单的表达式的每一部分都会产生很多有趣的信息。 作为表达式,一段代码必须求值。 它可以使用对它们的操作数执行某种运算的运算符来产生该值。 运算符具有优先级关联性的属性,这使编译器知道如何处理表达式中可能出现并最终达到该值的所有不同运算符。

什么情况

“但是三元表达式呢?!”你说。 “这就是我来这里的目的!”我要说的是,我们要到达那里! 让我们看一看三元表达式的第一部分,即条件操作数。

condition可以转换为true或false的表达式。

我们已经知道表达式必须求值。 但是,如何将该值转换为true或false? 让我们再定义一些术语:

类型强制: 将值从一种数据类型转换为另一种数据类型。

正确: 转换为布尔类型值true的值。

falsy: 转换为布尔类型值false的值。

在期望值为真或假的情况下,例如在if(...)语句或三元数的第一个操作数中, 隐式类型强制将表达式的结果值转换为真或假。 这种强制性是否遵循某些规则? 你敢打赌!

JavaScript中的false, null, undefined, 0, NaN, '', ""值包括false, null, undefined, 0, NaN, '', ""document.all

真正的价值几乎是其他一切! true, [], {} ,非空字符串和非零数字。

重要的是要注意,JavaScript逻辑上下文中发生的隐式类型强制实际上并没有重新分配原始值。

 令x = 10 
如果(x){
console.log(“嗨!”)
}
console.log(x)
  //预期输出: 
//“嗨”
// 10

在上面的示例中, x的值没有改变,但是在if语句的逻辑上下文中,它被强制并且发现为真。 因此,执行console.log("Hi!")行。

现在我们已经研究了强制类型,该条件操作数变得很清楚:由于其逻辑上下文,三元表达式中的条件操作数将根据其求值的真实性/虚假性而被强制转换为布尔值true或false。 。

全部放在一起!

我们有表达式,有逻辑上下文,它会根据真实/虚假值触发隐式类型强制。 而且,您知道?:运算符具有奇怪的优美语法,您可以根据自己的规则进行操作。 这些规则是什么?

  条件exprTexprF 
  1. 如果condition转换为true,三元表达式的计算值为exprT如果condition转换为false,则三进制表达式的计算值为exprT
  2. exprTexprF可以求值为任何类型的值。
  3. 三元运算符是右关联的。
  4. 三元表达式根据condition评估exprTexprF

这一切都很好,但是三元表达式的用例是什么? 好吧,它们非常适合分配值! 想象一下一个宠物动物园,该动物园为12岁以下的儿童提供折扣。我们可以根据年龄计算门票价格:

 功能票价格(年龄){ 
返回年龄<12岁? 5:10
}
 令价格=门票价格(8) 
console.log(价格)
//预期输出:5

上例中的条件表达式为age < 12 ,它使用比较运算符< ,如果左侧操作数的值小于右侧操作数的值,则返回true。 8实际上小于12,因此返回值5

因为这个动物园是由一个怪异的亿万富翁经营的,所以专门为名叫泰勒的顾客提供了特别的服务。 没问题:

 功能票价格(年龄,姓名){ 
返回名称===“泰勒”? 3
:<12岁? 5:10
}
 设价格= ticketPrice(15,“泰勒”) 
设price2 = ticketPrice(15,“ Meg”)
  console.log(price,price2) 
//预期输出:3、10

请记住,三元运算符是正确的关联,因此,在ticketPrice中链接的三元表达式在第一个函数调用ticketPrice(15, “Tyler")被解析为:

age < 12 ? 5 : 10 age < 12 ? 5 : 10等于10,因为age的值为1515不少于12 ,因此计算exprF表达式。

name === "Tyler" ? 3 : 10 name === "Tyler" ? 3 : 10评估为3因为这个孩子100%叫泰勒。

在第二个函数调用ticketPrice(15, "Meg") ,我们的票价最终为10 ,因为Meg为15,而100%未命名为Tyler。

奖励回合:逗号变色龙

在寻求三元满意度的过程中,我偶然发现了另一个我不知道JavaScript中不存在的奇怪运算符。 我想您可以将其称为逗号表达式,这只是一个用逗号分隔的表达式列表,就像这样……

 让y,z 
 令x =(y = 10,z = 40,“嗨!”) 
  console.log(x,y,z) 
//预期输出:“嗨!”,10、40

逗号运算符评估其每个操作数,并评估到最左边的一个。 在上面的示例中,计算y = 10 ,然后计算z = 40 ,最后是字符串"Hi!" 。 自"Hi!" 是最左边的操作数,括号内的表达式的计算结果为“Hi!” ,然后返回熟悉的赋值表达式区域。 您可能已经猜到了,逗号运算符的好处是副作用-现在我们为yz设置了值。

由于exprTexprF需要为表达式,因此该逗号运算符可用于三元组。 在下面的示例中,我们具有根据用户是否正确回答问题来更新游戏的级别和阶段的功能。 如果他们回答正确,我们要更新舞台,或者如果舞台已经是3,则更新水平。 但是,如果用户错误地回答了该问题,则我们希望减小该级,或者如果该级已经处于1,则减小该级。 如果阶段和级别均为1,则我们要为阶段和级别返回“ LOST!”。

  const updaterFunction =(答案)=>答案? 
(级别,阶段)=> {
阶段=== 3? (level ++,stage = 1)
:舞台++
返回({级别:级别,阶段:阶段})
}
:(级别,阶段)=> {
阶段> 1? (阶段 - ):
级别> 1? (等级-,阶段= 3)
:(级别=“丢失!”,阶段=“丢失!”)
返回({级别:级别,阶段:阶段})
}

看到三元运算符和逗号运算符共同发挥的强大力量! 请注意,必须将逗号表达式括在括号中,以便将它们正确解析为三进制内部的表达式。

结论:三元表达很兴奋

我一直怀疑这是真的,但是在深入研究细节并花时间认真研究这个主题之后,我对?:运算符和JavaScript有了更深入的了解。 三元表达式可以帮助您减少代码的冗长程度,而且这样做看起来还不错。 发光,你疯了?: