草庐IT

JavaScript快速入门-04-运算符

Surpassme 2023-03-28 原文

4 运算符

4.1 算术运算符

4.1.1 概述

    JavaScript 提供的算术运算符如下所示:

类型 符号 示例
加法运算符 + a+b
减法运算符 - a-b
乘法运算符 * a*b
除法运算符 / a/b
余数运算符 % a%b
自增运算符 ++ ++a/a++
自减运算符 -- --a/a--
指数运算符 ** a**b

4.1.2 加法运算符

    加法运算符是最常见的运算符,常用于求两个数值的和。

4.1.2.1 基本规则

  • 1.数值相加

    如果是进行数值的相加,则为求和

1+2 // 3
  • 2.布尔类型相加
        在JavaScript中,也允许非数值相加,例如与布尔类型的相加。

在与布尔类型相加时,则会自动将布尔类型转换为数值,然后再进行相加。true会转换为1,false会转换为0

true+true // 2
3+true // 4
false+false  // 0
  • 3.字符串相加

    如果是与字符串类型的值相加,则会进行字符串的连接,并返回一个新的字符串。如果其中一个不是字符串,则会自动转换为字符串再进行连接。

"I Love"+" Surpass"  // 'I Love Surpass'
2+"-28" // '2-28'
true+" boolean" // 'true boolean'

    加法运算符是在运行时决定,到底是执行相加,还是执行连接,即运算子不同,执行不同的语法行为,也称之为重载。因加法运算符存在重载行为,可能执行不同的运算,使用的时候需要特别注意。

"2020"+4+3 // '202043'
2020+4+"3" // '20243'

上面代码中,因为是从左到右进行运算,字符串的位置不一样,则会出现不一样的结果

    除了加法运算符,其他算术运算符(如减法、除法、乘法、余数等)则不会发生重载。其规则:所有运算子一律先转换为数值,再进行相应的算术运算

100-"88" // 12
100*"88" // 8800
100/"88" // 1.1363636363636365
100%"88" // 12

4.1.2.2 对象相加

    如果运算子是对象,必须先转换为原始类型的值,再进行相加

var obj={name:"surpass"};
console.log(obj+8) // [object Object]8

上面代码中,对象obj转换成原始类型的值是[object Object],再与8相加就得到结果[object Object]8

    对象转换成原始类型的值,规则如下所示

  • 1.首先自动调用对象的valueOf()方法,再调用对象的toString()方法
var obj={name:"surpass"};
console.log(obj.valueOf()); // { name: 'surpass' }
console.log(obj.valueOf().toString()); // [object Object]

一般来说,对象的valueOf()方法总是返回对象自身,再调用对象的toString()方法,将其转换为字符串。在知道这个规则后,我们可自定义valueOf()和toString()方法,得到想到的结果。

var obj = { 
    valueOf: function () {
         return 28; 
        } 
    };
console.log(obj + 8); // 36

上述代码由于直接定义了obj的valueOf()方法返回28,再与8相加得到结果36。由于valueOf()方法直接返回一个原始类型的值,所以不再调用toString()方法。我们也可以自定义toString()方法,如下所示:

var obj = { 
    toString: function () {
         return "Surpass "; 
        } 
    };
console.log(obj + 8); // Surpass 8

    但这里有一个特例,如果运算子是一个Date的对象实例,则优先执行toString()方法,如下所示:

var obj=new Date();
obj.valueOf=function(){return 28;};
obj.toString=function(){return "Surpass "};
console.log(obj+100);  // Surpass 100

4.1.3 余数运算符

    余数运算符主要用于计算两个数的余数。

15%5 // 0
15%7 // 1

    需要注意的是,运算结果的正负号是由第一个运算子的正负号决定。

-15%5 // -0
-15%7 // -1

4.1.4 自增/自减运算符

    自增和自减运算符,是一元运算符,只需要一个运算子。其作用是将运算子首先转换为数值,然后再加1或减1,会修改原始变量。

var a=100;
var b=88;
var c=99;
var d=66;
console.log("a++ value is:",a++);
console.log("a value is:",a);
console.log("b value is:",b);
console.log("++b value is:",++b);
console.log("c-- value is:",c--);
console.log("c value is:",c);
console.log("d value is:",d);
console.log("--d value is:",--d);

输出结果如下所示:

a++ value is: 100
a value is: 101
b value is: 88
++b value is: 89
c-- value is: 99
c value is: 98
d value is: 66
--d value is: 65

    通过以下结果,可以总结出以下结论

  • 自增和自减运算符在变量前面,先进行自增或自减操作后,再输出其值
  • 自增或自减运算符在变量之后,先输出其值,再进行自增或自减操作

4.1.4 指数运算符

    指数运算符通常用于一个数的n次幂。

2**5 // 32

    这里有一个注意事项,指数运算符是右结合,而不是左结合,即多个指数运算符连用时,先进行最右边的计算

2**3**2  // 512
2**4**2**1 // 65536

4.2 比较运算符

4.2.1 概述

    比较运算符一般常用于比较两个值的大小,然后返回一个布尔值,用于表示是否满足条件。JavaScript 提供的比较运算符如下所示:

类型 符号 示例
大于运算符 > a>b
大于等于运算符 >= a>=b
小于运算符 < a<b
小于等于运算符 <= a<=b
相等运算符 == a==b
严格相等运算符 === a===b
不相等运算符 != a!=b
严格不相等运算符 !== a!==b

    以上比较运算符可以分为相等比较运算符不相等运算符。两者的比较的规则是不一样的。对于不相等的比较规则为两个运算子都为字符串,按照字典顺序比较(实际上是比较Unicode码点),如果不是,则转换为数值,再比较数值大小

4.2.2 不相等运算符

4.2.2.1 字符串比较

    在JavaScript中比较字符串时,会首先比较首字符的Unicode码点。如果相等,再比较第二个字符的Unicode码点,以此类推。

"Surpass" < "surpass" // true

    上面代码中s的码点(115)大于S的码点(83),所以返回true,因为汉字也有Unicode码点,所以汉字也可以进行比较的,如下所示:

"上" > "海" // false

上面代码中,上的码点为:19978,海的码点为:28023,所以返回为false

4.2.2.2 非字符串比较

    因为参与比较的运算子一般都有2个,则可以分为两种情况:

1.原始类型值

    如果两个运算子都是原始类型值,则先转换为数值再进行比较。如下所示:

5 > "4" // true,会先将"4"转换为数值4,再参与比较
true > false // true ,会将true和false转换为数值,分别对应为1和0,再参与比较
5 > false // true

    这里有一个特殊情况,就是与NaN进行比较,任何值与NaN使用不相等运算符比较,均返回false

1 > NaN // false
"abc" >= NaN // false
NaN == NaN // false

2.对象

    如果运算子是对象,则会转换为原始类型值,再进行比较。

对象转换为原始类型值,则先调用对象的valueOf()方法;如果返回值仍然为对象,则再调用toString()方法

var number=10;
var testArray=[8];
console.log("testArray toString value is:",testArray.valueOf().toString()); // testArray toString value is: 8
console.log("testArray > number",testArray>number); // testArray > number false

var objA={"name":"Surpass"};
var objB={"age":28};
console.log("objA >= objB",objA >= objB); // objA >= objB true 

4.2.3 严格比较运算符

    严格比较运算符包括严格相等运算符严格不相等运算符

4.2.3.1 严格相等运算符

    在JavaScript中提供两种相等运算符=====,两者主要区别如下所示:

  • ==是比较两个值是否相等,即两边类型允许不一致
  • ===是比较两个值是否为同一个值,即要求两边类型必须一致,否则则返回false

1.不同类型值

1=="1" // true
1==="1" // false
true == 1 // true
true === 1 // false

2.同类型的原始类型值

2==0x2  // true
2===0x2 // true

NaN与任何值都不相等

NaN == NaN   // false
NaN === NaN  // false

3.复合类型

    两个复合类型(对象、数组、函数)的数据比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个内存地址

let objA={};
let objB={};
let objC=objA;
console.log("objA === objB ?",objA === objB);
console.log("objA === objC ?",objA === objC);

let funA=function(){};
let funB=function(){};
let funC=funA;
console.log("funA === funB ?",funA === funB);
console.log("funA === funC ?",funA === funC);

输出结果如下所示:

objA === objB ? false
objA === objC ? true
funA === funB ? false
funA === funC ? true

对于两个对象的比较,严格相等运算比较的是其内存地址,而大于或小于运算符比较的是值

4.undefined和null

    undefined和null与自身严格相等

undefined === undefined // true
null === null // true

4.2.3.2 严格不相等运算符

    严格不相等运算符与严格相等运算符类似,主要用于判断两个是否严格不相等。

1 !== "1" // true

4.2.4 相等运算符

    相等运算符常用于比较两个运算子是否相等,通常分为以下几种情况:

  • 如果是相同类型的数据进行比较时,则等同于严格相等运算符
  • 如果是不同类型的数据时,则会先将两边数据进行转换,再使用严格相等运算符进行比较

4.2.4.1 原始类型值

    原始类型值会先转换成数值再进行比较,如下所示:

1 == true // true
2 == false // false
"true" == true // false 等同于Number("true")  = NaN
"" == false // true 等同于Number("") = 0

4.2.4.2 对象与原始类型值

    对象与原始类型值比较时,对象在转换为原始类型值再参与比较,即先调用对象的valueOf()方法,再调用toString()方法后,再参与比较。

[1] == 1  // true
[1,2,3] == "1,2,3" // true
[1] == true // true

    以上代码中,如果是对象参与相等判断时,JavaScript会调用对象的valueOf()方法,由于返回的还是一个对象,则会再调用toString()方法,得到字符串后,再基于规则进行比较,我们来看一个比较直观的例子,如下所示:

var obj={
    valueOf:function(){
        console.log("call valueOf method");
        return obj;
    },
    toString:function(){
        console.log("call toString method");
        return "Surpass";
    }
};
var myName="Surpass";
console.log("myName == obj result is: ", myName == obj);

输出结果如下所示:

call valueOf method
call toString method
myName == obj result is:  true

4.2.4.3 undefined 和 null

    undefined和null只有与自身比较,或者相互比较时,才会返回true;与其他类型的值比较时,结果都为false,如下所示:

// 与自身或相互比较
undefined == undefined // true
null == null // true
undefined == null // true
// 与其他类型比较
false == null // false
false == undefined  // false
2 == null // false
2 == undefined // false

4.3 布尔运算符

4.3.1 概述

    布尔运算符一般用于将表达式值转换为布尔值,主要包括以下几种:

  • 与运算符:&&
  • 或运算符:||
  • 非运算符:!

4.3.2 与运算符

    &&运算符常用于多个表达式的求值。其运算规则如下所示:

  • 所有表达式的值均为true时,返回true
  • 如果第一个表达式值为false时,则直接返回false
  • 如果第一个运算子的布尔值为true,则返回第二运算子的值(注意这里不是布尔值),如果第一个运算子的布尔值为false,则直接返回第一个运算子的值,且不再对第二个运算子求值
true && true // true
true && 3>2 && false // false
"t" && "f" // f
"" && "Surpass" // ""

    与运算符还是一种短路运算符,即如果第一个运算子决定了结果,则不会对后续运算子进行操作求值。示例如下所示:

var found=false;
var result=(found && age); // 不会报错,因为第一个运算子是false
console.log("result is: ",result); // 执行打印

var found=true;
var result=(found && age); // 会报错,因为age没有事先声明
console.log("result is:",result); // 不会执行

    利用这个短路特性,可以取代if结构,如下所示:

function doSomething(){
    console.log("call doSomething method");
}

var flag=true;
if (flag){
    console.log("call if");
    doSomething();
}

flag && doSomething(); //利用短路特性

输出结果如下所示:

call if
call doSomething method
call doSomething method

    对于特殊字符的处理逻辑如下所示:

  • 如果有一个运算子是null,返回null
  • 如果有一个运算子是NaN,返回NaN
  • 如果有一个运算子是undefined,返回undefined

4.3.3 或运算符

    || 也可以用于多个表达式求值。,其运算规则如下所示:

  • 所有表达式中,只有一个表达式值为true,则为true
  • 如果第一个表达式为true,则直接返回true
  • 如果第一个运算子的布尔值为true,则返回第一个运算子的值,且不再对第二个运算子求值,如果第一个运算子的布尔值为false,则返回第二个运算子的值
"true" || "true" //  true
true || 3 > 2 && false  //  true
"t" || "f" // t
"" || "Surpass"
"true" || 2>3 || false  // true

短路规则同样也适用于或运算符

    对于特殊字符的处理逻辑如下所示:

  • 如果两个运算子都是null,返回null
  • 如果两个运算子都是NaN,返回NaN
  • 如果两个运算子都是undefined,返回undefined

4.3.4 非运算符

    非运算符常用于将一个布尔值变为其反值,即true变为false,false变为true。

!true // false
!false // true

    对于非布尔值,非运算符会将其转换为布尔值,以下6个值进行非运算后为true,其他值均为false

  • undefined
  • null
  • false
  • 0
  • NaN
  • 空字符串("")

4.4 其他运算符

4.4.1 逗号运算符

    逗号运算符可以用来在一条语句中执行多个操作,如下所示:

let a=1,b=2,c=3;
console.log("a value is;"+a+"\nb value is:"+b+"\nc value is:"+c);

输出结果如下所示:

a value is;1
b value is:2
c value is:3

4.4.2 条件运算符

    条件运算符语法格式如下所示:

variable = boolean_expression ? true_value : false_value;

    variable最终值取决于boolean_expression的值,如果boolean_expression为true,则赋值true_value,否则,则赋值false_value,示例如下所示:

let a=100,b=123;
let result=(a>b)?"a大于b":"a小于b";
console.log("result is:",result) // result is: a小于b

原文地址:https://www.jianshu.com/p/64391eb825fc

本文同步在微信订阅号上发布,如各位小伙伴们喜欢我的文章,也可以关注我的微信订阅号:woaitest,或扫描下面的二维码添加关注:

有关JavaScript快速入门-04-运算符的更多相关文章

  1. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  2. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  3. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  4. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  5. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  6. ES基础入门 - 2

    ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear

  7. ruby - 带括号和 splat 运算符的并行赋值 - 2

    我明白了:x,(y,z)=1,*[2,3]x#=>1y#=>2z#=>nil我想知道为什么z的值为nil。 最佳答案 x,(y,z)=1,*[2,3]右侧的splat*是内联扩展的,所以它等同于:x,(y,z)=1,2,3左边带括号的列表被视为嵌套赋值,所以它等价于:x=1y,z=23被丢弃,而z被分配给nil。 关于ruby-带括号和splat运算符的并行赋值,我们在StackOverflow上找到一个类似的问题: https://stackoverflow

  8. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  9. ruby - 定义自定义 Ruby 运算符 - 2

    问题是:除了在“OperatorExpressions”?例如:1%!2 最佳答案 是的,可以创建自定义运算符,但有一些注意事项。Ruby本身并不直接支持它,但是superatorsgem做了一个巧妙的把戏,将运算符链接在一起。这允许您创建自己的运算符,但有一些限制:$geminstallsuperators19然后:require'superators19'classArraysuperator"%~"do|operand|"#{self}percent-tilde#{operand}"endendputs[1]%~[2]#Out

  10. ruby - 在 Ubuntu 14.04 中使用 Curl 安装 RVM 时出错 - 2

    我试图在Ubuntu14.04中使用Curl安装RVM。我运行了以下命令:\curl-sSLhttps://get.rvm.io|bash-sstable出现如下错误:curl:(7)Failedtoconnecttoget.rvm.ioport80:Networkisunreachable非常感谢解决此问题的任何帮助。谢谢 最佳答案 在执行curl之前尝试这个:echoipv4>>~/.curlrc 关于ruby-在Ubuntu14.04中使用Curl安装RVM时出错,我们在Stack

随机推荐