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. 20155205 郝博雅 Exp 8 Web基础

    20155205 郝博雅 Exp 8 Web基础 一.实验目标 (1).Web前端HTML(0.5分) 能正常安装.启停Apache.理解HTML,理解表单,理解GET与POST方法,编写一个含有表单 ...

  2. Robust Influence Maximization

    一.   研究背景 在社会和经济网络中,影响最大化问题在过去十年中得到广泛的研究,由于其广泛应用于病毒式营销[1,2],突破检测[3],谣言监测[4]等.例如公司可以通过向初始用户(称为种子)发送免费 ...

  3. android 图形图像

    Canvas 画布 paint 画笔 Path 路径Path代表任意多条直线连接而成的任意图形,当Canvas根据Path绘制时,它可以绘制出任意的形状 使用 Matrix 控制图像或组件变换步骤:① ...

  4. Linux下Oracle数据库的安装

    记录详细过程以备使用 一.准备安装 为了确保Oracle数据库11g能够成功安装,您需要做好准备工作,例如检查网络配置.更改Linux内核参数.创建用户Oracle.创建安装目录.设置用户Oracle ...

  5. 1.1.1 PROB Your Ride Is Here

    === /* ID: luopengting PROG: ride LANG: C++ */ #include <iostream> #include <cstdio> #in ...

  6. c# 使用资源文件

    1.新建项目 2.新建资源文件 3. 代码中使用嵌入资源 using System;using System.Collections.Generic;using System.Text;using S ...

  7. 【.NET Core项目实战-统一认证平台】第六章 网关篇-自定义客户端授权

    [.NET Core项目实战-统一认证平台]开篇及目录索引 上篇文章我们介绍了网关使用Redis进行缓存,并介绍了如何进行缓存实现,缓存信息清理接口的使用.本篇我们将介绍如何实现网关自定义客户端授权, ...

  8. nodejs异步请求重试策略总结

    对于node开发同学经常要处理异步请求,然后根据请求的结果或请求成功后的状态码做不同的策略处理,众多策略中最常用的一种就是重试策略.针对重试策略我们往往还需要设定一定的规则,如重试次数.重试时间间隔. ...

  9. VSCode插件开发全攻略(七)WebView

    更多文章请戳VSCode插件开发全攻略系列目录导航. 什么是Webview 大家都知道,整个VSCode编辑器就是一张大的网页,其实,我们还可以在Visual Studio Code中创建完全自定义的 ...

  10. Dubbo 源码分析 - SPI 机制

    1.简介 SPI 全称为 Service Provider Interface,是 Java 提供的一种服务发现机制.SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加 ...