前端-JS学习笔记-基础语法

变量,数据类型,运算符,分支语句,循环语句

1. JavaScript的交互方式

1.1. alert()

  • 接受一个参数
  • 弹窗查看
1
alert("Hello World");

1.2. console.log()

  • 接受多个参数
  • 在浏览器控制台查看
1
console.log("Hello World");

1.3. document.write()

  • 接受多个字符串
  • 在浏览器页面查看
1
document.write("Hello World");

1.4. prompt()

  • 接受一个参数
  • 在浏览器接受用户输入
1
2
var result = prompt("请输入你的名字:");
alert(result);

2. Chrome的调试工具

  • 在JavaScript中通过console函数显示一些内容时,也可以使用Chrome浏览器来查看

  • 另外补充几点

    1. 如果在代码中出现了错误,那么可以在console中显示错误
    2. console中有个 > 标志,表示控制台的命令行
      • 在命令行中可以直接编写JavaScript代码,按下enter会执行代码
      • 如果希望编写多行代码,可以按下shift+enter来进行换行编写
    3. 通过debug方式来调试、查看代码的执行流程

3. VSCode插件和配置

  • ES7+ React/Redux/React-Native snippets

    • 这个插件是在react开发中会使用到的
    • 可用于打印语句
      • 快捷键 clg - console.log();
  • Bracket Pair Colorizer 2

    • 可以将js方法,css样式中的 { } 整体感很突出

    • 已经废弃,因为VSCode已经内置了该功能,可以直接通过VSCode的配置来达到插件的效果

    • 配置setting.json

      • 快捷键打开设置 command+,
      • 打开setting.json

      • 添加代码
      1
      "editor.bracketPairColorization.enabled": true, "editor.guides.bracketPairs":"active"

4. JavaScript语句和分号

  • 语句是向浏览器发出的指令,通常表达一个操作或者行为(Action)

    • 语句英文是Statements
    • 编写的每一行代码都是一个语句,用于告知浏览器一条执行的命令
    1
    alert("Hello World");
  • 通常每条语句的后面会添加一个分号,表示语句的结束

    • 分号的英文是semicolon
    • 当存在换行符(line break)时,在大多数情况下可以省略分号
    • JavaScript 将换行符理解成“隐式”的分号
    • 这也被称之为自动插入分号(an automatic semicolon)
  • 在对JavaScript语法不熟悉的情况推荐添加分号

5. JavaScript的注释

  • 在HTML、CSS中都添加过注释,JavaScript也可以添加注释

    • HTML注释 <!-- -->
    • CSS注释 /* */
  • JavaScript的注释主要分为三种

  • 单行注释 //

  • 多行注释 /* */

  • 文档注释(VSCode中需要在单独的JavaScript文件中编写才有效)

  • 注意:JavaScript不支持注释的嵌套

6. JavaScript变量

6.1. 变化数据的记录 – 变量

  • 如果希望记录某一个之后会变量的数据,在JavaScript中可以定义一个变量

    • 一个变量,就是一个用于存放数值的容器
    • 这个数值可能是一个用于计算的数字,或者是一个句子中的字符串,或者其他任意的数据
    • 变量的独特之处在于它存放的数值是可以改变的
  • 可以把变量想象成一个盒子,盒子里面装着数据,需要给盒子进行一个特性的名称

    • 例如,变量 message 可以被想象成一个标有 “message” 的盒子,盒子里面的值为 “Hello!”
    • 并且,这个盒子的值,想改变多少次,就可以改变多少次
    1
    2
    var message = "Hello";
    message = "Word";

6.2. 变量的命名格式

  • 在JavaScript中命名一个变量包含两部分

    • 变量的声明
      • 在JavaScript中声明一个变量使用var关键字(variable单词的缩写)
      • ES6还有let、const声明方式
    • 变量的赋值
      • 使用 = 给变量进行赋值
    1
    var name = "why";
  • 这个过程也可以分开操作

    1
    2
    var name;
    namr = "why";
  • 也可以同时声明多个变量

    1
    2
    3
    4
    5
    6
    7
    var name,age,height;
    name = "why";
    age = 18;
    height = 1.88;

    var friend = "john", hobbies="football";
    console.log(name,age,height,friend,hobbies);

6.3. 变量的命名规范

  • 变量命名规则:必须遵守

    1. 第一个字符必须是一个字母、下划线( _ )或一个美元符号( $ )

    2. 其他字符可以是字母、下划线、美元符号或数字

    3. 不能使用关键字和保留字命名

    4. 变量严格区分大小写

  • 变量命名规范:建议遵守

    • 多个单词使用驼峰标识
    • 赋值 = 两边都加上一个空格
    • 一条语句结束后加上分号; 也可以不加
    • 变量应该做到见名知意

6.4. 变量的练习

  • 练习一:定义一个变量name,赋值成why。定义一个变量admin,将name赋值给admin

    1
    2
    var name = "why";
    var admin = name;
  • 练习二:定义变量,保存两个数字,并且对两个变量的数字进行交换

    • 方式一:使用临时变量

      1
      2
      3
      4
      5
      6
      7
      var a = 1;
      var b = 2;
      console.log(a,b);
      var temp = a;
      a = b;
      b = temp;
      console.log(a,b);
    • 方式二:不使用临时变量

      1
      2
      3
      4
      5
      6
      7
      8
      var a = 1;
      var b = 2;
      console.log(a,b);

      a = a + b;
      b = a - b;
      a = a - b;
      console.log(a,b);
  • 练习三:让用户在浏览器中输入一个值,在JavaScript程序中使用变量接收

    1
    2
    var result = prompt("请输入用户名");
    console.log(result);

6.5. 变量的使用注意

  • 注意一:如果一个变量未声明(declaration)就直接使用,那么会报错

    • 不要使用name这个变量进行测试,该变量在window对象中已有定义
    1
    2
    // Uncaught ReferenceError: message is not defined
    console.log(message);
  • 注意二:如果一个变量有声明,但是没有赋值,那么默认值是undefined

    1
    2
    3
    var info
    // undefined
    console.log(info);
  • 注意三:如果没有使用var声明变量也可以,会被当作全局变量,但是不推荐(事实上会被添加到window对象上)

    1
    2
    3
    4
    5
    admin = "why";
    // why
    console.log(admin);
    // why
    console.log(window.admin);

7. JavaScript的数据类型(8种)

  • JavaScript中的值都具有特定的类型

    • 例如,字符串或数字
    • 可以将值赋值给一个变量,那么这个变量就具备了特定的类型
    • 一个变量可以在前一刻是个字符串,下一刻就存储一个数字
    • 允许这种操作的编程语言,例如 JavaScript,被称为”动态类型“(dynamically typed)的编程语言
  • 在 JavaScript 中有 8 种基本的数据类型(7 种原始类型和 1 种复杂类型)

    • Number
    • String
    • Boolean
    • Undefined
    • Null
    • Object
    • BigInt
    • Symbol

7.1. typeof操作符

  • 因为 ECMAScript 的类型系统是松散的,所以需要一种手段来确定任意变量的数据类型

    • typeof 操作符就是为此而生的
  • 对一个值使用 typeof 操作符会返回下列字符串之一

    • “undefined”表示值未定义
    • “boolean”表示值为布尔值
    • “string”表示值为字符串
    • “number”表示值为数值
    • “object”表示值为对象(而不是函数)或 null
    • “function”表示值为函数
    • “symbol”表示值为符号
  • typeof()的用法

  • 另一种语法:typeof(x),它与 typeof x 相同

  • typeof是一个操作符,并非是一个函数,()只是将后续的内容当做一个整体而已

7.2. Undefined类型

  • Undefined 类型只有一个值,就是特殊值 undefined

    • 如果声明一个变量,但是没有对其进行初始化时,它默认就是undefined

      1
      2
      3
      4
      5
      var message;
      // undefined
      console.log(message);
      // true
      console.log(message === undefined);
  • 下面的代码是一样的

    1
    2
    var info;
    var info = undefined;
  • 未初始化和未定义变量是不一样的

    1
    2
    3
    4
    5
    let message;
    // undefined
    console.log(message);
    // ReferenceError: age is not defined
    console.log(age);

    对于未声明的变量,只能调用typeof

    对于未声明的变量调用,typeof返回的也是字符串”undefined”

    1
    2
    // undefined
    console.log(typeof age);
  • 有两个注意事项

    • 注意一:最好在变量定义的时候进行初始化,而不只是声明一个变量
    • 注意二:不要显式的将一个变量赋值为undefined
      • 如果变量刚开始什么都没有,可以初始化为0、空字符串、null等值

7.3. Null类型

  • Null 类型同样只有一个值,即特殊值 null

  • 逻辑上讲,null值表示一个空对象指针,所以使用 typeof null会返回“object”

    • null类型通常用来表示一个对象为空
    • 所以通常在给一个对象进行初始化时,会赋值为null
    1
    2
    3
    4
    5
    6
    7
    8
    // object
    console.log(typeof null);

    var obj = null;
    obj = {
    name: "why",
    age: 18
    }
  • null和undefined的关系

    • undefined值是由null派生而来的,ECMA-262将它俩定义为表面相等

      1
      2
      3
      4
      5
      6
      7
      8
      // true
      console.log(undefined == null);
      // undefined
      console.log(typeof undefined);
      //object
      console.log(typeof null);
      //false
      console.log(undefined === null);
    • 当一个变量声明但是未初始化时,它的默认值通常是undefined,不需要直接将一个变量赋值为undefined

    • 当一个变量准备保存一个对象,但是这个对象不确定时,可以先赋值为null

7.4. Boolean类型

  • 布尔(Boolean)是计算机科学中的逻辑数据类型,以发明布尔代数的数学家乔治·布尔为名

  • Boolean(布尔)类型用于表示真假,有两个字面值:true和false

    • 布尔值不同于数值。true不等于1,false不等于0
    • 布尔值字面量区分大小写。True和False就不是布尔值

7.5. Number类型

  • Number类型使用IEEE 754格式表示整数和浮点值。不同数值类型有不同的数值字面量格式

7.5.1. 十进制

  • 十进制整数可以直接写出来 let num = 55;
  • 使用其他进制格式创建的数值在所有数字操作中都被视为十进制数值

7.5.2. 二进制

  • 二进制字面量需要前缀0b,后续只能使用0/1,使用其他数值就会报错
1
2
3
4
5
6
let num1 = 0b110;
// 十进制数6
console.log(num1);

// 无法完成赋值
// let num2 = 0b3;

7.5.3. 八进制

  • 八进制字面量第一个数字必须是0,后续对应八进制的数值0-7

  • 超过八进制应用的范围就会忽略前缀的0而被当成十进制数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    let num1 = 070;
    // 十进制的56
    console.log(num1);

    let num2 = 079;
    // 无效的八进制值,输出的是十进制数79
    console.log(num2);

    let num3 = 08;
    // 无效的八进制值,输出的是十进制数8
    console.log(num3);
  • 八进制字面量前缀用0表示在严格模式下是无效的,会抛出语法错误 Octal literals are not allowed,应该使用0o前缀

    1
    2
    3
    let num = 0o70;
    // 56
    console.log(num);

7.5.4. 十六进制

  • 十六进制字面量需要前缀0x,后续是十六进制数(0-9,A-F),不区分大小写

  • 超过十六进制应用的范围也会忽略前缀而被当成十进制数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    let num1 = 0xf;
    // 十进制数15
    console.log(num1);

    let num2 = 0x79;
    // 十进制数121
    console.log(num2);

    let num3 = 0x8;
    // 无效的十六进制值,输出的是十进制数8
    console.log(num3);

7.5.5. 浮点值

  • 定义浮点值,数值中必须包含小数点,并且小数点后必须至少一个数字

  • 存储浮点值使用的内存空间是存储数值的两倍,当数值的小数点后没有数字或只有0时会被转换为整数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    let num1 = 1.1;
    // 1.1
    console.log(num1);

    let num2 = 1.0;
    // 1
    console.log(num2);

    let num3 = 1.;
    // 1
    console.log(num3);
  • 对于非常大或非常小的数值,用科学计数法表示。以10为底的幂级数

  • 默认情况下,ECMAScript会将小数点后至少包含6个0的浮点值转换为科学计数法

    1
    2
    3
    4
    5
    6
    7
    let num1 = 3.125e7;
    // 31250000
    console.log(num1);

    let num2 = 0.000000003;
    // 3e-9
    console.log(num2);
  • 浮点值的精确度最高可达17位小数,但是算术计算中不如整数精确

  • 0.1加0.2并不能得到0.3,而是0.300 000 000 000 000 04。这是使用IEEE 754导致的

    1
    2
    // false
    console.log((0.1+0.2)==0.3);

7.5.6. 无穷值

  • ECMAScript并不能表示世界上所有的数值

    • 可以表示的最小数值为Number.MIN_VALUE
    • 可以表示的最大数值为Number.MAX_VALUE
    1
    2
    3
    4
    // 5e-324
    console.log(Number.MIN_VALUE);
    // 1.7976931348623157e+308
    console.log(Number.MAX_VALUE);
  • 如果数值超出了可以表示的范围,这个数值自动被转换为无穷值

    1
    2
    3
    4
    // Infinity
    console.log(1/0);
    // -Infinity
    console.log(-1/0);
  • 主动获取无穷值

    1
    2
    3
    4
    // -Infinity
    console.log(Number.NEGATIVE_INFINITY);
    // Infinity
    console.log(Number.POSITIVE_INFINITY);
  • 对于无穷值将不再进一步用于任何计算,因为无穷值没有可用于计算的数值表示形式

    1
    2
    3
    var num = Number.NEGATIVE_INFINITY+Number.POSITIVE_INFINITY;
    // NaN
    console.log(num);
  • 可以用isFinite()函数判断数值是否为有限值

    1
    2
    3
    4
    5
    6
    7
    8
    // false
    console.log(isFinite(1/0));

    var num = Number.MAX_VALUE+Number.MAX_VALUE;
    // Infinity
    console.log(num);
    // false
    console.log(isFinite(num));

7.5.7. NaN

  • NaN表示不是数值(Not a Number)

  • 代表一个计算错误,它是一个错误的操作所得到的结果

    • 比如 字符串和一个数字相乘
    1
    2
    3
    var c = 1 + "2";
    // NaN
    console.log(c);
  • NaN本身是数值类型

    1
    2
    // number
    console.log(typeof NaN);
  • 在ECMAScript中,0/+0/-0相除会返回NaN

    1
    2
    3
    4
    5
    6
    // NaN
    console.log(0/0);
    // NaN
    console.log(+0/0);
    // NaN
    console.log(+0/-0);
  • 当分母为0时,返回无穷值Infinity

    1
    2
    3
    4
    // Infinity
    console.log(5/0);
    // -Infinity
    console.log(-5/0);
  • NaN特性

    • 任何涉及NaN的操作始终返回NaN

      1
      2
      3
      4
      5
      6
      // NaN
      console.log(NaN+0);
      // NaN
      console.log(Nan/0);
      // NaN
      console.log(NaN + NaN);
    • NaN不等于包括NaN在内的任何值

      1
      2
      // false
      console.log(NaN == NaN);
  • isNaN()函数接收一个参数用于判断这个参数是否“不是数值”

    • 参数值都会被尝试转换成数值,任何不能被转换为数值的都会导致函数返回true
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // true
    console.log(isNaN(NaN));
    // false,10是数值
    console.log(isNaN(10));
    // false,字符串"10"可以转换为数值10
    console.log(isNaN("10"));
    // true,字符串"blue"不能转换为数值
    console.log(isNaN("blue"));
    // false,空字符串转换为数值0
    console.log(isNaN(""));
    // false,布尔值true转换为数值1
    console.log(isNaN(true));
  • isNaN()函数还可以用于测试对象

    • 先调用对象的valueOf()确定是否能转换为数值
    • 不能时再调用对象的toString(),测试其返回值

7.6. String类型

  • String表示零或多个16位Unicode字符序列

  • 字符串必须被括在引号里,有三种包含字符串的方式

    • 双引号:”Hello”

    • 单引号:’Hello’

    • 反引号:

      1
      2
      var name = "World";
      var message = `Hello ${name}`;
  • 前后的引号类型必须一致

    • 如果在字符串里面本身包括单引号,可以使用双引号
    • 如果在字符串里面本身包括双引号,可以使用单引号

7.6.1. 转义字符

  • 除了普通的可打印字符以外,一些有特殊功能的字符可以通过转义字符的形式放入字符串中
转义字符 表示符号
\' 单引号
\" 双引号
\\ 反斜杠
\n 换行符
\r 回车符
\t 制表符
\b 退格符

7.6.2. 字符串特点

  • 字符串是不可变的

    • 修改某个变量中的字符串值,必须先销毁原始的字符串,将包含新值的另一个字符串保存到该变量
    1
    2
    3
    4
    var str = "Hello";
    var str += " World";
    // Hello World
    console.log(str);

7.7. Symbol类型

7.8. Object类型

7.9. 数据类型总结

  • JavaScript 中有八种基本的数据类型(前七种为基本数据类型,也称为原始类型,而 object 为复杂数据类型,也称为引用类型)

    • number 用于任何类型的数字:整数或浮点数
    • string 用于字符串:一个字符串可以包含 0 个或多个字符,所以没有单独的单字符类型
    • boolean 用于 true 和 false
    • undefined 用于未定义的值:只有一个 undefined 值的独立类型
    • object 用于更复杂的数据结构
    • null 用于未知的值:只有一个 null 值的独立类型
  • 后续学习的类型

    • symbol 用于唯一的标识符
    • bigint 用于任意长度的整数

7.10. 数据类型的转换

  • 在开发中,可能会在不同的数据类型之间进行某些操作

  • 也就是在开发中,会经常需要对数据类型进行转换

    • 大多数情况下,运算符和函数会自动将赋予它们的值转换为正确的类型,这是一种隐式转换

    • 也可以通过显示的方式来对数据类型进行转换

7.10.1. 字符串String的转换

  • 转换方式一:隐式转换

    • 一个字符串和另一个字符串进行+操作

      • 如果+运算符左右两边有一个是字符串,那么另一边会自动转换成字符串类型进行拼接

      • 某些函数的执行也会自动将参数转为字符串类型,比如console.log函数

  • 转换方式二:显式转换

    • 调用String()函数
    • 调用toString()方法

7.10.2. 数字类型Number的转换

  • 转换方式一:隐式转换
    • 在算数运算中,通常会将其他类型转换成数字类型来进行运算
      • 比如 “6” / “2”
      • 但是如果是+运算,并且其中一边有字符串,那么还是按照字符串来连接的
  • 转换方式二:显式转换
    • 也可以使用Number()/parseInt()/parseFloat()函数来进行显式的转换
  • 其他类型转换数字的规则
转换后的值
undefined NaN
null 0
true 和 false 1 and 0
string 去掉首尾空格后的纯数字字符串中含有的数字
如果剩余字符串为空,则转换结果为 0
否则,将会从剩余字符串中“读取”数字
当类型转换出现 error 时返回 NaN

7.10.3. 布尔类型Boolean的转换

  • 布尔(boolean)类型转换发生在逻辑运算中,但是也可以通过调用 Boolean(value) 显式地进行转换

  • 转换规则如下

    转化后
    0, null, undefined, NaN, “” false
    其他值 true
    • 直观上为“空”的值(如 0、空字符串、null、undefined 和 NaN)将变为 false

      • 如下代码是不会输出内容的,因为判断条件是false
      1
      2
      3
      4
      5
      6
      var name = "";
      var age = 0;
      var isAdmin;
      if(name||age||isAdmin){
      console.log("pass");
      }
    • 其他值变成 true

      • 如下代码会输出Hello字符串
      1
      2
      3
      4
      var obj = {};
      if(obj) {
      console.log("Hello");
      }
  • 注意:包含 0 的字符串 “0” 是 true

    • 一些编程语言(比如 PHP)视 “0” 为 false。但在 JavaScript 中,非空的字符串总是 true

8. JavaScript运算符

8.1. 认识运算元

  • 运算元:运算符应用的对象

    • 比如说乘法运算 5 * 2,有两个运算元
      • 左运算元 5 和右运算元 2
      • 也称其为“参数”
  • 如果一个运算符对应的只有一个运算元,那么它是一元运算符

    • 比如说一元负号运算符(unary negation)-,它的作用是对数字进行正负转换
  • 如果一个运算符拥有两个运算元,那么它是二元运算符

    • 比如 2 + 3

8.2. 认识运算符

  • 比如加号 +、乘号 *、减号 - 、除号/

  • 几乎所有的编程语言都有各种各样的运算符(也被称之为操作符,operators)

  • 但是常见的高级语言运算符都是相似的,学了JavaScript运算符很容易掌握C/C++/OC/Python等语言的运算符

  • 计算机最基本的操作就是执行运算,执行运算时就需要使用运算符来操作

    • console.log(20 + 30); +号就是一个运算符
    • console.log(20 * 30); *号也是一个运算符
  • JavaScript按照使用场景的不同将运算符分成了很多种类型

    • 算术运算符
    • 赋值运算符
    • 关系(比较)运算符
    • 逻辑运算符
    • 位运算符

8.3. 算术运算符

  • 算术运算符用在数学表达式中, 它的使用方式和数学中一样
  • 算术运算符是对数据进行计算的符号
运算符 运算规则 范例 结果
+ 加法 2+3 5
+ 连接字符串 ‘中’+’国’ ‘中国’
- 减法 2-3 -1
* 乘法 2*3 6
/ 除法 5/2 2.5
% 取余数 5%2 1
** 幂(ES7) 2**3 8

8.4. 赋值运算符

  • =被称之为赋值( assignments )运算符

  • = 是一个运算符,而不是一个有着“魔法”作用的语言结构

    • 语句 x = value 将值 value 写入 x 然后返回 x。
  • 链式赋值(Chaining assignments)

    1
    2
    3
    var a, b, c;
    a = b = c = 2 + 2;
    console.log(a,b,c);
    • 链式赋值从右到左进行计算
    • 首先,对最右边的表达式 2 + 2 求值,然后将其赋给左边的变量:c、b 和 a
    • 最后,所有的变量共享一个值
    • 但是从代码的可读性的角度来说,不推荐这种写法

8.4.1. 原地修改

  • 什么是原地修改(Modify-in-place)

    • 对一个变量做运算,并将新的结果存储在同一个变量中

      1
      2
      3
      var n = 10;
      n = n + 5;
      n = n * 2;
  • 可以使用运算符 += 和 *= 来缩写这种表示

    1
    2
    3
    var n = 10;
    n += 5;
    n *= 2;
  • 所有算术和位运算符都有简短的“修改并赋值”运算符:/= 和 -= 等

8.4.2. 自增、自减

  • 对一个数进行加一、减一是最常见的数学运算符之一

    • 自增 ++ 将变量加1
    • 自减 – 将变量减1
  • 注意:自增/自减只能应用于变量

    • 将其应用于数值(比如 5++)则会报错
  • 运算符 ++ 和 – 可以置于变量前,也可以置于变量后

    • 当运算符置于变量后,被称为“后置形式”(postfix form):counter++
    • 当运算符置于变量前,被称为“前置形式”(prefix form):++counter
    • 两者都做同一件事:将变量 counter 与 1 相加
  • 有什么区别

    • 前置形式返回一个新的值,但后置返回原来的值
    • counter++:先运算,后自增
    • ++counter:先自增,后运算
  • 操作符可以作用于任何值

  • 字符串。有效数值形式,转换为数值再应用改变

  • 字符串。无效数值形式,值为NaN

  • 浮点数。应用于变量进行加/减1

  • 布尔值。false转换为0,true转换为1,再进行应用改变

  • 对象。调用对象的valueOf()/toString() 方法后再应用改变

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var s1 = "3";
var s2 = "a";
var s3 = false;
var s4 = 1.1;
var s5 = {
valueOf: function(){
return -1;
}
}
++s1;
s2--;
--s3;
s4++;
--s5;
// 4 NaN -1 2.1 -2
console.log(s1,s2,s3,s4,s5);

8.4.3. 一元加减

  • 一元加由+表示,放在变量前头

    • 对数值没有任何影响
    • 对非数值,会执行与Number()一样的类型转换
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    var s1 = "3";
    var s2 = "a";
    var s3 = "";
    var s4 = "0x70";
    var s5 = null;
    var s6 = false;
    var s7 = 1.1;
    var s8 = {
    valueOf(){
    return -1;
    }
    }

    s1 = +s1;
    s2 = +s2;
    s3 = +s3;
    s4 = +s4;
    s5 = +s5;
    s6 = +s6;
    s7 = +s7;
    s8 = +s8;
    // 3 NaN 0 112 0 0 1.1 -1
    console.log(s1,s2,s3,s4,s5,s6,s7,s8);
  • 一元减由-表示,放在变量前头

    • 把数值变成负值
    • 非数值遵循Number()一样的类型转换,再取负值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    var s1 = "3";
    var s2 = "a";
    var s3 = "";
    var s4 = "0x70";
    var s5 = null;
    var s6 = false;
    var s7 = 1.1;
    var s8 = {
    valueOf(){
    return -1;
    }
    }

    s1 = -s1;
    s2 = -s2;
    s3 = -s3;
    s4 = -s4;
    s5 = -s5;
    s6 = -s6;
    s7 = -s7;
    s8 = -s8;
    // -3 NaN -0 -112 -0 -0 -1.1 1
    console.log(s1,s2,s3,s4,s5,s6,s7,s8);

8.5. 比较运算符

  • 在数学中有很多用于比较大小的运算符,在JavaScript中也有相似的比较

    • 大于 / 小于:a > b,a < b
    • 大于等于 / 小于等于:a >= b,a <= b
    • 检查两个值的相等:a == b,请注意双等号 == 表示相等性检查,而单等号 a = b 表示赋值
    • 检查两个值不相等:不相等在数学中的符号是 ≠,但在 JavaScript 中写成 a != b
  • 比较运算符的结果都是Boolean类型的

运算符 运算规则 范例 结果
== 相等 4 == 3 false
!= 不等于 4 != 3 true
> 小于 4 > 3 true
< 大于 4 < 3 false
>= 大于等于 4 >= 3 false
<= 小于等于 4 <= 3 true

8.6. 逻辑运算符

  • 逻辑运算符,主要是由三个
    • ||(或),&&(与),!(非)
    • 它可以将多个表达式或者值放到一起来获取到一个最终的结果
运算符 运算规则 范例 结果
&& 与:同时为真 false & true false
|| 或:一个为真 false or true true
! 非:取反 !false true

8.6.1. 逻辑或的本质

  • ||(或)两个竖线符号表示“或”运算符(也称为短路或)

    1
    result = a || b;
    • 从左到右依次计算操作数
    • 处理每一个操作数时,都将其转化为布尔值(Boolean)
    • 如果结果是 true,就停止计算,返回这个操作数的初始值
    • 如果所有的操作数都被计算过(也就是,转换结果都是 false),则返回最后一个操作数
  • 注意:返回的值是操作数的初始形式,不会转换为Boolean类型

  • 换句话说,一个或运算 || 的链,将返回第一个真值,如果不存在真值,就返回该链的最后一个值

    1
    2
    // 获取有效值
    var message = info|| "默认值";

8.6.2. 逻辑与的本质

  • &&(或)两个竖线符号表示“与”运算符(也称为短路与)

    1
    result = value1 && value2 && value3;
    • 从左到右依次计算操作数
    • 在处理每一个操作数时,都将其转化为布尔值(Boolean)
    • 如果结果是 false,就停止计算,并返回这个操作数的初始值(一般不需要获取到初始值)
    • 如果所有的操作数都被计算过(例如都是真值),则返回最后一个操作数
  • 换句话说,与运算&& 返回第一个假值,如果没有假值就返回最后一个值

    1
    2
    3
    4
    5
    6
    7
    8
    var obj = {
    friend:{
    eating: function(){
    console.log("eating");
    }
    }
    }
    obj&&obj.friend&&obj.friend.eating&&obj.friend.eating();

8.6.3. !(非)

  • 逻辑非运算符接受一个参数,并按如下运算

    • 步骤一:将操作数转化为布尔类型true/false
    • 步骤二:返回相反的值
    1
    2
    3
    var message = "Hello World";
    // false
    console.log(!message);
  • 两个非运算 !! 用来将某个值转化为布尔类型

    • 第一个非运算将值转化为布尔类型并取反,第二个非运算再次取反
    • 最后就得到了一个任意值到布尔值的转化
    1
    2
    3
    var message = "Hello World";
    // true
    console.log(!!message);

8.7. 位运算符

  • 按位非 ~:数值二进制的每一位取反

    1
    2
    3
    4
    5
    6
    // 0000 0000 0000 0000 0000 0000 0001 1001
    var num1 = 25;
    // 1111 1111 1111 1111 1111 1111 1110 0110
    var num2 = ~num1;
    // -26
    console.log(num2);
    • 值的结果是对数值取反并减一
    1
    2
    3
    4
    5
    6
    7
    8
    var num1 = 25;
    var num2 = ~num1;
    // 11001
    console.log(num1.toString(2));
    // -11010
    console.log(num2.toString(2));
    // 26
    console.log(-num1-1);
  • 按位与 &:将两个运算元二进制每一位对齐,都为1时结果为1,其余都为0

    1
    2
    3
    4
    5
    6
    7
    8
    // 0000 0000 0000 0000 0000 0000 0001 1001
    var a = 25;
    // 0000 0000 0000 0000 0000 0000 0000 0011
    var b = 3;
    // 0000 0000 0000 0000 0000 0000 0000 0001
    var result = a & b;
    // 1
    console.log(result);
  • 按位或 |:将两个运算元二进制每一位对齐,有1时结果为1,都为0时结果为0

    1
    2
    3
    4
    5
    6
    7
    8
    // 0000 0000 0000 0000 0000 0000 0001 1001
    var a = 25;
    // 0000 0000 0000 0000 0000 0000 0000 0011
    var b = 3;
    // 0000 0000 0000 0000 0000 0000 0001 1011
    var result = a | b;
    // 27
    console.log(result);
  • 按位异或 ^:将两个运算元二进制每一位对齐,相同时结果为0,不同时结果为1

    1
    2
    3
    4
    5
    6
    7
    8
    // 0000 0000 0000 0000 0000 0000 0001 1001
    var a = 25;
    // 0000 0000 0000 0000 0000 0000 0000 0011
    var b = 3;
    // 0000 0000 0000 0000 0000 0000 0001 1010
    var result = a ^ b;
    // 26
    console.log(result);

8.8. 运算符的优先级

8.9. === 和 == 的区别

8.9.1. ==

  • 普通的相等性检查 == 存在一个问题,它不能区分出 0 和 false,或者空字符串和 false这类运算

    • 这是因为在比较不同类型的值时,处于判断符号 == 两侧的值会先被转化为数字

    • 空字符串和 false 也是如此,转化后它们都为数字 0

      1
      2
      3
      4
      5
      6
      7
      8
      var x = "";
      var y = false;
      // 0
      console.log(Number(x));
      // 0
      console.log(Number(y));
      // true
      console.log(x==y);
  • 但是 null会被当成一个对象和原生类型进行比较

    1
    2
    3
    4
    5
    6
    // false
    console.log(null=="");
    // false
    console.log(null==0);
    // true
    console.log(null==undefined);
  • https://262.ecma-international.org/5.1/#sec-11.9.3

  1. If Type(x) is the same as Type(y)

  2. If x is null and y is undefined, return true.

  3. If x is undefined and y is null, return true.

  4. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).

  5. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.

  6. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.

  7. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).

  8. If Type(x) is either String or Number and Type(y) is Object, return the result of the comparison x == ToPrimitive(y).

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var obj = {
    name: "why",
    age: 18,
    [Symbol.toPrimitive](){
    return 123;
    }
    }
    // true
    console.log(123==obj);
  9. If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y.

  10. Return false.

8.9.2. ===

  • 如果需要区分 0 和 false,该怎么办?

    • 严格相等运算符 === 在进行比较时不会做任何的类型转换
    • 换句话说,如果 a 和 b 属于不同的数据类型,那么 a === b 不会做任何的类型转换而立刻返回 false
  • 同样的,“不相等”符号 != 类似,“严格不相等”表示为 !==

  • 严格相等的运算符虽然写起来稍微长一些,但是它能够很清楚地显示代码意图,降低犯错的可能性

9. JavaScript分支语句

9.1. 程序的执行顺序

  • 在程序开发中,程序有三种不同的执行方式
    • 顺序:从上向下,顺序执行代码
    • 分支:根据条件判断,决定执行代码的 分支
    • 循环:让特定代码重复执行

9.2. 代码块的理解

  • 代码块是多行执行代码的集合,通过一个花括号 {} 放到了一起

    • 在开发中,一行代码很难完成某一个特定的功能,就会将这些代码放到一个代码块中
    1
    2
    3
    4
    5
    {
    var name = "why";
    var message = "My name is " + name;
    console.log(message);
    }
  • 在JavaScript中,可以通过流程控制语句来决定如何执行一个代码块

    • 通常会通过一些关键字来告知js引擎代码要如何被执行
    • 比如分支语句、循环语句对应的关键字等

9.3. 什么是分支结构

  • 程序是生活的一种抽象, 只是用代码表示了出来

    • 在开发中,需要根据一定的条件, 来决定代码的执行方向
    • 如果条件满足,才能做某件事情
    • 如果条件不满足,就做另外一件事情
  • 分支结构

    • 分支结构的代码就是根据条件来决定代码的执行
    • 分支结构的语句被称为判断结构或者选择结构
    • 几乎所有的编程语言都有分支结构(C、C++、OC、JavaScript等等)
  • JavaScript中常见的分支结构有

    • if分支结构
    • switch分支结构

9.4. if分支语句

  • if分支结构有三种
    • 单分支结构
      • if..
    • 多分支结构
      • if..else..
      • if..else if..else..

9.4.1. 单分支语句:if

  • if(…) 语句计算括号里的条件表达式,如果计算结果是 true,就会执行对应的代码块

    1
    2
    3
    4
    // 如果条件成立
    if (条件判断){
    // 执行代码块
    }

  • 如果代码块中只有一行代码,那么{}可以省略

  • if (…) 语句会计算圆括号内的表达式,并将计算结果转换为布尔型(Boolean)

    • 转换规则和Boolean函数的规则一致
    • 数字 0、空字符串 “”、null、undefined 和 NaN 都会被转换成 false
      • 因为它们被称为“假值(falsy)”
    • 其他值被转换为 true,所以它们被称为“真值(truthy)”

9.4.2. 多分支语句:if.. else..

  • 多分支语句一:if.. else..
    • if 语句有时会包含一个可选的 “else” 块
    • 如果判断条件不成立,就会执行它内部的代码
1
2
3
4
5
if (条件判断){
// 如果条件成立,执行代码块
}else {
// 如果条件不成立,执行代码块
}

  • 案例一:如果分数超过90分去游乐场,否则去上补习班
1
2
3
4
5
6
7
var score = prompt("请输入分数");
score = Number(score);
if(score>=90){
alert("游乐场");
}else{
alert("补习班");
}
  • 案例二:m=20,n=30,比较两个数字的大小,获取较大的那个数字

    1
    2
    3
    4
    5
    6
    7
    var m = 20;
    var n = 30;
    if(m>n){
    console.log(m);
    }else{
    console.log(n);
    }

9.4.3. 多分支结构: if.. else if.. else..

  • 多分支结构:if.. else if.. else..

    • 有时需要判断多个条件

    • 可以通过使用 else if 子句实现

      1
      2
      3
      4
      5
      6
      7
      8
      9
      if (条件1){
      // 代码块1
      }else if(条件2){
      // 代码块2
      }else if(条件3){
      // 代码块3
      }else{
      // 所有条件不成立,执行代码块
      }

  • 案例:分数评级

    • 考试分数大于90:优秀
    • 大于80小于等于90:良好
    • 大于60小于等于80:合格
    • 小于60分:不及格
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var score = prompt("请输入分数");
    score = Number(score);
    if(score>90){
    alert("优秀");
    }else if(score>80){
    alert("良好");
    }else if(score>=60){
    alert("及格");
    }else{
    alert("不及格");
    }

9.4.4. 三元运算符

  • 有时需要根据一个条件去赋值一个变量

    • 比如比较数字大小的时候,获取较大的数字
    • 这个时候if else语句就会显得过于臃肿,可以用更加简介的方法-三元运算符
  • 三元运算符使用格式如下

    1
    var result = condition ? value1: value2;
    • 计算条件结果,如果结果为真,则返回 value1,否则返回 value2
  • 条件运算符:?

    • 这个运算符通过问号 ? 表示
    • 有时它被称为三元运算符,被称为“三元”是因为该运算符中有三个操作数(运算元)
    • 实际上它是 JavaScript 中唯一一个有这么多操作数的运算符
  • 案例一:变量赋初值

    1
    2
    3
    4
    var info = {
    name: "why"
    }
    var obj = info?info:{};
  • 案例二:m=20,n=30,比较两个数字的大小,获取较大的那个数字

    1
    2
    3
    var m = 20;
    var n = 30;
    console.log(m>n?m:n);
  • 案例三:判断一个人是否是成年人了

    1
    2
    3
    var age = prompt("输入年龄");
    age = Number(age);
    var result = age>=18?"成年":"未成年";

9.5. switch语句

  • switch是分支结构的一种语句

    • 它是通过判断表达式的结果(或者变量)是否等于case语句的常量,来执行相应的分支体的
    • 注意:这里的相等是严格相等
      • 被比较的值必须是相同的类型才能进行匹配
  • 与if语句不同的是,switch语句只能做值的相等判断(使用全等运算符 ===),而if语句可以做值的范围判断

  • switch的语法

    • switch 语句有至少一个 case 代码块和一个可选的 default 代码块

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      switch(变量){
      case 常量1:
      // 语句1
      break;
      case 常量2:
      // 语句2
      break;
      default:
      // 语句3
      }
  • case穿透问题

    • 一条case语句结束后,缺少break关键字时,会自动执行下一个case的语句

      1
      2
      3
      4
      5
      6
      7
      8
      switch(变量){
      case 常量1:
      // 语句1
      case 常量2:
      // 语句2
      default:
      // 语句3
      }
    • 这种现象被称之为case穿透

  • break关键字

    • 通过在每个case的代码块后添加break关键字来解决case穿透问题

10. 认识循环

  • 循环是一种重复运行同一代码的方法

    • 如果是对某一个列表进行循环操作,称之为 遍历(traversal)或者迭代(iteration)
  • 在JavaScript中支持三种循环方式

    • while循环
    • do..while循环
    • for循环

10.1. while循环

  • while循环的语法如下

    • 当条件成立时,执行代码块
    • 当条件不成立时,跳出代码块
    1
    2
    3
    while(循环条件){
    // 循环代码
    }

  • 如果条件一直成立(为true),那么会产生死循环

    • 必须通过关闭页面来停止死循环
    • 开发中一定要避免死循环的产生
  • while循环练习

    • 打印10次Hello World

      1
      2
      3
      4
      5
      var i = 0; 
      while(i < 10){
      console.log("Hello World");
      i++;
      }
    • 打印0~99的数字

      1
      2
      3
      4
      var i = 0; 
      while(i < 100){
      console.log(i++);
      }
    • 练习三:计算0~99的数字和

      1
      2
      3
      4
      5
      6
      var sum = 0;
      var i = 0;
      while(i < 100){
      sum+=i++;
      }
      console.log(sum);
    • 练习四:计算0~99所有奇数的和

      1
      2
      3
      4
      5
      6
      7
      8
      9
      var sum = 0;
      var i = 0;
      while(i < 100){
      if(i%2!=0){
      sum+=i;
      }
      i++;
      }
      console.log(sum);
    • 练习五:计算0~99所有偶数的和

      1
      2
      3
      4
      5
      6
      7
      8
      9
      var sum = 0;
      var i = 0;
      while(i < 100){
      if(i%2==0){
      sum+=i;
      }
      i+=2;
      }
      console.log(sum);

10.2. do..while循环

  • do..while的特点是不管条件成不成立,do循环体都会先执行一次

    1
    2
    3
    4
    do {
    // 循环代码
    }
    while(循环条件);

  • do…while练习

    • 打印10次Hello World

      1
      2
      3
      4
      5
      var i = 0; 
      do{
      console.log("Hello World");
      i++;
      }while(i < 10);
    • 打印0~99的数字

      1
      2
      3
      4
      var i = 0; 
      do{
      console.log(i++);
      }while(i < 100);
    • 练习三:计算0~99的数字和

      1
      2
      3
      4
      5
      6
      var sum = 0;
      var i = 0;
      do{
      sum+=i++;
      }while(i < 100);
      console.log(sum);
    • 练习四:计算0~99所有奇数的和

      1
      2
      3
      4
      5
      6
      7
      8
      9
      var sum = 0;
      var i = 0;
      do{
      if(i%2!=0){
      sum+=i;
      }
      i++;
      }while(i < 100);
      console.log(sum);
    • 练习五:计算0~99所有偶数的和

      1
      2
      3
      4
      5
      6
      7
      8
      9
      var sum = 0;
      var i = 0;
      do{
      if(i%2==0){
      sum+=i;
      }
      i+=2;
      }while(i < 100);
      console.log(sum);

10.3. for循环

  • for 循环更加复杂,但它是最常使用的循环形式

    1
    2
    3
    for(begin; condition; step){
    //循环代码块
    }

10.3.1. 通过例子解释for

1
2
3
for(let i = 0; i < 10; i++){
console.log(i);
}
语句段 例子 执行过程
begin let i = 0 进入循环时执行一次
condition i<3 在每次循环迭代之前检查,如果为false,停止循环
body-循环体 console.log(i) 条件为真时,重复运行
step i++ 在每次循环体迭代后执行
  • begin 执行一次,然后进行迭代
  • 每次检查 condition 后,执行 body 和 step

10.3.2. for循环的练习

  • 打印10次Hello World

    1
    2
    3
    for(var i = 0; i < 10; i++){
    console.log("Hello World");
    }
  • 打印0~99的数字

    1
    2
    3
    for(var i = 0; i < 100; i++){
    console.log(i);
    }
  • 练习三:计算0~99的数字和

    1
    2
    3
    4
    5
    var sum = 0;
    for(var i = 0; i < 100; i++){
    sum+=i;
    }
    console.log(sum);
  • 练习四:计算0~99所有奇数的和

    1
    2
    3
    4
    5
    6
    7
    var sum = 0;
    for(var i = 0; i < 100; i++){
    if(i%2!=0){
    sum+=i;
    }
    }
    console.log(sum);
  • 练习五:计算0~99所有偶数的和

    1
    2
    3
    4
    5
    6
    7
    var sum = 0;
    for(var i = 0; i < 100; i++){
    if(i%2==0){
    sum+=i;
    }
    }
    console.log(sum);

10.4. 双层for循环

10.4.1. 包含❤的矩形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 创建一个p元素
var p = document.createElement("p");
// p元素内容初始为空
p.innerHTML = "";
for(var i = 0; i < 6; i++){
// 横排连打6个星
for(var j = 0; j < 6; j++){
p.innerHTML+="❤ ";
}
// 打完一行后加打一个换行符
p.innerHTML+="<br>";
}
// 将p元素添加到body元素中
document.body.append(p);

10.4.2. 包含❤的三角

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 创建一个p元素
var p = document.createElement("p");
// p元素内容初始为空
p.innerHTML = "";
for(var i = 0; i < 6; i++){
// 根据行数打星
for(var j = 0; j <= i; j++){
p.innerHTML+="❤ ";
}
// 打完一行后加打一个换行符
p.innerHTML+="<br>";
}
// 将p元素添加到body元素中
document.body.append(p);

10.4.3. 九九乘法表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 创建一个table元素
var table = document.createElement("table");
// 边框合并样式
table.style.borderCollapse = "collapse";
for(var i = 1; i < 10; i++){
// 创建行
var tr = document.createElement("tr");
table.append(tr);
for(var j = 1; j <= i; j++){
// 创建每行的列
var td = document.createElement("td");
td.innerHTML=`${j}x${i}=${i*j}`;
// 每列添加边框
td.style.border = "1px solid #999";
// 添加内间距
td.style.padding = "8px 16px";
tr.append(td);
}
}
document.body.append(table);

10.5. 循环控制

  • 循环的跳转(控制)

    • 在执行循环过程中,遇到某一个条件时,可能想要做一些事情
    • 比如循环体不再执行(即使没有执行完),跳出循环
    • 比如本次循环体不再执行,执行下一次的循环体
  • 循环的跳转控制

    • break:直接跳出循环,循环结束
      • break 某一条件满足时,退出循环,不再执行后续重复的代码
    • continue:跳过本次循环次, 执行下一次循环体
      • continue 指令是 break 的“轻量版”
      • continue 某一条件满足时,不执行后续重复的代码

10.6. 猜数字游戏

  • 猜数字游戏规则
    • 电脑随机生成一个0~99之间的数字
    • 玩家有7次猜测的机会
    • 玩家猜测一个数字, 输入到程序中
    • 电脑根据输入的数字打印:猜大了/猜小了/猜对了的情况
    • 猜对了, 那么游戏结束,显示恭喜您
    • 7次机会用完打印:您的次数用完了, 您失败了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 随机生成数字
var num = Math.floor(Math.random()* 100);
// 控制台输出答案,作弊用
console.log(num);

var i = 0;
for(;i < 7; i++){
// 浏览器接受用户输入,但是结果是字符串
var a = prompt("输入数字");
// string
// console.log(typeof a);
// 字符串转为数字
a = Number(a);
if(a > num){
alert("猜大了");
}
else if(a === num){
alert("猜对了\n游戏结束,显示恭喜您");
break;
}else{
alert("猜小了");
}
}
if(i==7){
alert("您的次数用完了, 您失败了");
}

10.7. 循环的总结

  • 三种循环总结

    • while:每次迭代之前都要检查条件
    • do..while:每次迭代后都要检查条件
    • for (;;):每次迭代之前都要检查条件,可以使用其他设置
  • break/continue 可以对循环进行控制

本文结束  感谢您的阅读