JavaScript高级程序设计(重点记录)-持续更新

JavaScript权威指南阅读

1.JavaScript简介

一个完整的JavaScript由以下三部分组成
JavaScript一种专为与网页交互而设计的脚本语言

  • ECMAScript 核心

web浏览器是ECMAScript的宿主环境之一,宿主环境提供了基本的ECMAScript的实现,同时也会提供该语言的扩展,以便语言与环境之间对接交互

  • 文档对象模型 DOM

是针对 XML 但经过扩展用于 HTML 的应用程序编程接口DOM 把整个页面映射为一个多层节点结构。HTML或 XML 页面中的每个组成部分都是某种类型的节点,这些节点又包含着不同类型的数据

<html>
 <head>
 <title>Sample Pagetitle>
 head>
 <body>
 <p>Hello World!p>
 body>
html> 

JavaScript高级程序设计(重点记录)-持续更新_第1张图片

  • 浏览器对象模型 BOM

可以访问和操作浏览器窗口,主要用来处理浏览器窗口和框架

2.在HTML中使用JavaScript

向html中插入script元素主要方法就是使用

现代 Web 应用程序一般都把全部 JavaScript 引用放在body元素中页面内容的后面。在解析包含的 JavaScript 代码之前,页面的内容将完全呈现在浏览器中
JavaScript高级程序设计(重点记录)-持续更新_第2张图片

第二章小结

JavaScript高级程序设计(重点记录)-持续更新_第3张图片

3.基本概念

ECMAScript 中的一切(变量、函数名和操作符)都区分大小写

所谓标识符,就是指变量、函数、属性的名字,或者函数的参数

第一个字符必须是一个字母、下划线(_)或一个美元符号$
其他字符可以是字母、下划线、美元符号或数字。
按照惯例,ECMAScript 标识符采用驼峰大小写格式
不能把关键字、保留字、true、false 和 null 用作标识符

虽然语句结尾的分号不是必需的,但我们建议任何时候都不要省略它

全部关键字
break do instanceof typeof case else new var catch finally return void
continue for switch while debugger* function this with default if throw
delete in try 
全部保留字
abstract enum int short
boolean export interface static
byte extends long super
char final native synchronized
class float package throws
const goto private transient
debugger implements protected volatile
double import public let yield
定义一个变量
var message; //定义一个名为message的变量
该变量可以用来保存任何值(像这样未经过初始化的变量,会保存一个特殊的值——undefined
初始化变量
var message = "hi"; 
像这样初始化变量并不会把它标记为字符串类型;
初始化的过程就是给变量赋一个值那么简单

用 var 操作符定义的变量将成为定义该变量的作用域中的局部变量。也就是说,
如果在函数中使用 var 定义一个变量,那么这个变量在函数退出后就会被销毁
JavaScript高级程序设计(重点记录)-持续更新_第4张图片

省略var操作符 ,创建一个全局变量
JavaScript高级程序设计(重点记录)-持续更新_第5张图片

注意事项

虽然省略 var 操作符可以定义全局变量,但这也不是我们推荐的做法。因为在局部作用域中定义的全局变量很难维护,而且如果有意地忽略了 var 操作符,也会由于相应变量不会马上就有定义而导致不必要的混乱。给未经声明的变量赋值在严格模式下会导致抛出 ReferenceError 错误

数据类型
基本数据类型
Undefined、Null、Boolean、Number和 String
引用数据类型
Object ,本质上是由一组无序的键值对组成的
typeof操作符

检测给定变量的数据类型

 “undefined”——如果这个值未定义;
 “boolean”——如果这个值是布尔值;
 “string”——如果这个值是字符串;
 “number”——如果这个值是数值;
 “object”——如果这个值是对象或 null;
 “function”——如果这个值是函数。

undefined类型

Undefined 类型只有一个值,即特殊的 undefined。在使用 var 声明变量但未对其加以初始化时,这个变量的值就是 undefined
在这里插入图片描述
等价于
在这里插入图片描述
一般而言,不存在需要显式地把一个变量设置为 undefined 值的情况。未经初始化的值默认就会取得 undefined 值
JavaScript高级程序设计(重点记录)-持续更新_第6张图片
第二个警告框传递给 alert()函数的是尚未声明的变量 age,则会导致一个错误。对于尚未声明过的变量,只能执行一项操作,即使用 typeof 操作符检测其数据类型
对未经声明的变量调用 delete 不会导致错误,但这样做没什么实际意义,而且在严格模式下确实会导致错误
JavaScript高级程序设计(重点记录)-持续更新_第7张图片

null类型

Null 类型是第二个只有一个值的数据类型,这个特殊的值是 null。从逻辑角度来看,null 值表示一个空对象指针,而这也正是使用 typeof 操作符检测 null 值时会返回"object"的原因
在这里插入图片描述
如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为 null 而不是其他值。这样一来,只要直接检查 null 值就可以知道相应的变量是否已经保存了一个对象的引用
JavaScript高级程序设计(重点记录)-持续更新_第8张图片

Boolean类型

该类型只有两个字面值:true 和 false,并且区分大小写

ECMAScript 中所有类型的值都有与这两个 Boolean 值等价的值。要将一个值转换为其对应的 Boolean 值,可以调用转型函数 Boolean()
在这里插入图片描述
可以对任何数据类型调用Boolean()函数,而且总会返回一个Boolean值

各种数据类型转换规则
在这里插入图片描述
JavaScript高级程序设计(重点记录)-持续更新_第9张图片
这些转换规则对理解流控制语句(如 if 语句)自动执行相应的 Boolean 转换非常重要

Number类型
整数数值
//十进制整数
var intNum = 55; // 整数

//八进制
整数还可以通过八进制(以 8 为基数)或十六进制(以 16 为基数)的字面值来表示
八进制字面值的第一位必须是零(0),然后是八进制数字序列(07)。如果字面值中的数值超出了范围,那么前导零将被忽略,后面的数值将被当作十进制数值解析
var octalNum1 = 070; // 八进制的 56
var octalNum2 = 079; // 无效的八进制数值——解析为 79
var octalNum3 = 08; // 无效的八进制数值——解析为 8

//十六进制
十六进制字面值的前两位必须是 0x,后跟任何十六进制数字(09AF)。其中,字母 AF可以大写,也可以小写
var hexNum1 = 0xA; // 十六进制的 10
var hexNum2 = 0x1f; // 十六进制的 31

在进行算术计算时,所有以八进制和十六进制表示的数值最终都将被转换成十进制数值

鉴于 JavaScript 中保存数值的方式,可以保存正零(+0)和负零(-0)。正零和负零被认为相等
浮点数值
所谓浮点数值,就是该数值中必须包含一个小数点,并且小数点后面必须至少有一位数字
var floatNum1 = 1.1;
var floatNum2 = 0.1;
var floatNum3 = .1; // 有效,但不推荐

由于保存浮点数值需要的内存空间是保存整数值的两倍,如果小数点后面没有跟任何数字,那么这个数值就可以作为整数值来保存。如果浮点数值本身表示的就是一个整数(如 1.0),那么该值也会被转换为整数
var floatNum1 = 1.; // 小数点后面没有数字——解析为 1
var floatNum2 = 10.0; // 整数——解析为 10

对于那些极大或极小的数值,可以用 e 表示法(即科学计数法)表示的浮点数值表示
用 e 表示法表示的数值等于 e 前面的数值乘以 10 的指数次幂
前面是一个数值(可以是整数也可以是浮点数),中间是一个大写或小写的字母 E,后面是 10 的幂中的指数,该幂值将用来与前面的数相乘
var floatNum = 3.125e7; // 等于 31250000 

也可以使用 e 表示法表示极小的数值,如 0.00000000000000003,这个数值可以使用更简洁的 3e-17表示

浮点数值的最高精度是 17 位小数,但在进行算术计算时其精确度远远不如整数
0.10.2的结果不是 0.3,而是 0.30000000000000004

数值存储范围
最小数值保存在 Number.MIN_VALUE,这个值是 5e-324
最大数值保存在 Number.MAX_VALUE,这个值是 1.7976931348623157e+308

NaN

非数值(Not a Number)是一个特殊的数值,这个数值用于表示一个本来要返回数值的操作数未返回数值的情况(这样就不会抛出错误了)
在 ECMAScript中,任何数值除以 0会返回 NaN①,因此不会影响其他代码的执行

实际上只有 0 除以 0 才会返回 NaN,正数除以 0 返回 Infinity,负数除以 0 返回-Infinity

NaN特点

  • 任何涉及 NaN 的操作(例如 NaN/10)都会返回 NaN
  • NaN 与任何值都不相等,包括 NaN 本身
alert(NaN == NaN); //false 

isNaN()函数
这个函数接受一个参数,该参数可以是任何类型,而函数会帮我们确定这个参数是否“不是数值”

isNaN()在接收到一个值之后,会尝试将这个值转换为数值。某些不是数值的值会直接转换为数值 Number()函数
而任何不能被转换为数值的值都会导致这个函数返回 true
在这里插入图片描述

isNaN()确实也适用于对象。在基于对象调用isNaN()函数时,会首先调用对象的 valueOf()方法,然后确定该方法返回的值是否可以转换为数值。如果不能,则基于这个返回值再调用 toString()方法,再测试返回值

数值转换

非数值转换为数值

Number() //可以用于任何数据类型
parseInt() //专门用于把字符串转换成数值
parseFloat() //专门用于把字符串转换成数值3 个函数对于同样的输入会有返回不同的结果

Number()函数的转换规则如下

如果是 Boolean 值,true 和 false 将分别被转换为 1 和 0。
 如果是数字值,只是简单的传入和返回。
 如果是 null 值,返回 0。
 如果是 undefined,返回 NaN。

 如果是字符串,遵循下列规则:

  • 如果字符串中只包含数字(包括前面带正号或负号的情况),则将其转换为十进制数值,即"1"会变成 1,"123"会变成 123,而"011"会变成 11(注意:前导的零被忽略了)
  • 如果字符串中包含有效的浮点格式,如"1.1",则将其转换为对应的浮点数值(同样,也会忽略前导零)
  • 如果字符串中包含有效的十六进制格式,例如"0xf",则将其转换为相同大小的十进制整数值
  • 如果字符串是空的(不包含任何字符),则将其转换为 0;
  • 如果字符串中包含除上述格式之外的字符,则将其转换为 NaN。

如果是对象,则调用对象的 valueOf()方法,然后依照前面的规则转换返回的值。如果转换
的结果是 NaN,则调用对象的 toString()方法,然后再次依照前面的规则转换返回的字符
串值。

例子

注意:一元加操作符 的操作与 Number()函数相同

praseInt()函数

处理整数的时候更常用的是parseInt()函数

parseInt()函数在转换字符串时,更多的是看其是否符合数值模式。
它会忽略字符串前面的空格,直至找到第一个非空格字符.如果第一个字符不是数字字符或者负号,parseInt()就会返回 NaN;

parseInt()转换空字符串会返回 NaN(Number()对空字符返回 0)
如果第一个字符是数字字符,parseInt()会继续解析第二个字符,直到解析完所有后续字符或者遇到了一个非数字字符
如果字符串以"0x"开头且后跟数字字符,就会将其当作一个十六进制整数
如果字符串以"0"开头且后跟数字字符,则会将其当作一个八进制数来解析。
JavaScript高级程序设计(重点记录)-持续更新_第10张图片

注意

  • 在 ECMAScript 5 JavaScript 引擎中,parseInt()已经不具有解析八进制值的能力
  • 可以为praseInt()函数提供第二个参数
var num = parseInt("0xAF", 16); //175 
var num1 = parseInt("AF", 16); //175
var num2 = parseInt("AF"); //NaN 
var num1 = parseInt("10", 2); //2 (按二进制解析)
var num2 = parseInt("10", 8); //8 (按八进制解析)
var num3 = parseInt("10", 10); //10 (按十进制解析)
var num4 = parseInt("10", 16); //16 (按十六进制解析)
建议无论在什么情况下都明确指定基数
praseFloat()函数
  • 从第一个字符(位置 0)开始解析每个字符。而且也是一直解析到字符串末尾,或者解析到遇见一个无效的浮点数字字符为止
  • 字符串中的第一个小数点是有效的,而第二个小数点就是无效的了
  • parseFloat()与 parseInt()的第二个区别在于它始终都会忽略前导的零
  • parseFloat()只解析十进制值,因此它没有用第二个参数指定基数的用法
  • parseFloat()可以识别所有浮点数值格式
  • 如果字符串包含的是一个可解析为整数的数(没有小数点,或者小数点后都是零)parseFloat()会返回整数
var num1 = parseFloat("1234blue"); //1234 (整数)
var num2 = parseFloat("0xA"); //0
var num3 = parseFloat("22.5"); //22.5
var num4 = parseFloat("22.34.5"); //22.34
var num5 = parseFloat("0908.5"); //908.5
var num6 = parseFloat("3.125e7"); //31250000 
String类型

用于表示由零或多个 16 位 Unicode 字符组成的字符序列,即字符串。可以由双引号或单引号表示

特殊字符
JavaScript高级程序设计(重点记录)-持续更新_第11张图片
字符串的特点

  • ECMAScript 中的字符串是不可变的,也就是说,字符串一旦创建,它们的值就不能改变
  • 要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量
var lang = "Java";
lang = lang + "Script"; 
实现流程:
首先创建一个能容纳 10 个字符的新字符串,然后在这个字符串中填充"Java""Script",最后一步是销毁原来的字符串"Java"和字符串"Script",因为这两个字符串已经没用了

转换为字符串
两种方式

  • 使用几乎每个值都有的 toString()方法
  • 数值、布尔值、对象和字符串值都有的 toString()方法
  • 但 null 和 undefined 值没有toString()这个方法
var age = 11;
var ageAsString = age.toString(); // 字符串"11"
var found = true;
var foundAsString = found.toString(); // 字符串"true" 
  • 多数情况下,调用 toString()方法不必传递参数。但是,在调用数值的 toString()方法时,可以传递一个参数:输出数值的基数。默认情况下,toString()方法以十进制格式返回数值的字符串表示
var num = 10;
alert(num.toString()); // "10"
alert(num.toString(2)); // "1010"
alert(num.toString(8)); // "12"
alert(num.toString(10)); // "10"
alert(num.toString(16)); // "a" 
默认的(没有参数的)输出值与指定基数 10 时的输出值相同
  • 在不知道要转换的值是不是 null 或 undefined 的情况下,可以使用转型函数 String(),,这个函数能够将任何类型的值转换为字符串

String()函数遵循下列转换规则:
 如果值有 toString()方法,则调用该方法(没有参数)并返回相应的结果;
 如果值是 null,则返回"null";
 如果值是 undefined,则返回"undefined"。

var value1 = 10;
var value2 = true;
var value3 = null;
var value4;
alert(String(value1)); // "10"
alert(String(value2)); // "true"
alert(String(value3)); // "null"
alert(String(value4)); // "undefined" 

要把某个值转换为字符串,可以使用加号操作符把它与一个字符串("")加在一起。

Object类型

ECMAScript 中的对象其实就是一组数据和功能的集合,对象可以通过执行 new 操作符后跟要创建的对象类型的名称来创建

var o = new Object(); 
//构造函数(constructor)就是 Object()
  • 关键是要理解一个重要的思想:即在 ECMAScript 中,Object 类型是所有它的实例的基础
  • Object 类型所具有的任何属性和方法也同样存在于更具体的对象中

Object 的每个实例都具有下列属性和方法
JavaScript高级程序设计(重点记录)-持续更新_第12张图片

注意事项

从技术角度讲,ECMA-262 中对象的行为不一定适用于 JavaScript 中的其他对象。
浏览器环境中的对象,比如 BOM 和 DOM 中的对象,都属于宿主对象,因为它们是
由宿主实现提供和定义的。ECMA-262 不负责定义宿主对象,因此宿主对象可能会也
可能不会继承 Object。

操作符

ECMAScript 操作符的与众不同之处在于,它们能够适用于很多值,例如字符串、数字值、布尔值,甚至对象。不过,在应用于对象时,相应的操作符通常都会调用对象的 valueOf()和(或)toString()方法,以便取得可以操作的值。

一元操作符
只能操作一个值的操作符叫做一元操作符

递增与递减操作符

前置型
var age = 29;
++age;
<==>
var age = 29;
age = age + 1;
  • 执行前置递增和递减操作时,变量的值都是在语句被求值以前改变的
var age = 29;
var anotherAge = --age + 2;
alert(age); // 输出 28
alert(anotherAge); // 输出 30 
  • 前置递增和递减操作与执行语句的优先级相等,整个语句会从左至右被求值
var num1 = 2;
var num2 = 20;
var num3 = --num1 + num2; // 等于 21
var num4 = num1 + num2; // 等于 21 

后置性;后置递增和递减与前置递增和递减有一个非常重要的区别,即递增和递减操作是在包含它们的语句被求值之后才执行的

var num1 = 2;
var num2 = 20;
var num3 = num1-- + num2; // 等于 22
var num4 = num1 + num2; // 等于 21 

所有这 4 个操作符对任何值都适用,也就是它们不仅适用于整数,还可以用于字符串、布尔值、浮点数值和对象。在应用于不同的值时,递增和递减操作符遵循下列规则
JavaScript高级程序设计(重点记录)-持续更新_第13张图片

var s1 = "2";
var s2 = "z";
var b = false;
var f = 1.1;
var o = {
     
 valueOf: function() {
     
 return -1;
 }
};
s1++; // 值变成数值 3
s2++; // 值变成 NaN
b++; // 值变成数值 1
f--; // 值变成 0.10000000000000009(由于浮点舍入错误所致)
o--; // 值变成数值-2 
一元加减运算符
  • 一元加操作符以一个加号(+)表示,放在数值前面,对数值不会产生任何影响
var num = 25;
num = +num; // 仍然是 25 
  • 对非数值应用一元加操作符时,该操作符会像 Number()转型函数一样对这个值执行转换。布尔值 false 和 true 将被转换为 0 和 1,字符串值会被按照一组特殊的规则进行解析,而对象是先调用它们的 valueOf()和(或)toString()方法,再转换得到的值
var s1 = "01";
var s2 = "1.1";
var s3 = "z";
var b = false;
var f = 1.1;
var o = {
     
 valueOf: function() {
     
 return -1;
 }
};
s1 = +s1; // 值变成数值 1
s2 = +s2; // 值变成数值 1.1
s3 = +s3; // 值变成 NaN
b = +b; // 值变成数值 0
f = +f; // 值未变,仍然是 1.1
o = +o; // 值变成数值-1 
  • 一元减操作符主要用于表示负数,例如将 1 转换成-1。
var num = 25;
num = -num; // 变成了-25 
  • 将一元减操作符应用于数值时,该值会变成负数
  • 当应用于非数值时,一元减操作符遵循与一元加操作符相同的规则,最后再将得到的数值转换为负数
var s1 = "01";
var s2 = "1.1";
var s3 = "z";
var b = false;
var f = 1.1;
var o = {
     
 valueOf: function() {
     
 return -1;
 }
};
s1 = -s1; // 值变成了数值-1
s2 = -s2; // 值变成了数值-1.1
s3 = -s3; // 值变成了 NaN
b = -b; // 值变成了数值 0
f = -f; // 变成了-1.1
o = -o; // 值变成了数值 1 
位操作符

位操作符:按内存中表示数值的位来操作数值

ECMAScript 中的所有数值都以64位格式存储,位操作符并不直接操作64位格式的值,而是先将64位格式转换为32位格式,然后执行操作,最后再将结果转换回 64 位

  • 对于有符号的整数,32 位中的前 31 位用于表示整数的值。第 32 位用于表示数值的符号:0 表示正数,1 表示负数。这个表示符号的位叫做符号位,符号位的值决定了其他位数值的格式
  • 正数以纯二进制格式存储,31 位中的每一位都表示 2 的幂,。例如,数值 18 的二进制表示是00000000000000000000000000010010
  • 负数同样以二进制码存储,但使用的格式是二进制补码

计算二进制补码的步骤

  1. 求这个数值绝对值的二进制码
  2. 求二进制反码,即将 0 替换为 1,将 1 替换为 0
  3. 反码加1
    JavaScript高级程序设计(重点记录)-持续更新_第14张图片
  • 在以二进制字符串形式输出一个负数时,我们看到的只是这个负数绝对值的二进制码前面加上了一个负号
var num = -18;
alert(num.toString(2)); // "-10010" 

对数值应用位操作符时
后台会发生如下转换过程:64 位的数值被转换成 32位数值,然后执行位操作,最后再将 32 位的结果转换回 64 位数值。
这个转换过程也导致了一个严重的副效应,即在对特殊的 NaN 和 Infinity 值应用位操作时,这两个值都会被当成 0 来处理

对非数值应用位操作符时
会先使用 Number()函数将该值转换为一个数值(自动完成),然后再应用位操作。得到的结果将是一个数值

按位非NOT

  • 按位非操作符由一个波浪线(~)表示,执行按位非的结果就是返回数值的反码
var num1 = 25; // 二进制 00000000000000000000000000011001
var num2 = ~num1; // 二进制 11111111111111111111111111100110
alert(num2); // -26 

二进制可以看后811100110 这里表示的是-26的补码
-26 源码是1(符号位负数为1)001,1010 
-26补码除符号位取反末位加1 1110 0110

代码等价于
var num1 = 25;
var num2 = -num1 - 1;
alert(num2); // "-26" 

但是按位非的操作速度更快

按位与AND

  • 按位与操作符由一个和号字符(&)表示,它有两个操作符数
  • 按位与操作就是将两个数值的每一位对齐,然后根据下表中的规则,对相同位置上的两个数执行 AND 操作
    JavaScript高级程序设计(重点记录)-持续更新_第15张图片
var result = 25 & 3;
alert(result); //1 

按位或OR

  • 按位或操作符由一个竖线符号(|)表示,同样也有两个操作数。按位或操作遵循下面这个真值表
    JavaScript高级程序设计(重点记录)-持续更新_第16张图片
var result = 25 | 3;
alert(result); //27 

按位异或(XOR)

  • 按位异或操作符由一个插入符号(^)表示,也有两个操作数。以下是按位异或的真值表。
    JavaScript高级程序设计(重点记录)-持续更新_第17张图片
var result = 25 ^ 3;
alert(result); //26 

左移操作符

  • 左移操作符由两个小于号(<<)表示,这个操作符会将数值的所有位向左移动指定的位数
如果将数值 2(二进制码为 10)向左移动 5 位,结果就是 64(二进制码为 1000000var oldValue = 2; // 等于二进制的 10
var newValue = oldValue << 5; // 等于二进制的 1000000,十进制的 64 
  • 在向左移位后,原数值的右侧多出了 5 个空位。左移操作会以 0 来填充这些空位,以便得到的结果是一个完整的 32 位二进制数
    JavaScript高级程序设计(重点记录)-持续更新_第18张图片
  • 左移不会影响操作数的符号位

有符号的右移

  • 有符号的右移操作符由两个大于号(>>)表示,这个操作符会将数值向右移动
  • 但保留符号位(即正负号标记)
  • 有符号的右移操作与左移操作恰好相反,即如果将 64 向右移动 5 位,结果将变回 2
var oldValue = 64; // 等于二进制的 1000000
var newValue = oldValue >> 5; // 等于二进制的 10 ,即十进制的 2
  • 在移位过程中,原数值中也会出现空位。只不过这次的空位出现在原数值的左侧、符号位的右侧
  • 此时 ECMAScript 会用符号位的值来填充所有空位
    JavaScript高级程序设计(重点记录)-持续更新_第19张图片

无符号的右移

  • 无符号右移操作符由 3 个大于号(>>>)表示,这个操作符会将数值的所有 32 位都向右移动
  • 对正数来说,无符号右移的结果与有符号右移相同
var oldValue = 64; // 等于二进制的 1000000
var newValue = oldValue >>> 5; // 等于二进制的 10 ,即十进制的 2 
  • 对负数来说,无符号右移是以0来填充空位,而不像有符号右移,是以符号位的值来填充空位
  • 无符号右移操作符会把负数的二进制码当成正数的二进制码。而且,由于负数以其绝对
    值的二进制补码形式表示,因此就会导致无符号右移后的结果非常之大
var oldValue = -64; // 等于二进制的 11111111111111111111111111000000
var newValue = oldValue >>> 5; // 等于十进制的 134217726 

当对-64 执行无符号右移 5 位的操作后,得到的结果是 134217726。之所以结果如此之大,是因为-64 的二进制码为 11111111111111111111111111000000,而且无符号右移操作会把这个二进制码当成正数的二进制码,换算成十进制就是 4294967232。如果把这个值右移 5 位,结果就变成了00000111111111111111111111111110,即十进制的 134217726
布尔操作符

布尔操作符一共有 3 个:非(NOT)、与(AND)和或(OR)

逻辑非!

  • 可以应用于 ECMAScript 中的任何值。无论这个值是什么数据类型,这个操作符都会返回一个布尔值
  • 逻辑非操作符首先会将它的操作数转换为一个布尔值,然后再对其求反

 如果操作数是一个对象,返回 false;
 如果操作数是一个空字符串,返回 true;
 如果操作数是一个非空字符串,返回 false;
 如果操作数是数值 0,返回 true;
 如果操作数是任意非 0 数值(包括 Infinity),返回 false;
 如果操作数是 null,返回 true;
 如果操作数是 NaN,返回 true;
 如果操作数是 undefined,返回 true。

alert(!false); // true
alert(!"blue"); // false
alert(!0); // true
alert(!NaN); // true
alert(!""); // true
alert(!12345); // false
  • 同时使用两个逻辑非 ,可以用于将一个值转换为与其对应的布尔值
  • 第一个逻辑非操作会基于无论什么操作数返回一个布尔值,而第二个逻辑非操作则对该布尔值求反,于是就得到了这个值真正对应的布尔值
  • 最终结果与对这个值使用 Boolean()函数相同
alert(!!"blue"); //true
alert(!!0); //false
alert(!!NaN); //false
alert(!!""); //false
alert(!!12345); //true 

逻辑与

  • 逻辑与操作符由两个和号(&&)表示,有两个操作数
  • var result = true && false;
  • 逻辑与的真值表如下
    JavaScript高级程序设计(重点记录)-持续更新_第20张图片
  • 逻辑与操作可以应用于任何类型的操作数,而不仅仅是布尔值
  • 有一个操作数不是布尔值的情况下,逻辑与操作就不一定返回布尔值
  • 遵循以下规则

 如果第一个操作数是对象,则返回第二个操作数;
 如果第二个操作数是对象,则只有在第一个操作数的求值结果为 true 的情况下才会返回该
对象;
 如果两个操作数都是对象,则返回第二个操作数;
 如果有一个操作数是 null,则返回 null;
 如果有一个操作数是 NaN,则返回 NaN;
 如果有一个操作数是 undefined,则返回 undefined

  • 逻辑与操作属于短路操作,即如果第一个操作数能够决定结果,那么就不会再对第二个操作数求值
  • 如果第一个操作数是 false,则无论第二个操作数是什么值,结果都不再可能是
    true 了
  • 不能在逻辑与操作中使用未定义的值,例如
var found = true;
var result = (found && someUndefinedVariable); // 这里会发生错误
alert(result); // 这一行不会执行var found = false;时不会发生错误 
var found = false;
var result = (found && someUndefinedVariable); // 不会发生错误
alert(result); // 会执行("false")

逻辑或

  • 逻辑或操作符由两个竖线符号(||)表示,有两个操作数
  • var result = true || false;
  • 逻辑或的真值表如下
    JavaScript高级程序设计(重点记录)-持续更新_第21张图片
  • 与逻辑与操作相似,如果有一个操作数不是布尔值,逻辑或也不一定返回布尔值,遵循以下规则

 如果第一个操作数是对象,则返回第一个操作数;
 如果第一个操作数的求值结果为 false,则返回第二个操作数;
 如果两个操作数都是对象,则返回第一个操作数;
 如果两个操作数都是 null,则返回 null;
 如果两个操作数都是 NaN,则返回 NaN;
 如果两个操作数都是 undefined,则返回 undefined

  • 与逻辑与操作符相似,逻辑或操作符也是短路操作符。也就是说,如果第一个操作数的求值结果为true,就不会对第二个操作数求值了
var found = true;
var result = (found || someUndefinedVariable); // 不会发生错误
alert(result); // 会执行("true")

把 found 的值改为 false,就会导致错误
var found = false;
var result = (found || someUndefinedVariable); // 这里会发生错误
alert(result); // 这一行不会执行

注意

  • 可以利用逻辑或的这一行为来避免为变量赋 null 或 undefined 值
var myObject = preferredObject || backupObject; 
变量myObject 将会被赋值preferredObject 与 backupObject中的一个,变量preferredObject 中包含优先赋给变量 myObject 的值,变量 backupObject 负责在 preferredObject 中不包含有效值的情况下提供后备值。
如果 preferredObject 的值不是 null,那么它的值将被赋给 myObject;如果是 null,则将 backupObject 的值赋给 myObject
乘性操作符

ECMAScript 定义了 3 个乘性操作符:乘法、除法和求模

  • 在操作数为非数值的情况下会执行自动的类型转换
  • 如果参与乘性计算的某个操作数不是数值,后台会先使用 Number()转型函数将其转换为数值。也就是说,空字符串将被当作0,布尔值 true 将被当作 1

乘法

  • 乘法操作符由一个星号(*)表示,用于计算两个数值的乘积
  • var result = 34 * 56;
  • 在处理特殊值的情况下,乘法操作符遵循下列特殊的规则

 如果操作数都是数值,执行常规的乘法计算,即两个正数或两个负数相乘的结果还是正数,而
如果只有一个操作数有符号,那么结果就是负数。如果乘积超过了 ECMAScript 数值的表示范围,
则返回 Infinity 或-Infinity;
 如果有一个操作数是 NaN,则结果是 NaN;
 如果是 Infinity 与 0 相乘,则结果是 NaN;
 如果是 Infinity 与非 0 数值相乘,则结果是 Infinity 或-Infinity,取决于有符号操作数
的符号;
 如果是 Infinity 与 Infinity 相乘,则结果是 Infinity;
 如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值,然后再应用上面的
规则。

除法

  • 除法操作符由一个斜线符号(/)表示,执行第二个操作数除第一个操作数的计算
var result = 66 / 11; 
  • 除法计算遵循以下规则

 如果操作数都是数值,执行常规的除法计算,即两个正数或两个负数相除的结果还是正数,而
如果只有一个操作数有符号,那么结果就是负数。如果商超过了 ECMAScript 数值的表示范围,
则返回 Infinity 或-Infinity;
 如果有一个操作数是 NaN,则结果是 NaN;
 如果是 Infinity 被 Infinity 除,则结果是 NaN;
 如果是零被零除,则结果是 NaN;
 如果是非零的有限数被零除,则结果是 Infinity 或-Infinity,取决于有符号操作数的符号;
 如果是 Infinity 被任何非零数值除,则结果是 Infinity 或-Infinity,取决于有符号操作
数的符号;
 如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值,然后再应用上面的规则。

求模

  • 求模(余数)操作符由一个百分号(%)表示,用法如下
var result = 26 % 5; // 等于 1 
  • 取模运算遵循以下规则

 如果操作数都是数值,执行常规的除法计算,返回除得的余数;
 如果被除数是无穷大值而除数是有限大的数值,则结果是 NaN;
 如果被除数是有限大的数值而除数是零,则结果是 NaN;
 如果是 Infinity 被 Infinity 除,则结果是 NaN;
 如果被除数是有限大的数值而除数是无穷大的数值,则结果是被除数;
 如果被除数是零,则结果是零;
 如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值,然后再应用上面的规则。

加法

  • 如果两个操作符都是数值,执行常规的加法计算,然后根据下列规则返回结果:

 如果有一个操作数是 NaN,则结果是 NaN;
 如果是 Infinity 加 Infinity,则结果是 Infinity;
 如果是-Infinity 加-Infinity,则结果是-Infinity;
 如果是 Infinity 加-Infinity,则结果是 NaN;
 如果是+0 加+0,则结果是+0;
 如果是0 加0,则结果是0;
 如果是+0 加0,则结果是+0。
不过,如果有一个操作数是字符串,那么就要应用如下规则:
 如果两个操作数都是字符串,则将第二个操作数与第一个操作数拼接起来;
 如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将两个字符串拼接起来

  • 如果有一个操作数是对象、数值或布尔值,则调用它们的 toString()方法取得相应的字符串值,然后再应用前面关于字符串的规则。对于 undefined 和 null,则分别调用 String()函数并取得字符串"undefined"和"null"
var result1 = 5 + 5; // 两个数值相加
alert(result1); // 10 
var result2 = 5 + "5"; // 一个数值和一个字符串相加
alert(result2); // "55" 

如果想对数值执行算术计算,再将结果与字符串拼接起来,应该使用圆括号
var num1 = 5;
var num2 = 10;
var message = "The sum of 5 and 10 is " + (num1 + num2);
alert(message); //"The sum of 5 and 10 is 15" 

减法

  • 减法操作符遵循规则

 如果两个操作符都是数值,则执行常规的算术减法操作并返回结果;
 如果有一个操作数是 NaN,则结果是 NaN;
 如果是 Infinity 减 Infinity,则结果是 NaN;
 如果是-Infinity 减-Infinity,则结果是 NaN;
 如果是 Infinity 减-Infinity,则结果是 Infinity;
 如果是-Infinity 减 Infinity,则结果是-Infinity;
 如果是+0 减+0,则结果是+0;
 如果是+0 减0,则结果是0;
 如果是0 减0,则结果是+0;
 如果有一个操作数是字符串、布尔值、null 或 undefined,则先在后台调用 Number()函数将其转换为数值,然后再根据前面的规则执行减法计算。如果转换的结果是 NaN,则减法的结果就是 NaN;
 如果有一个操作数是对象,则调用对象的 valueOf()方法以取得表示该对象的数值。如果得到的值是 NaN,则减法的结果就是 NaN。如果对象没有 valueOf()方法,则调用其 toString()
方法并将得到的字符串转换为数值。

var result1 = 5 - true; // 4,因为 true 被转换成了 1
var result2 = NaN - 1; // NaN
var result3 = 5 - 3; // 2
var result4 = 5 - ""; // 5,因为"" 被转换成了 0
var result5 = 5 - "2"; // 3,因为"2"被转换成了 2
var result6 = 5 - null; // 5,因为 null 被转换成了 0 
关系操作符

小于(<)、大于(>)、小于等于(<=)和大于等于(>=),返回布尔值

  • 数据转换规则

 如果两个操作数都是数值,则执行数值比较。
 如果两个操作数都是字符串,则比较两个字符串对应的字符编码值。
 如果一个操作数是数值,则将另一个操作数转换为一个数值,然后执行数值比较。
 如果一个操作数是对象,则调用这个对象的 valueOf()方法,用得到的结果按照前面的规则执行比较。如果对象没有 valueOf()方法,则调用 toString()方法,并用得到的结果根据前面的规则执行比较。
 如果一个操作数是布尔值,则先将其转换为数值,然后再执行比较。

  • 在比较字符串时,实际比较的是两个字符串中对应位置的每个字符的字符编码值,再返回一个布尔值
  • 大写字母的字符编码全部小于小写字母的字符编码
var result = "Brick" < "alphabet"; //true 
字母 B 的字符编码为 66,而字母 a 的字符编码是 97

将两个操作数都转换为小写形式
var result = "Brick".toLowerCase() < "alphabet".toLowerCase(); //false 

var result = "23" < "3"; //true 
"2"的字符编码是 50,而"3"的字符编码是 51

var result = "23" < 3; //false 
,字符串"23"会被转换成数值 23,然后再与 3 进行比较

var result = "a" < 3; // false,因为"a"被转换成了 NaN 
任何操作数与 NaN 进行关系比较,结果都是 false

var result1 = NaN < 3; //false
var result2 = NaN >= 3; //false 
相等操作符
  • 两组操作符:相等和不相等——先转换再比较,全等和不全等——仅比较而不转换

相等和不相等

  • 相等操作符由两个等于号(==)表示,如果两个操作数相等,则返回 true
  • 而不相等操作符由叹号后跟等于号(!=)表示,果两个操作数不相等,则返回 true
  • 这两个操作符都会先转换操作数(通常称为强制转型),然后再比较它们的相等性
  • 转换不同的数据类型时,相等和不相等操作符遵循下列基本规则

 如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false 转换为 0,而true 转换为 1;
 如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值;
 如果一个操作数是对象,另一个操作数不是,则调用对象的 valueOf()方法,用得到的基本类型值按照前面的规则进行比较;

这两个操作符在进行比较时则要遵循下列规则。
 null 和 undefined 是相等的。
 要比较相等性之前,不能将 null 和 undefined 转换成其他任何值。
 如果有一个操作数是 NaN,则相等操作符返回 false,而不相等操作符返回 true。重要提示:
即使两个操作数都是 NaN,相等操作符也返回 false;因为按照规则,NaN 不等于 NaN。
 如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回 true;否则,返回 false

JavaScript高级程序设计(重点记录)-持续更新_第22张图片
全等和全不等

  • 全等操作符由 3 个等于号(===)表示,只在两个操作数未经转换就相等的情况下返回 true
var result1 = ("55" == 55); //true,因为转换后相等
var result2 = ("55" === 55); //false,因为不同的数据类型不相等
  • 不全等操作符由一个叹号后跟两个等于号(!==)表示,在两个操作数未经转换就不相等的情况下返回 true
var result1 = ("55" != 55); //false,因为转换后相等
var result2 = ("55" !== 55); //true,因为不同的数据类型不相等
  • null == undefined 会返回 true,因为它们是类似的值
  • null === undefined 会返回 false,因为它们是不同类型的值
  • 推荐使用全等和不全等操作符
条件操作符
  • variable = boolean_expression ? true_value : false_value;
  • var max = (num1 > num2) ? num1 : num2;
赋值运算符
var num = 10; 

var num = 10;
num += 10; 

复合赋值运算符
 乘/赋值(*=);
 除/赋值(/=);
 模/赋值(%=);
 加/赋值(+=);
 减/赋值(=);
 左移/赋值(<<=);
 有符号右移/赋值(>>=);
 无符号右移/赋值(>>>=)。
逗号操作符
var num1=1, num2=2, num3=3; 
var num = (5, 1, 4, 8, 0); // num 的值为 0 
用于赋值时,逗号操作符总会返回表达式中的最后一项
if语句
if (condition)
 statement1 
else 
 statement2 
condition(条件)可以是任意表达式
ECMAScript 会自动调用 Boolean()转换函数将这个表达式的结果转换为一个布尔值
do-while语句

在对条件表达式求值之前,循环体内的代码至少会被执行一次

do {
     
 statement
} while (expression);
下面是一个示例:
var i = 0;
do {
     
 i += 2;
} while (i < 10);
alert(i);
while语句

在循环体内的代码被执行之前,就会对出口条件求值

while(expression) statement
下面是一个示例:
var i = 0;
while (i < 10) {
     
 i += 2;
} 
for语句

前测试循环语句,但它具有在执行循环之前初始化变量和定义循环后要执行的代码的能力

for (initialization; expression; post-loop-expression) statement
下面是一个示例:
var count = 10;
for (var i = 0; i < count; i++){
     
 alert(i);
} 
  • 由于 ECMAScript 中不存在块级作用域,因此在循环内部定义的变量也可以在外部访问到
var count = 10;
for (var i = 0; i < count; i++){
      
alert(i);
}
alert(i); //10 
for (;;) {
      // 无限循环
 doSomething();
} 
只给出控制表达式实际上就把 for 循环转换成了 while 循环
var count = 10;
var i = 0;
for (; i < count; ){
     
 alert(i);
 i++;
} 
for-in语句

是一种精准的迭代语句,可以用来枚举对象的属性

for (property in expression) statement
下面是一个示例:
for (var propName in window) {
     
 document.write(propName);
使用 for-in 循环来显示了 BOM 中 window 对象的所有属性
每次执行循环时,都会将 window 对象中存在的一个属性名赋值给变量 propName。这个过程会一直持续到对象中的所有属性都被枚举一遍为止
} 
  • 在使用 for-in 循环之前,先检测确认该对象的值不是 null 或 undefined,如果是的话,则不执行循环体
label语句

使用 label 语句可以在代码中添加标签,以便将来使用

label: statement
下面是一个示例:
start: for (var i=0; i < count; i++) {
     
 alert(i);
} 
定义的 start 标签可以在将来由 breakcontinue 语句引用。加标签的语句一般都要与 for 语句等循环语句配合使用
break与continue语句

break 语句会立即退出循环,强制继续执行循环后面的语句。
continue 语句虽然也是立即退出循环,但退出循环后会从循环的顶部继续执行

var num = 0;
for (var i=1; i < 10; i++) {
     
 if (i % 5 == 0) {
     
 break;
 }
 num++;
}
alert(num); //4 

var num = 0;
for (var i=1; i < 10; i++) {
     
 if (i % 5 == 0) {
     
 continue;
 } 
 num++;
}
alert(num); //8 
  • break 和 continue 语句都可以与 label 语句联合使用,从而返回代码中特定的位置
var num = 0;
outermost:
for (var i=0; i < 10; i++) {
     
 for (var j=0; j < 10; j++) {
     
 if (i == 5 && j == 5) {
     
 break outermost;
 }
 num++;
 }
}
alert(num); //55 
添加这个标签的结果将导致 break 语句不仅会退出内部的 for 语句(即使用变量 j 的循环),而且也会退出外部的 for 语句(即使用变量 i 的循环)
var num = 0;
outermost:
for (var i=0; i < 10; i++) {
     
 for (var j=0; j < 10; j++) {
     
 if (i == 5 && j == 5) {
     
 continue outermost;
 }
 num++;
 }
}
alert(num); //95 
continue 语句会强制继续执行循环——退出内部循环,执行外部循环
with语句

with 语句的作用是将代码的作用域设置到一个特定的对象中

with (expression) statement; 

定义 with 语句的目的主要是为了简化多次编写同一个对象的工作
var qs = location.search.substring(1);
var hostName = location.hostname;
var url = location.href; 

===with(location){
     
 var qs = search.substring(1);
 var hostName = hostname;
 var url = href;
} 

不建议使用 with 语句。
switch语句
switch (expression) {
     
 case value: statement
 break;
 case value: statement
 break;
 case value: statement
 break;
 case value: statement
 break;
  default: statement
} 

switch (i) {
     
 case 25:
 alert("25");
 break;
 case 35:
 alert("35");
 break;
 case 45:
 alert("45");
 break;
 default:
 alert("Other");
} 

switch (i) {
     
 case 25:
 /* 合并两种情形 */
 case 35:
 alert("25 or 35");
 break;
 case 45:
 alert("45");
 break;
 default:
 alert("Other");
} 
  • 可以在switch 语句中使用任何数据类型(在很多其他语言中只能使用数值),无论是字符串,还是对象都没有问题。其次,每个 case 的值不一定是常量,可以是变量,甚至是表达式
var num = 25;
switch (true) {
     
 case num < 0:
 alert("Less than 0.");
 break;
 case num >= 0 && num <= 10:
 alert("Between 0 and 10.");
 break;
 case num > 10 && num <= 20:
 alert("Between 10 and 20.");
 break;
 default:
 alert("More than 20.");
} 

switch 语句在比较值时使用的是全等操作符,因此不会发生类型转换(例如,字符串"10"不等于数值 10)。

函数
function functionName(arg0, arg1,...,argN) {
     
 statements
}
以下是一个函数示例:
function sayHi(name, message) {
     
 alert("Hello " + name + "," + message);
} 
调用: sayHi("Nicholas", "how are you today?"); 
  • ECMAScript 中的函数在定义时不必指定是否返回值
  • 任何函数在任何时候都可以通过return 语句后跟要返回的值来实现返回值
function sum(num1, num2) {
     
 return num1 + num2;
} 

function sum(num1, num2) {
     
 return num1 + num2;
 alert("Hello world"); // 永远不会执行
} 

  • return 语句也可以不带有任何返回值。在这种情况下,函数在停止执行后将返回 undefined值
  • 一般用在需要提前停止函数执行而又不需要返回值的情况下
function sayHi(name, message) {
     
 return;
 alert("Hello " + name + "," + message); //永远不会调用
} 

-要么让函数始终都返回一个值,要么永远都不要返回值
 不能把函数命名为 eval 或 arguments;
 不能把参数命名为 eval 或 arguments;
 不能出现两个命名参数同名的情况。

你可能感兴趣的:(js高级程序设计,javascript,javascript)