JS基础(三、数组、运算符)

一、数组

按次序排列的一组值。每个值的位置都有编号(从0开始),整个数组用方括号表示。

任何类型的数据,都可以放入数组。

如果数组的元素还是数组,就形成了多维数组

本质上,数组属于一种特殊的对象。typeof运算符会返回数组的类型是object。

特殊性:键名是按次序排列的一组整数(0,1,2…)

var arr = ['a', 'b', 'c'];

Object.keys(arr)
// ["0", "1", "2"]

对象的键名一律为字符串
可以用数值读取,是因为非字符串的键名会被转为字符串。

var arr = ['a', 'b', 'c'];

arr['0'] // 'a'
arr[0] // 'a'

a[1.00] = 6;
a[1] // 6

一个值总是先转成字符串,再作为键名进行赋值
arr.0的写法不合法,因为单独的数值不能作为标识符。所以,数组成员只能用方括号arr[0]表示(方括号是运算符,可以接受数值)。

length属性
返回数组的成员数量。

数组成员最多只有 4294967295 个(232 - 1)个

等于键名中的最大整数加上1

1.1in 运算符

检查某个键名是否存在的运算符in,适用于对象,也适用于数组。
for…in循环不仅可以遍历对象,也可以遍历数组,毕竟数组只是一种特殊对象,不仅会遍历数组所有的数字键,还会遍历非数字键。

几种遍历方式:for while foreach

var a = [1, 2, 3];
a.foo = true;
for (var key in a) {
  console.log(key);
}
// for循环
for(var i = 0; i < a.length; i++) {
  console.log(a[i]);
}

// while循环
var i = 0;
while (i < a.length) {
  console.log(a[i]);
  i++;
}
var colors = ['red', 'green', 'blue'];
colors.forEach(function (color) {
  console.log(color);
});

1.2数组的空位

当数组的某个位置是空元素,即两个逗号之间没有任何值,我们称该数组存在空位(hole)
如果最后一个元素后面有逗号,并不会产生空位。
使用delete命令删除一个数组成员,会形成空位,并且不会影响length属性,length属性不过滤空位。

数组的某个位置是空位,与某个位置是undefined,是不一样的。如果是空位,使用数组的forEach方法、for…in结构、以及Object.keys方法进行遍历,空位都会被跳过
如果某个位置是undefined,遍历的时候就不会被跳过。

1.3类似数组的对象

如果一个对象的所有键名都是正整数或零,并且有length属性,那么这个对象就很像数组,语法上称为“类似数组的对象”(array-like object)。

var obj = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
};

典型的“类似数组的对象”是函数的arguments对象,以及大多数 DOM 元素集,还有字符串。
数组的slice方法可以将“类似数组的对象”变成真正的数组。

var arr = Array.prototype.slice.call(arrayLike);

通过call()把数组的方法放到对象上面,可以使用数组的方法。

Array.prototype.forEach.call(arrayLike, print);
字符串也是类似数组的对象,所以也可以用Array.prototype.forEach.call遍历。

Array.prototype.forEach.call('abc', function (chr) {
  console.log(chr);
});
// a
// b
// c 

最好先将“类似数组的对象”转为真正的数组

2、运算符

2.1、算术运算符

加法运算符:x + y
减法运算符: x - y
乘法运算符: x * y
除法运算符:x / y
指数运算符:x ** y
余数运算符:x % y
自增运算符:++x 或者 x++
自减运算符:–x 或者 x–
数值运算符: +x
负数值运算符:-x

JavaScript 允许非数值的相加。
布尔值都会自动转成数值,然后再相加。
如果是两个字符串相加,这时加法运算符会变成连接运算符\如果一个运算子是字符串,另一个运算子是非字符串,这时非字符串会转成字符串,再连接在一起。

加法运算符是在运行时决定,到底是执行相加,还是执行连接。也就是说,运算子的不同,导致了不同的语法行为,这种现象称为“重载”(overload)

'3' + 4 + 5 // "345"
3 + 4 + '5' // "75"

其他算术运算符(比如减法、除法和乘法)都不会发生重载。它们的规则是:所有运算子一律转为数值,再进行相应的数学运算。

2.2、对象的相加

对象,必须先转成原始类型的值
obj转成原始类型的值是[object Object]

规则如下
1、调用对象的valueOf方法
2、调用对象的toString方法
对象的toString方法默认返回[object Object],

自己定义valueOf方法或toString方法,可以得到想要的结果。

特例,如果运算子是一个Date对象的实例,那么会优先执行toString方法。

2.3、余数运算符

余数运算符(%)返回前一个运算子被后一个运算子除,所得的余数。

运算结果的正负号由第一个运算子的正负号决定。
为了得到负数的正确余数值,可以先使用绝对值函数。

function isOdd(n) {
  return Math.abs(n % 2) === 1;
}

可以用于浮点数的运算。但是,由于浮点数不是精确的值,无法得到完全准确的结果。

2.4、自增和自减运算符

运算之后,变量的值发生变化,这种效应叫做运算的副作用(side effect)。自增和自减运算符是仅有的两个具有副作用的运算符

放在变量之后,会先返回变量操作前的值,再进行自增/自减操作;放在变量之前,会先进行自增/自减操作,再返回变量操作后的值

2.5、数值运算符,负数值运算符

一元运算符

数值运算符的作用在于可以将任何值转为数值(与Number函数的作用相同)。

+true // 1
+[] // 0
+{} // NaN

负数值运算符(-),也同样具有将一个值转为数值的功能,只不过得到的值正负相反。连用两个负数值运算符,等同于数值运算符。
会返回一个新的值,而不会改变原始变量的值

2.6、指数运算符

右结合,而不是左结合。即多个指数运算符连用时,先进行最右边的计算

// 相当于 2 ** (3 ** 2)
2 ** 3 ** 2
// 512

2.7、赋值运算符

(=)
与其他运算符结合,形成变体。下面是与算术运算符的结合。

// 将 1 赋值给变量 x
var x = 1;
// 等同于 x = x + y
x += y

// 等同于 x = x - y
x -= y

与位运算符的结合

3、比较运算符

用于比较两个值的大小,然后返回一个布尔值,表示是否满足指定的条件

大于运算符
< 小于运算符
<= 小于或等于运算符
= 大于或等于运算符
== 相等运算符
=== 严格相等运算符
!= 不相等运算符
!== 严格不相等运算符

对于非相等的比较,算法是先看两个运算子是否都是字符串,如果是的,就按照字典顺序比较(实际上是比较 Unicode 码点);否则,将两个运算子都转成数值,再比较数值的大小。

3.1非相等运算符

字符串的比较

按照字典顺序进行比较。

'cat' > 'dog' // false
'cat' > 'catalog' // false

首先比较首字符的 Unicode 码点。如果相等,再比较第二个字符的 Unicode 码点,以此类推
汉字也可以比较。

非字符串的比较
如果两个运算子之中,至少有一个不是字符串,需要分成以下两种情况。

(1)原始类型值
如果两个运算子都是原始类型的值,先转成数值再比较

任何值(包括NaN本身)与NaN使用非相等运算符进行比较,返回的都是false。
(2)对象

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

先调用valueOf方法;如果返回的还是对象,再接着调用toString方法

3.2严格相等运算符

相等运算符()比较两个值是否相等,严格相等运算符(=)比较它们是否为“同一个值”

严格相等运算符
(1)不同类型的值

如果两个值的类型不同,直接返回false。
2)同一类的原始类型值

同一类型的原始类型的值(数值、字符串、布尔值)比较时,值相同就返回true,值不同就返回false
1 === 0x1 // true

NaN与任何值都不相等(包括自身)。另外,正0等于负0。

(3)复合类型值

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

{} === {} // false
[] === [] // false
(function () {} === function () {}) // false

如果两个变量引用同一个对象,则它们相等。

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

var obj1 = {};
var obj2 = {};

obj1 > obj2 // false
obj1 < obj2 // false
obj1 === obj2 // false

(4)undefined 和 null

undefined和null与自身严格相等
变量声明后默认值是undefined,因此两个只声明未赋值的变量是相等的。

3.3严格不相等运算符

!==
先求严格相等运算符的结果,然后返回相反值。

3.4相等运算符

相等运算符用来比较相同类型的数据时,与严格相等运算符完全一样。
(1)原始类型值

原始类型的值会转换成数值再进行比较

'true' == true // false
// 等同于 Number('true') === Number(true)
// 等同于 NaN === 1

'' == 0 // true
// 等同于 Number('') === 0
// 等同于 0 === 0


'\n  123  \t' == 123 // true
// 因为字符串转为数字时,省略前置和后置的空格

(2)对象与原始类型值比较

对象(这里指广义的对象,包括数组和函数)与原始类型的值比较时,对象转换成原始类型的值,再进行比较。

先调用对象的valueOf()方法,如果得到原始类型的值,就按照上一小节的规则,互相比较;如果得到的还是对象,则再调用toString()方法

(3)undefined 和 null

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

不相等运算符
先求相等运算符的结果,然后返回相反值。

四、布尔运算符

取反运算符:!
且运算符:&&
或运算符:||
三元运算符:?:

对于非布尔值,取反运算符会将其转为布尔值。可以这样记忆,以下六个值取反后为true,其他值都为false。
undefined
null
false
0
NaN
空字符串(’’)

不管什么类型的值,经过取反运算后,都变成了布尔值

如果对一个值连续做两次取反运算,等于将其转为对应的布尔值,与Boolean函数(转成布尔值)的作用相同。这是一种常用的类型转换的写法。

4.1且运算符(&&)

如果第一个运算子的布尔值为true,则返回第二个运算子的值(注意是值,不是布尔值);如果第一个运算子的布尔值为false,则直接返回第一个运算子的值,且不再对第二个运算子求值

跳过第二个运算子的机制,被称为“短路”。

可以多个连用,这时返回第一个布尔值为false的表达式的值。如果所有表达式的布尔值都为true,则返回最后一个表达式的值。

4.2或运算符(||)

如果第一个运算子的布尔值为true,则返回第一个运算子的值,且不再对第二个运算子求值;如果第一个运算子的布尔值为false,则返回第二个运算子的值。

短路规则

4.3三元条件运算符(?:)

第一个表达式的布尔值为true,则返回第二个表达式的值,否则返回第三个表达式的值。

if…else是语句,没有返回值;三元条件表达式是表达式,具有返回值。
console.log(true ? ‘T’ : ‘F’);

5、二进制位运算符

二进制或运算符(or):符号为|,表示若两个二进制位都为0,则结果为0,否则为1。
二进制与运算符(and):符号为&,表示若两个二进制位都为1,则结果为1,否则为0。
二进制否运算符(not):符号为~,表示对一个二进制位取反。
异或运算符(xor):符号为^,表示若两个二进制位不相同,则结果为1,否则为0。
左移运算符(left shift):符号为<<,详见下文解释。
右移运算符(right shift):符号为>>,详见下文解释。
头部补零的右移运算符(zero filled right shift):符号为>>>,详见下文解释。

位运算符只对整数起作用,如果一个运算子不是整数,会自动转为整数后再执行。

JS内部,数值都是以64位浮点数的形式储存,但是做位运算的时候,是以32位带符号的整数进行运算的,并且返回值也是一个32位带符号的整数。

将i(不管是整数或小数)转为32位整数
i = i | 0;

对于大于或等于2的32次方的整数,大于32位的数位都会被舍去

5.1二进制或运算符

两个二进制位之中只要有一个为1,就返回1,否则返回0。
0 | 3 // 3

位运算只对整数有效,遇到小数时,会将小数部分舍去,只保留整数部分。所以,将一个小数与0进行二进制或运算,等同于对该数去除小数部分,即取整数位。
2.9 | 0 // 2
-2.9 | 0 // -2

不适用超过32位整数最大值

&)的规则是逐位比较两个运算子,两个二进制位之中只要有一个位为0,就返回0,否则返回1。

(~)将每个二进制位都变为相反值(0变为1,1变为0)
对一个整数连续两次二进制否运算,得到它自身

使用二进制否运算取整,是所有取整方法中最快的一种。
对字符串及其他类型的值进行二进制否运算,JavaScript 引擎会先调用Number函数,将字符串转为数值。

5.2异或运算符

异或运算(^)在两个二进制位不同时返回1,相同时返回0

0 ^ 3 // 3

每一个二进制位都不同,所以得到11(即3)。

异或运算”有一个特殊运用,连续对两个数a和b进行三次异或运算,a^=b; b^=a; a^=b;,可以互换它们的值

也可以用来取整。
12.9 ^ 0 // 12

5.3左移运算符

左移运算符(<<)表示将一个数的二进制值向左移动指定的位数,尾部补0,即乘以2的指定次方。向左

// 4 的二进制形式为100,
// 左移一位为1000(即十进制的8)
// 相当于乘以2的1次方
4 << 1
// 8

如果左移0位,就相当于将该数值转为32位整数,等同于取整,对于正数和负数都有效。

5.4、右移运算符

右移运算符(>>)表示将一个数的二进制值向右移动指定的位数。如果是正数,头部全部补0;如果是负数,头部全部补1。右移运算符基本上相当于除以2的指定次方(最高位即符号位参与移动)。
右移运算可以模拟 2 的整除运算。

头部补零的右移运算符(>>>)与右移运算符(>>)只有一个差别,就是一个数的二进制形式向右移动时,头部一律补零,而不考虑符号位。所以,该运算总是得到正值。对于正数,该运算的结果与右移运算符(>>)完全一致,区别主要在于负数。

5.5、开关作用

位运算符可以用作设置对象属性的开关。

6、其他运算符,运算顺序

6.1void 运算符

执行一个表达式,然后不返回任何值,或者说返回undefined。
void(0) // undefined
主要用途是浏览器的书签工具(Bookmarklet),以及在超级链接中插入代码防止网页跳转。
用户点击链接提交表单,但是不产生页面跳转。

用户点击链接提交表单,但是不产生页面跳转。
<a href="javascript: void(document.form.submit())">
  提交
</a>

6.2逗号运算符

逗号运算符用于对两个表达式求值,并返回后一个表达式的值

6.3运算顺序

(())可以用来提高运算的优先级,因为它的优先级是最高的

函数放在圆括号中,会返回函数本身。如果圆括号紧跟在函数的后面,就表示调用函数。
圆括号之中,只能放置表达式,如果将语句放在圆括号之中,就会报错。

少数运算符是“右结合”,其中最主要的是赋值运算符(=)和三元条件运算符(?:)
指数运算符(**)也是右结合

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值