努力经营当下,直至未来明朗!
前言
一个人最大的痛苦来自于对自己无能的愤怒!
Hi,这里依旧是秃头宝贝儿!
本文依旧是介绍JS基础语法的,紧接着上一篇文章介绍。
四、【运算符】
JS的运算符整体和Java差不多
- 算术运算符:
+
-
*
/
%
- 赋值运算符 & 复合赋值运算符
=
+=
-=
*=
/=
%=
- 自增自减运算符
++: 自增1
- -: 自减1
也有前置和后置
- 比较运算符
<
>
<=
>=
== 比较相等(会进行 隐式类型转换)
!= (也会进行隐式类型转换)
=== 比较相等(不会进行隐式类型转换)(类型不同则直接false)
!== (不会进行隐式类型转换)
- 逻辑运算符
用于计算多个 boolean 表达式的值.
&& 与: 一假则假
|| 或: 一真则真
! 非
- 位运算
& 按位与
| 按位或
~ 按位取反
^ 按位异或
- 移位运算
<< 左移
>> 有符号右移(算术右移)
>>> 无符号右移(逻辑右移)
【补充】
-
== 和 === (能否隐式类型转换)
-
比较相等是不能用于比较两个浮点数的!!比较浮点数有风险:因为浮点数本质是遵守IEEE 754标准的,表示浮点数不一定精确,尤其是在进行算术运算的时候容易放大误差。
-
逻辑运算符
Java的与 和 或 返回的是true /false
JS的与 和 或 返回的是 第一个表达式 或 第二个表达式
【c= a || b:如果a为真就将a的值赋值给c,但是如果a为假就将b赋值给c
c= a && b:如果a为假就将a的值赋值给c,否则就是b】
(大多数使用或||、与&&其实就是为了保证其中有变量是undefined或null的时候至少还可以保证0,如下:
)
五、条件、三元、switch、循环语句
都和Java类似,就简单介绍带过。
- 条件语句:其实就是if语句,和Java类似。
- 三元表达式:
条件 ? 表达式1 : 表达式2
// 注意, 三元表达式的优先级是比较低的
- switch语句:switch、case、break、default
- 循环语句:while、continue、break、for
六、数组
【数组】:和java差别较大,主要原因就是隐式类型转换
- 和Java不同,JS的数组是可以动态变化的,JS的数组更接近与Java的ArrayList。
2.JS的数组允许里面存在不同类型的元素!!而Java则要求一个数组中无比是同一类型。
(归咎于动态类型,其他的动态类型语言如Python、PHP、Ruby…也都是类似的设定)
- 访问数组元素,通过下标方式进行操作,依旧是从0开始;如果下标超出范围读取元素, 则结果为 undefined。(Java中抛出下标访问越界异常)
(是可以修改数组元素的,还可以直接打印整个数组元素)
(发现长度length是针对整个数组的,不管是添加元素前后;赋值时可以直接指定目前不存在的下标位置赋值,中间的间隔元素是空/undefined。)
(如果给下标-1位置赋值:数组整体长度不变,且取元素是可以取到的!)
其实JS的数组不仅是个数组,还能起到map这样的效果(键值对)
所以:把数组视为一个对象,JS对象和Java对象不同,JS对象是可以在运行时随意新增属性的。JS中访问成员既可以使用. 也可以使用[ ]。对于js数组来说,[ ]里面是非负整数的时候才把这个操作视为是“操作下标”,如果是其他类型的值,就都认为是数组的自定义属性。
虽然数组有能力表示键值对,但是不建议这样使用;
js中有专门的map类型来表示键值对(ES标准引入的特性)——PHP类似,Python(叫列表)还好。
- 数组新增元素有很多种方式:最常使用的就是push方法进行尾插。使用pop进行尾删并返回该元素。
(其实push、pop就会想到Java数据结构中的栈)
- JS的数组也支持中间位置的插入和删除,还可以进行元素的替换:splice。
splice(m,n,k);
// m:表示你要取的数组的起始下标;
// n:表示你要取的数组的长度,0就表示不对原来的内容做出调整;
// k:表示要替换到数组指定范围的新的值。
所以:splice的本质功能是“替换”,取数组上的一段,把这一段替换成新的内容(替换内容跟原内容不是一一对应关系)
【如果第三个参数啥也不写就是“删除”功能】
七、函数
-
我们一般是不区分函数function和方法method的,但是如果深究的话:函数就相当于是独立的一段逻辑(不依附对象);而方法则是依赖于一个对象的(本质上就是编译器在编译的时候自动给方法前面多加了个参数,然后自动把this传进去)
——Python、Go比较明显 -
JS中,函数function不必写返回值类型(因为动态类型);形参列表的每个形参类型也不必显式的写出(一个函数可以支持多种类型的参数)
// 创建函数/函数声明/函数定义
function 函数名(形参列表) {
函数体
return 返回值;
}
// 函数调用
函数名(实参列表) // 不考虑返回值
返回值 = 函数名(实参列表) // 考虑返回值
① 正因为JS是动态类型,所以在调用函数进行传参的时候,同一个函数就允许传不同的类型;但是要保证传入的类型能够在函数内部正常使用,否则可能就会出行如NaN的情况
② 像JS这样的动态类型的语言,相当于自带了“泛型”机制,也不需要函数重载这样的语法
- JS的函数能够支持不同个数的参数,即JS并不强制要求形参和实参个数匹配!!
即:就是调用函数的时候,实参的个数可以比形参多可以比形参少,不会出现语法错误。
但是当实参比形参多的时候,多出来的实参就不能通过形参获取到了(即:此时多出来的实参无效)。
当实参比形参少的时候,多出来的形参就是undefined。
(undefined和数字相加结果就是NaN)
- 那么如何能够在任何情况下都算出正确结果呢?
① 使用逻辑或操作解决了实参<形参中形参的undefined问题
② 那么实参>形参时又该怎么办呢?
可以直接使用arguments数组解决形参和实参之间的所有个数不匹配问题(多or少),arguments这个数组中就包含了调用该方法的所有实参的值!:
① so:为啥splice方法可以支持多个变长的参数,就是通过arguments数组来完成的
② js中可以加分号,也可以不加,一般建议还是加上
-
函数表达式
在js中函数是可以像普通变量一样进行赋值的,还可以作为另一个函数的参数或返回值。所以称函数在js中是“一等公民”,即:这个函数和普通变量一样。
调用方法和普通函数一样,此处的function()其实就类似于匿名函数(lambda表达式)。
-
函数作用域:
Js里,当代码尝试访问一个变量时会首先查找当前的代码块;如果当前的代码块中没有就继续往上级代码块中查找,一直查到全局作用域(全局作用域就是
【前端面试最喜欢考:闭包(在作用域的基础上会改变变量的生命周期)和原型链】
八、 对象
【对象】:js对象类似于Java对象,但是更加简化
- js中的对象是使用{}来表示的,对象中可以有属性和方法(使用的是:以及,)。定义好对象之后可以使用.进行访问
(补充:在当前vscode下按control+shift+c 可以调出cmd)
在js中创建对象不需要类,但是js中也有类的概念(ES6版本的语法才加入的)
- 可以使用构造函数解决创建对象的冗余问题,构造函数是可以独立存在的。
(在ES6标准之后引入了class关键字,也就允许js中定义“类”了)
【重点放在使用{}创建对象的方法上,这个了解就行】
JS写构造函数一般习惯上首字母大写
注意一下:创建对象是使用 new 构造函数名(实参)
- 在JS中虽然有类的概念,但是不能提供“封装”,也不能进行“继承”(可以通过“原型链”的机制模拟实现出类似于继承的效果),更不能实现“多态”。所以,JS并不是一个“面向对象”的编程语言!(面向对象的三个特征都没有)
THINK
- 运算符(主要关注 == 和 ===能否进行隐式类型转换 + 逻辑与、逻辑或与Java的差别)
- 数组(JS数组可以动态变化、splice进行替换)
- 函数(JS中形参实参个数不一定匹配,不指定类型。使用arguments数组!)
- 函数作用域链
- 构造函数创建对象