JavaScript 系列博客(二)

前言

本篇博客介绍 js 中的运算符、条件语句、循环语句以及数组。

运算符

  • 算术运算符
// + | - | * | / | % | ++ | --
console.log(5 / 2); // 2.5
// 取整
console.log('%d', 5 / 2); // "2"
var num = parseInt(5 / 2); // 2
console.log(num); // 取模(求余)
console.log(5 % 2); // 1
// 任何一个自然数对 n 取余, 结果为 [0, n-1] // 自增|自减 ++|--
// ++就是自增1, --就是自减1
var num = 10
console.log(num++); // 10
console.log(++num); // 12
console.log(num); // 12
// ++在变量后(num++), 先将变量的值拿去使用,再自身自增1
// ++再变量前(++num), 先将变量自身自增1, 再将结果拿去使用
// 总结: 不管++在前在后,运算结束后,变量自身值一定自增1 // res = ++num <==> num++; res = num
// res = num++ <==> res = num; ++num
  • 赋值运算符
// = | += | -= | *= | /= | %=
var x = 10; // 将10的值赋值给变量x
y = x; // 将变量x的值传递给变量y
console.log(y); // 10 x += 10; // x = x + 10, 运算方式由右至左, 将x+10的结果重新复制给x
console.log(y); // 10, y的值虽然来源于x, 但y值只由自身控制 // x /= 10 == x = x / 10
  • 比较运算符
// 比较运算符, 结果为Boolean类型
// == | ===
console.log("5" == 5); // true, 只做值比较
console.log("5" === 5); // false, 比较值及类型 // != | !==
console.log("5" != 5); // false, 只做值比较
console.log("5" !== 5); // true, 比较值及类型
  • 逻辑运算符
// 总结&&: 全真为真, 有假则假
// 总结||: 全假则假, 有真则真
// 总结!: 真则假, 假则真 // 逻辑运算符的结果本质上为表达式值
// 表达式: 由数字,变量,运算符组成的合法式子
res = a < b && c;
console.log(res); res = (a = 1 || b == c);
console.log(res); // 针对 && | ||
// 疑问: 逻辑运算符结果可能为逻辑运算符之前表达式的值,也可能是之后表达式的值

针对逻辑运算符,会出现短路现象。当运算符为&&时,如果第一个表达式的结果为假,那么第二个表达式就不会执行;同理,||当第一个表达式的结果为真时,第二个表达式就不会执行(python 在逻辑判断也会出现短路现象)

  • 三目运算符(等同于 python 中的三元表达式)
// 语法:  条件表达式 ? 表达式1 : 表达式2
var a = 10, b = 20;
var res = a < b ? a : b; // 取小值
console.log(res);
res = a < b ? b : a; // 取大值
console.log(res); // 类似于if...esle...
a < b ? console.log("表达式结果为true") : console.log("表达式结果为false")

三目表达式可以看做 if...else 的简写形式。

程序结构

根据执行方式程序可以分为三大结构:顺序结构、分支结构、循环结构。其实只有一种结构就是顺序结构,像分支结构本质还是顺序执行的,只不过选择多了;而循环结构也是一样的道理。

条件语句

if 结构

if结构首先判断后面表达式的布尔值,然后决定是否执行后面的代码。布尔值只有两个,true 为真,false 为假。

// 语法
if (表达式1) {
语句; };
// 或
if (表达式2) {语句};

上面是 if 结构的基本形式。需要注意的是,‘’布尔值‘’往往是由一个条件表达式产生的,必须放在圆括号中,表达对该表达式求值。如果表达式的结果为 true,就执行后面的代码语句;如果为 false,则跳过后面的语句。

if...else 结构

跟 python 一样,if 后面也可以跟 else 代码块,表示不满足条件时,要执行的代码块。

if (表达式3) {
//表达式结构为真时,执行的代码
} else {
// 表达是结构为假时,执行的代码
}

如果需要对于一个表达式进行多次判断时,多个 if...else 语句可以连到一起。

if (表达式4) {

} else if {表达式5} {

} else if {表达式6} {

} else {

} // 注意:else 代码块总是与离自己最近的那个 if 语句配对

switch 分支

// 语法
switch (结果为整数|字符串的表达式) {
case 值1(值需要和表达式进行类型统一): 代码块; break;
...
case 值n: 代码块; break;
default: 代码块;
}
// 需要注意的是,switch 语句后面的表达是,与 case 语句后面的表达是比较运行结果时,采用的是严格相等运算符(===),而不是相等运算符(==),这意味着比较时不会发生类型转换。
// break作用是结束分支结构(结束所属switch语句),可以省略。

default 分支

default分支,出现在所有case之下,当所有case没有匹配上,走该分支,该分支也可以省略,代表没有未匹配到的动作。

循环语句

循环语句用于重复执行某个操作,直到条件不满足跳出循环。

while 循环

while 循环包括一个循环条件和一段代码块,只要条件为真,就会不断执行代码块。

while (条件表达式) {
语句;
}

while语句的循环条件为一个条件表达式,必须放在圆括号中,表示需要先计算表达式的结果才能进行是否进行循环。代码块部分,如果只有一条语句,可以省略大括号。

var i = 0;
while (i < 100) {
console.log('i 为:' + i);
i++;
}

这段代码会循环100次,直到i 等于100。

for 循环

for 循环是循环结构的另一种形式,可以指定循环的起点、终点和终止条件。格式如下:

/*
for (循环变量定义并初始化①; 循环变量条件表达式②; 循环变量增量③) {
代码块④;
}
执行顺序 ① ②④③ ... ②④③ ②, ②④③个数就是循环次数
*/ for (var i = 0; i < 5; i++) {
console.log("我最棒, 我最帅, 我是天下第一!");
}

上段代码圆括号里面有三个表达式:

  • 表达式①(initialize):确定循环变量的初始值,只在循环开始时执行一次。
  • 表达式②(test):每轮循环开始时,都需要执行判断,只有判断为真时,才会继续循环。
  • 表达式③(increment):每轮循环的最后一个操作,通常用来递增循环变量。

所有 for 循环,都可以用 while 循环实现。

for 循环里面的三个表达式可以省略其中任何一个,也可以全部省略。

for ( ; ; ) {
console.log('Hello MUSIBII!');
}

这段代码省略了 for 表达式的三个部分,结果就导致了一个无限循环。

do...while 循环

do...while 循环和 for 循环类似,唯一区别就是 do 循环不管条件满不满足都会执行一次循环,之后进行第二次循环才会进行判断条件。

do
代码块
while (条件表达式); // 或
do {
代码
} while (条件表达式);

不管条件是否为真,do...while 循环至少需要运行一次,这是和while 循环的本质区别。另外 while 语句后面的分号不要省略。

var x = 3;
var y = 0;
do {
console.log(y);
y++;
} while(y < x);

break 和 continue 语句

只要有循环就少不了 break 和 continue,这两个关键词都具有跳转作用,可以控制代码的执行顺序。

  • break 语句用于跳出循环体
var i = 0;

while(i < 100) {
console.log('i 为:' +i);
i++;
if (i === 10) break;
}

当 i 等于10时,if 表达式判断为真,执行 break 跳出循环体

  • continue 语句用于立即终止本轮循环,进入下次循环。
var i = 0;
while(i < 100) {
if (i % 2 === 0) continue;
console.log('i 为:' +i);
i++;
}

这段代码只有 i 为奇数时,才会输出 i 的值。如果 i 为偶数,则直接进入下一轮循环。如果存在多重循环,不带参数的 break 语句和 continue 语句都只针对本层循环。

数组

数组的定义

数组(Array)是按照次序排列的一组值。每个值得索引从0开始,数组使用中括号表示。

var array = ['a', 'b', 'c', 1, 2, 3];

这样,array 就构成一个数组,两端的方括号是数组的标志。'a' 是0号位置,3是5号位置。

除了在定义时赋值,数组也可以先定义后赋值。(通过构造函数(constructor))

var array = [];
array[0] = 'hello';
array[1] = 'world';

任何类型的数据,都可以放入数组(类比 python 的列表)。

特别的,如果数组的元素还是数组,则形成了多维数组。

数组的本质

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

typeof(['a', 'b', 'c']) // object

这表明,数组类型为对象。数组的特殊性体现在,它的键名是按次序排列的一组整数(从0开始)。

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

Object.keys(array) // ['0', '1', '2']

通过 Object 的 keys 方法可以返回指定数组的所有键名。

由于数组成员的键名是固定的,因此数组不用为每个元素指定键名,而对象的每个成员都必须指定键名。JavaScript 语言规定,对象的键名一律为字符串,所以,数组的键名其实也是字符串。之所以可以用数值取值,是因为非字符串的键名会被转为字符串。

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

array[0]; // 'a'
array['0']; // 'a'

这点在赋值时也会成立(js 的数据类型转换需要注意),一个值总是先转成字符串,再进行赋值。

var a = [];
a[1.00] = 'c';
a[1]; // 'c'

赋值时,先把1.00转为字符串1,赋值结束后可以通过数字键1取值。

length 属性

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

array.length // 3

JavaScript 使用一个32位整数,保存数组的元素个数。这意味着,数组成员最多只用(2^32 - 1)个,也就是说 length 属性的最大值就是4294967295。

只要是数组就一定有 length 属性。该属性是一个动态的值(因为可以动态赋值)。数组的数字键不需要连续,length 属性的值总是比最大的那个整数键大1.另外,数组是一种动态的数据结构,可以随时增减数组成员。

注意:length 属性是可写的。如果认为的设置一个小于当前成员个数的值,该数组的成员会自动减少到 length 设置的值。

var array = ['a', 'b', 'c'];
array.length; // 3
array.length = 2;
array // ['a', 'b']

这表明当数组的 length 属性值设为2,那么整数键2就会被删除。这样清空一个数组就可以直接把 length 属性值设为0就 ok 了。

如果人为设置 length 值大于当前数组元素个数,那么数组的成员数量会增加到这个值,新增的位置都是空(undefined)。

var array = ['a'];

a.length = 2;
a[1]; // undedined

当 length 属性值设为大于数组个数时,读取新增的位置都会返回 undefined。如果设置的不合法,比如设置一个非整数的值时,JavaScript 会报错。

var array = [];
array.length = -1;
// RangeError: Invalid array length array.length = Math.pow(2, 32);
// RangeError: Invalid array length array.length = 'abc';
// RangeError: Invalid array length

因为数组的本质是一种对象,所以可以为数组添加属性,但是这不会影响数组的 length 属性。

var array = ['a'];
array['name'] = 'musibii'; array.length; // 1

注意:如果数组添加的键名超过范围的数值,该键名会自动转化为字符串。

var array = [];
array[-1] = 'a'; array[Math.pow(2, 32)] = 'b'; array.length //0
array[-1]; // 'a'
array[4294967296]; // 'b'

上面为数组添加了两个不合法的数字键,并不会影响到 length 的值。这些数字键都变成了字符串键名。最后两行会取到值是因为会把数字转为字符串。

in 运算符

检查某个键名是否存在于数组中,使用 in 运算符,这个适用于对象,自然也适用于数组。

var array = ['a', 'b', 'c', 1, 2, 3];
2 in array; // true
'2' in array; // true
6 in array; // false

数组存在键名为2的键,由于键名都为字符串,所以数值2会自动转成字符串。

var array = [];
array[100] = 'a'; array.length; // 101
array[1]; // undefined 1 in array; // false

数组 array 只有一个成员,虽然 length 为101,但是其他位置的键名都会返回 false。

for...in 循环和数组的遍历

for...in 循环不仅可以遍历对象,也可以遍历数组。因为数组是对象。

var array = ['a', 'b', 'c'];
for (var i in array) {
console.log(array[i]);
}
// 'a', 'b', 'c' 换行打印

for...in 不仅会遍历数组所有的数字键,也会遍历非数字键。

var array = ['a', 'b', 'c'];
array.name = 'musibii'; for (var i in array) {
console.log(array[i]);
}
// 'a', 'b', 'c', 'musibii'

在遍历数组时,也会遍历非整数键name,所以不建议使用for...in 遍历数组。可以使用 for 循环或者 while 循环。(这样只会遍历出整数的键名)

数组的空位

当数组的某个位置是空元素,即两个逗号之间没有任何值,那么称该数组存在空位。

var array = ['a', '', 'c'];
array.length; // 3
array[1]; // undefined

这表名数组的空位不影响 length 属性的值。 并且空位是可以被读取的,只不过值为 undefined。

使用 delete 命令可以删除数组中的某个成员,这样会形成空位,和上面一样不会影响数组的 length 属性。

var array = ['a', 'b', 'c'];
delete array[1];
a[1]; //undefined
a.length; // 3

使用 delete 删除了数组中的元素,不会影响数组的 length 属性值,这样如果使用 length 对一个数组进行遍历时需要谨慎(这好奇怪啊。。。。)

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

不得不说,真的奇怪。这个设计思想也太灵活了8。。。

空位表示数组没有这个元素,所以不会被遍历到,而 undefined 表示数组有这个元素,值为 undefined,这样遍历就不会跳过。

本文参考https://wangdoc.com/javascript/types/array.html

JavaScript 系列博客(二)的更多相关文章

  1. JavaScript 系列博客(五)

    JavaScript 系列博客(五) 前言 本篇博客学习 js 选择器来控制 css 和 html.使用事件(钩子函数)来处理事件完成后完成指定功能以及js 事件控制页面内容. js 选择器 在学习 ...

  2. JavaScript 系列博客(三)

    JavaScript 系列博客(三) 前言 本篇介绍 JavaScript 中的函数知识. 函数的三种声明方法 function 命令 可以类比为 python 中的 def 关键词. functio ...

  3. JavaScript 系列博客(一)

    JavaScript 系列博客(一) 前言 本系列博客为记录学习 JavaScript 的学习笔记,会从基础开始慢慢探索 js.今天的学习笔记主要为 js 引入.定义变量以及 JavaScript 中 ...

  4. JavaScript 系列博客(七)

    JavaScript 系列博客(七) 前言 本篇博客介绍页面节点概念.文档结构以及如何使用 js 操作文档节点还有事件 target 以及 BOM 操作. 节点 dom与dom属性 // DOM: 文 ...

  5. JavaScript 系列博客(六)

    JavaScript 系列博客(六) 前言 本篇博客介绍 js 操作高级,通过 js 获取标签的全局属性.设置标签的全局属性,以及事件的绑定与取消.js 盒模型与 js 动画. 对象使用的高级 对象的 ...

  6. JavaScript 系列博客(四)

    JavaScript 系列博客之(四) 前言 本篇介绍 JavaScript 中的对象.在第一篇博客中已经说到 JavaScript 是一种''对象模型''语言.所以可以这样说,对象是 JavaScr ...

  7. Django 系列博客(二)

    Django 系列博客(二) 前言 今天博客的内容为使用 Django 完成第一个 Django 页面,并进行一些简单页面的搭建和转跳. 命令行搭建 Django 项目 创建纯净虚拟环境 在上一篇博客 ...

  8. Flutter 即学即用系列博客——09 MethodChannel 实现原生与 Flutter 通信(二)

    前言 上一篇我们讲解了如何通过 EventChannel 实现 Android -> Flutter 的通信. 并且也看到了 Flutter 内部 EventChannel 源码也是对 Meth ...

  9. Django 系列博客(十二)

    Django 系列博客(十二) 前言 本篇博客继续介绍 Django 中的查询,分别为聚合查询和分组查询,以及 F 和 Q 查询. 聚合查询 语法:aggregate(*args, **kwargs) ...

随机推荐

  1. RabbitMq相关

    RabbitMq 通过通过IP,Port等参数创建connection对象,然后实际上通信用的是channel,channel的建立基于connection RPC 调用: RPCClient通过ch ...

  2. MySQL定时器

    MySQL的定时器是一个很有用的功能,有时候需要数据库自动根据时间进行一些必要的操作,此时定时器就派上了用场了. 一.查看MySQL版本号 select version(); 二.查看event的状态 ...

  3. html、css基础整理

    1.块元素与行内元素之间的转换: HTML可以将元素分类方式分为行内元素.块状元素和行内块状元素三种.这三者是可以互相转换的,使用display属性能够将三者任意转换: (1)display:inli ...

  4. 自动的输入号码的辅助软件在ie浏览器下的尝试

    在ie下面的自动输入号码的软件,我已经折腾了好久.由于ie环境非常复杂:网页延迟这个时间一直不能准确的得到,这个时间主要包括:网络的与服务器的交换速度,网页自身的加载速度,网页的js渲染的效果的影响. ...

  5. finalize方法的使用

    finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法.这个方法在gc启动,该对象被回收的时候被调用.其实gc可以回收大部分的对象(凡是new出来的对象,g ...

  6. UltraISO制作CentOS 7.6 U盘引导安装盘

    一.制作准备: 1.UltraISO下载安装 2.CentOS镜像文件下载(阿里镜像下载) 二.制作引导盘: 1.电脑插入U盘 2.UltraISO加载镜像文件: 文件->打开->选择对应 ...

  7. Jenkins的初级应用(2)-Invoke Phing targets

    Invoke Phing targets这个插件主要是读取xml形式包括自动化测试打包部署的配置文件,然后根据流程走下来.用phing命令读取并执行xml配置文件,然后执行定义的步骤.比如check. ...

  8. Ettercap 实施中间人攻击

    中间人攻击(MITM)该攻击很早就成为了黑客常用的一种古老的攻击手段,并且一直到如今还具有极大的扩展空间,MITM攻击的使用是很广泛的,曾经猖獗一时的SMB会话劫持.DNS欺骗等技术都是典型的MITM ...

  9. 暴走Python之运算符与条件语句

    本文原创作者:LoneliNess,本文属i春秋原创奖励计划,未经许可禁止转载   本文来源:i春秋学院   i春秋(ichunqiu.com)网络安全平台能提供专业的网络安全技术.网络渗透技术.网络 ...

  10. Android JNI 学习(六):Object Operations Api

    一.AllocObject jobjectAllocObject(JNIEnv *env, jclass clazz); 分配新 Java 对象而不调用该对象的任何构造函数.返回该对象的引用. cla ...