一. JavaScript概述
1. 什么是JavaScript?
-
JavaScript 是一门跨平台、面向对象的脚本语言,运行在客户端浏览器中,可以改变网页(DOM)的外观与样式,它能使网页可交互(例如拥有复杂的动画,可点击的按钮,通俗的菜单等)。
-
JavaScript还有服务端版本,例如Node.js,它可以让你在网页上添加更多功能,不仅仅是下载文件(例如在多台电脑之间的协同合作)。在宿主环境(例如 web 浏览器)中, JavaScript 能够通过其所连接的环境提供的编程接口进行控制。
-
脚本语言:不需要编译,就可以被浏览器直接解析执行,边解析边执行。
-
JavaScript简称JS。
2. JavaScript和Java
-
JavaScript 在 1995 年由 Brendan Eich (布伦丹·艾希) 发明,并于 1997 年成为一部 ECMA 标准。ECMA-262 是其官方名称。ECMAScript 6 (发布于 2015 年)是最新的 JavaScript 版本。
-
JavaScript 和 Java 是完全不同的语言,不论是概念上还是设计上(有一种说法是JavaScript当年想蹭Java的热度,方便快速推广,所以名称中带上了Java)。
-
JavaScript 和 Java 有一些共性,但是在另一些方面有着根本性区别。JavaScript语言类似 Java 但是并没有 Java 的静态类型和强类型检查特性。JavaScript 遵循了 Java 的表达式语法,命名规范以及基础流程控制,这也是 JavaScript 从 LiveScript 更名的原因(这个理由更官方一些^_^)。
-
与 Java 相比,Javascript 是一门形式自由的语言。你不必声明所有的变量,类和方法。你不必关心方法是否是共有、私有或者受保护的,也不需要实现接口。无需显式指定变量、参数、方法返回值的数据类型。
-
JavaScript的变量类型是动态的,而Java是静态的。
3. 为什么要学习JavaScript
JavaScript是前端开发三剑客之一,另外两个是HTML和CSS。
前端网页三剑客分工如下:
-
HTML (网页结构、内容)
-
CSS(美观、样式)
-
JavaScript(动态、交互)
二.基础知识
1.js的两种引入方式
内联定义 和 外部引入
内联定义:
-
通过在网页上的一对script标签定义JavaScript代码片段。
-
在Html页面的body标签之后编写JavaScript代码片段。
外部引入:
- 在项目中创建js目录,在其中创建index.js
- 在Html页面的body标签之后使用以下方式引入外部的js文件
<script type="text/javascript" charset="UTF-8" src="js/index.js"></script>
2.基础语法规范
- JavaScript是区分大小写的
- 代码最后的分号不是必须的
如果一条语句独占一行的话,那么分号是可以省略的(不建议这样做)。但如果一行中有多条语句,那么这些语句必须以分号隔开。
- 字符串不区分单双引号
- 注释方式和java相似
3. 变量、基本数据类型
3.1. 变量命名规范
JavaScript中变量的命名规范和Java类似,一个 JavaScript 标识符必须以字母、下划线(_)或者美元符号($)开头;后续的字符也可以是数字(0-9)。因为 JavaScript 语言是区分大小写的,所以字母可以是从“A”到“Z”的大写字母和从“a”到“z”的小写字母。
3.2. 声明方式
JavaScript有三种声明方式。
-
var
声明一个变量,可选初始化一个值,全局变量。
-
let (ECMA6新增) (推荐使用)
声明一个块作用域的局部变量,可选初始化一个值。
-
const (ECMA6新增)
声明一个块作用域的只读常量,不能更改
<script type="text/javascript"> //1. var定义全局变量 if(true){ //在JS中两个{}包裹的区域称之为块作用域,一般块作用域中的变量都是局部变量 var $name="张三"; } console.log($name); //在网页的控制台会打印 张三 //2. let定义局部变量,只能在定义的块作用域中使用,不能在块作用域之外使用 if(true){ let _age=30; } //console.log(_age); //控制台会显示出错并提示错误信息,后面的代码也无法执行 //3. const定义只读常量,如果没有明确块作用域,那这时块作用域就是全局 const ADDRESS="河南"; ADDRESS="郑州"; console.log(ADDRESS); //控制台会提示并打印错误信息 </script>
3.3. 全局变量
全局变量是全局对象的属性。在网页中,(译注:缺省的)全局对象是 window
,所以可以用形如 window.
variable 的语法来设置和访问全局变量。
//1. 全局变量,是全局对象的属性,全局对象:window
var name="李四";
console.log(name);
console.log(window.name); //输出结果相同
//2. 局部变量,局部变量只是局部块作用域对象的属性
if(true){
let sex="男";
console.log(window.sex); //undefined
}
let age=30;
console.log(window.age); //undefined
3.4. 常量
你可以用关键字 const
创建一个只读的常量。常量标识符的命名规则和变量相同:必须以字母、下划线(_)或美元符号($)开头并可以包含有字母、数字或下划线。常量不能更改。
3.5. 数据类型
-
布尔类型 (Boolean)
-
和Java中类似,JS中的Boolean类型也有两个值:
true
和false
-
-
数字 (Number)
-
在JS中整数和浮点数都是同一个类型,Number。例如:42、3.1415926
-
-
字符串 (String)
-
JS中字符串类型和Java语言类似,不同的是JS中不区分单引号和双引号
-
-
空值 (Null)
-
一个表明 null 值的特殊关键字。 JavaScript 是大小写敏感的,因此
null
与Null
、NULL
或变体完全不同。
-
-
未定义 (undefined) 有点特殊,着重记忆
-
和 null 一样是一个特殊的关键字,undefined 表示变量未定义时的属性。
-
-
任意精度的大整数 (BigInt)
-
可以安全地存储和操作大整数,甚至可以超过数字的安全整数限制。
-
3.6. 数据类型的转换
JavaScript是一种动态类型语言(dynamically typed language)。这意味着你在声明变量时可以不必指定数据类型,而数据类型会在代码执行时会根据需要自动转换。因此,你可以按照如下方式来定义变量:
var answer = 33;
// 因为 JavaScript 是动态类型的,这种赋值方式并不会提示出错。
answer = "Thanks for all the fish...";
// 数值类型自动转成字符串
var i = 8;
var str_i = i+"1";
console.log(str_i); // 81
// 注意: 只有 + 号运算符可以将数字转成字符串,而 - 号运算符则不可以
var j = i-"2";
console.log(j); //6
// 字符串类型转成数字
var str_pi = "3.14";
var int_pi = parseInt(str_pi); //通过调用parseInt()方法实现 字符到整型的转换
console.log(int_pi); // 3
var float_pi = parseFloat(str_pi);
console.log(float_pi); // 3.14
4. 运算符
4.1. 赋值运算符
名字 | 简写的操作符 | 含义 |
---|---|---|
赋值(Assignment) | x = y | x = y |
加法赋值(Addition assignment) | x += y | x = x + y |
减法赋值(Subtraction assignment) | x -= y | x = x - y |
乘法赋值(Multiplication assignment) | x *= y | x = x * y |
除法赋值(Division assignment) | x /= y | x = x / y |
求余赋值(Remainder assignment) | x %= y | x = x % y |
求幂赋值(Exponentiation assignment)(求次方赋值) | x **= y | x = x ** y |
左移位赋值(Left shift assignment) | x <<= y | x = x << y |
右移位赋值(Right shift assignment) | x >>= y | x = x >> y |
无符号右移位赋值(Unsigned right shift assignment) | x >>>= y | x = x >>> y |
按位与赋值(Bitwise AND assignment) | x &= y | x = x & y |
按位异或赋值(Bitwise XOR assignment) | x ^= y | x = x ^ y |
按位或赋值(Bitwise OR assignment) | x |= y | x = x | y |
4.2. 比较运算符
运算符 | 描述 | 返回true的示例 |
---|---|---|
等于 Equal (== ) | 如果两边操作数相等时返回true。 | 3 == var1 "3" == var1 3 == '3' |
不等于 Not equal (!= ) | 如果两边操作数不相等时返回true | var1 != 4 var2 != "3" |
全等 Strict equal (=== ) | 两边操作数相等且类型相同时返回true。 参见 Object.is and sameness in JS. | 3 === var1 |
不全等 Strict not equal (!== ) | 两边操作数不相等或类型不同时返回true。 | var1 !== "3" 3 !== '3' |
大于 Greater than (> ) | 左边的操作数大于右边的操作数返回true | var2 > var1 "12" > 2 |
大于等于 Greater than or equal (>= ) | 左边的操作数大于或等于右边的操作数返回true | var2 >= var1 4 >= 3 |
小于 Less than (< ) | 左边的操作数小于右边的操作数返回true | var1 < var2 "2" < 12 |
小于等于 Less than or equal (<= ) | 左边的操作数小于或等于右边的操作数返回true | var1 <= var2 2 <= 5 |
4.3. 算术运算符
运算符 | 描述 | 示例 |
---|---|---|
求余(% ) | 二元运算符. 返回相除之后的余数. | 12 % 5 返回 2。 |
自增(++ ) | 一元运算符. 将操作数的值加一. 如果放在操作数前面 (++x ), 则返回加一后的值; 如果放在操作数后面 (x++ ), 则返回操作数原值,然后再将操作数加一. | var x=3;``console.log(++x); //4``console.log(x); //4``var y=3;``console.log(y++); //3``console.log(y); //4 |
自减 (-- ) | 一元运算符. 将操作数的值减一. 前后缀两种用法的返回值类似自增运算符. | var x=3; console.log(--x); //输入2,x=2var y=3;console.log(y--);//输出3,x=2; |
一元负值符(- ) | 一元运算符,返回操作数的负值. | var x=3; console.log(-x); //输入-3 |
一元正值符 (+) | 一元运算符,返回操作数,如果操作数在之前不是number,将其转换为number | console.log( +'3' ); // 3``console.log( '3' ); // '3' console.log(+true); // 1 |
指数运算符(**) | 计算 base(底数) 的 exponent( 指数)次方 , 表示为baseexponent | 2 ** 3 returns 8 . 10 ** -1 returns 0.1 . |
4.4. 逻辑运算符
运算符 | 范例 | 描述 |
---|---|---|
逻辑与(&& ) | expr1 && expr2 | (逻辑与) 如果expr1能被转换为false,那么返回expr1;否则,返回expr2 。因此,&& 用于布尔值时,当操作数都为true时返回true;否则返回false. |
逻辑或 (|| ) | expr1 || expr2 | (逻辑或) 如果expr1能被转换为true,那么返回expr1;否则,返回expr2 。因此,||用于布尔值时,当任何一个操作数为true则返回true;如果操作数都是false则返回false。 |
逻辑非(!) | !expr | (逻辑非) 如果操作数能够转换为true则返回false;否则返回true。 |
能被转换为
false
的值有null
,0
,NaN
, 空字符串("")和undefined
。
4.5. 条件(三目)运算符
和Java中类似,JavaScript中也提供了条件分支的三目运算符
// 当条件为真时,aa = 值1,否则 aa = 值2
var aa = 条件 ? 值1 : 值2;
4.6. delete操作符
delete
操作符,删除一个对象或一个对象的属性或者一个数组中某一个键值。语法如下:
delete objectName; //删除对象
delete objectName.property; //删除对象属性
delete objectName[index]; //删除数组中对应下标的元素
objectName
是一个对象名,property
是一个已经存在的属性,index
是数组中的一个已经存在的键值的索引值。
删除数组中的元素时,数组的长度是不变的,例如删除
a[3]
,a[4]
,a[4]和a[3]
仍然存在的,但是值变成了undefined
。
4.7. typeof运算符
typeof操作符返回一个表示operand类型的字符串值。operand可为字符串、变量、关键词或对象,其类型将被返回。
var myFun = new Function("5 + 2"); //构建一个函数(方法)对象
var shape = "round";
var size = 1;
var today = new Date(); //构建一个日期对象
console.log(today);
console.log(today.getFullYear()); //获取年
console.log(today.getMonth()+1); //获取月 0-11
console.log(today.getDay()); //获取周的某一天 0-6 0周日
console.log(today.getDate()); //获取日
console.log(today.getHours()); //获取时 HH:mm:ss
console.log(today.getMinutes()); //获取分
console.log(today.getSeconds()); //获取秒
console.log(today.getMilliseconds()); //获取毫秒
console.log(typeof myFun); // "function"
console.log(typeof shape); // "string"
console.log(typeof size); // "number"
console.log(typeof today); // "object"
console.log("-------------------");
console.log(typeof true); // "boolean"
console.log(typeof null); // "object"
console.log("-------------------");
// 对于预定义对象, typeof将返回如下结果:
console.log(typeof Date); // returns "function"
console.log(typeof Function); // returns "function"
console.log(typeof Math); // returns "object"
console.log(typeof Option); // returns "function"
console.log(typeof String); // returns "function"
console.log("-------------------");
var random = Math.random(); //获取[0,1)随机小数
console.log(Math.floor(random*101));
// random: 0-0.99 (0-100) (max-min+1)+min (100-0+1)+0
4.8. instanceof运算符
判断对应的对象是否是指定的对象类型,如果是则返回true
,不是则返回false,其语法如下:
objectName instanceof objectType
objectName
是需要做判别的对象的名称,而objectType
是假定的对象的类型, 例如Date
或 Array
使用示例:
var x = 1;
console.log(x instanceof Number); // false
var x = new Number(1);
console.log(x instanceof Number); //true
4.9. in运算符
in
操作符,如果所指定的属性确实存在于所指定的对象中,则会返回true
,语法如下:
propNameOrNumber in objectName
在这里 propNameOrNumber
可以是一个属性名的字符串或者是一个数组索引的数值表达式,而objectName
则是一个对象名。
示例:
// 属性名 in 对象名 索引 in 数组
var nums = ["Java", "PHP", "Python", "JavaScript", "C++"];
console.log(0 in nums); //true 判断0索引是否在nums数组中,在true,不在false
console.log(1 in nums);
console.log(5 in nums); //false
console.log("JavaScript" in nums); // 此种写法不会报错,但是返回的是false
console.log("length" in nums); //true 判断 length属性 是否在nums数组对象中,在true,不在false
console.log("---------------------------------");
console.log("PI" in Math); //true 判断PI属性是否在Math预定义对象中,在true,不在false
var myString = new String("coral");
console.log("length" in myString); // returns true
console.log("---------------------------------");
var mycar = {make: "本田", model: "雅阁", year: 1998}; //js中 {key:value}都表示对象,key称之为对象的属性
console.log("make" in mycar); // returns true
console.log("model" in mycar); // returns true
4.10. void运算符
void运算符,表明一个运算没有返回值。expression是javaScript表达式,括号中的表达式是一个可选项。
你可以使用void运算符指明一个超文本链接。该表达式是有效的,但是并不会在当前文档中进行加载。
语法:
void (expression)
void expression
5. 流程控制语句
5.1. 语句块概念
最基本的语句块是用于组合语句的。该块由一对大括号界定,通常用于流程控制,如:if
、for
、while
等
while (x < 10) {
x++;
}
重点:在ECMAScript 6标准之前,Javascript没有块作用域。在一个块中引入的变量,其作用域是全局的,它们的效果会延续到块之外。换句话说,块语句不定义范围。JavaScript中的“独立”块会产生与C或Java中完全不同的结果。示例:
var x = 1;
{
var x = 2;
}
alert(x); // 输出的结果为 2
5.2. 分支语句
-
if ... else if ... else 语句
-
switch语句
-
for 语句
-
do ... while 语句
-
while 语句
-
for ... in 语句
可循环对象、数组等,循环的每个元素对于对象来说是对象的属性,而对于数组来说,则是下标。
var fruits = ["苹果", "香蕉", "橙子", "榴莲"];
for(let idx in fruits) {
console.log('idx: ' + idx);
}
- for ... of 语句
可循环对象包括:Array,Map、Set、arguments等,与for ... in 不同的是,循环的每个元素对于对象来说是对象每个属性的值,而对于数组来说,则是数组的每个元素。
var fruits = ["苹果", "香蕉", "橙子", "榴莲"];
for(let fruit of fruits){
console.log(fruit);
}
6. 异常处理语句
-
throw
和Java中不同的是,JavaScript中的throw可以抛出任意一个含有值的表达式而不用是一个特定的类型
throw "Error2"; // String type throw 42; // Number type throw true; // Boolean type throw { toString: function() { return "I'm an object!"; } };
也可以抛出Error对象,让你的错误信息包含更多有用的信息
var name="zhangsan"; if(name === "lisi"){ console.log(name); }else{ throw(new Error("用户名错误")); }
-
try ... catch
-
try ... catch ... finally
var name="zhangsan"; // 使用try后,出错不会爆红了 try{ if(name === "lisi"){ console.log(name); }else{ throw(new Error("用户名错误")); } }catch(e){ console.log(e); //获取抛出的异常,进行自定义解决 }finally{ // finally块是可选的 console.log("finally执行了"); //无论是否有异常, finally块的语句都会执行 }
7. 字符串常用操作
下面列举了
String
对象的方法方法 描述 charAt, charCodeAt, codePointAt 返回字符串指定位置的字符或者字符编码。 indexOf, lastIndexOf 分别返回字符串中指定子串的位置或最后位置(如果没找到,返回-1)。 startsWith, endsWith, includes 返回字符串是否以指定字符串开始、结束或包含指定字符串。 concat 连接两个字符串并返回新的字符串。 fromCharCode, fromCodePoint 从指定的Unicode值序列构造一个字符串。这是一个String类方法,不是实例方法。 split 通过将字符串分离成一个个子串来把一个String对象分裂到一个字符串数组中。 slice 从一个字符串提取片段并作为新字符串返回(推荐使用,替代substring、substr)。 substring, substr 分别通过指定起始和结束位置,起始位置和长度来返回字符串的指定子集。 match, replace, search 通过正则表达式来工作. toLowerCase, toUpperCase 分别返回字符串的小写表示和大写表示。 normalize 按照指定的一种 Unicode 正规形式将当前字符串正规化。 repeat 将字符串内容重复指定次数后返回。 trim 去掉字符串开头和结尾的空白字符。 7.1. 字符串常用操作
var sname = "zhang,san"; //获取字符串长度 console.log("sname的长度为: " + sname.length); // 9 //获取字符串指定位置的字符,字符串的下表索引从0开始 console.log("sname第三个位置的字符为:"+sname.charAt(2)); //a //获取字符串中指定子串首次出现的角标位置 console.log("an在sname中首次出现的位置:"+sname.indexOf("an")); //2 //获取字符串中指定子串最后出现的角标位置 console.log("an在sname中首次出现的位置:"+sname.lastIndexOf("an")); //7 //判断字符串是否以指定字符串开始 console.log("判断sname是否zh开始"+sname.startsWith("zh")); //true //判断字符串是否以指定字符串结尾 console.log("判断sname是否zh结尾"+sname.endsWith("zh")); //false //将字符串以参数为分隔,拆分为数组 console.log("sname拆分为数组为:"+sname.split(",")); //zhang,san //将字符串提取片段并作为新字符串返回,包含第一个参数,不包含第二个参数 console.log("从sname中提取san:"+sname.slice(6,sname.length)); // san console.log("从sname中提取san:"+sname.substr(6,sname.length)); //san console.log("从sname中提取san:"+sname.substring(6,sname.length)); //san //用正则提取字符串中的内容 var tel = '0371-12789453,0372-65897034'; // match方法中直接传入正则表达式对象 /g:所有匹配 console.log(tel.match(/\d{4}-\d{8}/)); // Array [ "0371-12789453" ] console.log(tel.match(/\d{4}-\d{8}/g)); // Array [ "0371-12789453", "0372-65897034" ] // match方法中传入正则表达式字符串(match方法会隐式地使用 new RegExp(obj) 将其转换为一个 RegExp) // 注意正则中诸如\d之类的字符需要转义 console.log(tel.match('\\d{4}-\\d{8}')); // Array [ "0371-12789453" ] //用正则替换字符串中指定内容 const p = 'The quick brown fox jumps over the lazy dog.'; // 替换字符串中匹配给定正则表达式对象的内容 const regex = /dog/gi; // /gi:匹配所有,忽略大小写 console.log(p.replace(regex, 'ferret')); //"The quick brown fox jumps over the lazy ferret." // 也可以不使用正则表达式实现,替换字符串中匹配给定字符串的内容 console.log(p.replace('dog', 'monkey')); //"The quick brown fox jumps over the lazy monkey." //搜索字符串中匹配指定正则内容出现的下标 //search()方法返回字符串中出现匹配正则内容的下标,如果找不到,则返回-1 const myStr = 'I love China!'; // 匹配非字母和空白字符的内容 const regex1 = /[^\w\s]/g; //匹配不包含字母、数字、下划线、空格、制表符、换页符的内容 console.log(myStr.search(regex1)); // 12 console.log(myStr[myStr.search(regex1)]); // "!" const regex2 = /^a/g; //匹配以a开头 console.log(myStr.search(regex2)); // -1 //转大小写 const str = "hello javascript"; console.log("转大写:"+str.toUpperCase()); const str1 = "HELLO JAVASCRIPT"; console.log("转小写:"+str.toLowerCase()); //去除首尾空格 const str2 = " 开始 "; console.log("去掉首尾空字符:"+str2.trim());
8. 正则相关操作
正则对象的
test()
方法和字符串对象的search()
方法类似,区别在于test()
方法返回true、false,而search()
方法返回的是下标let str3 = 'hello world!'; let regex3 = /^hello/; console.log(regex3.test(str3));// true let str4 = 'hello world!'; let regex4 = /^world/; console.log(regex4.test(str4));// false