文章目录
一、概述
1.1、前言
- JavaScript是世界上最流行的脚本语言,在电脑、平板、手机上浏览的所有网页,以及基于HTML5的手机APP,交互逻辑都是由JavaScript驱动的。
- JavaScript就是一种运行在浏览器中的解释型的编程语言。
- 在Web开发中,只有JavaScript能跨平台、跨浏览器驱动网页,与用户交互。
- 而JavaScript出了语法上有点像Java,其他部分基本上没啥关系。
1.2、ECMAScript
- 为了让JavaScript成为全球标准,几个公司联合ECMA(European Computer Manufacturers Association)组织制定了JavaScript语言的标准,被称为ECMAScript标准(由于JavaScript是网景公司注册的商标,所以不能用来作为标准)。
- ECMAScript其实就是一种语言标准,而JavaScript是网景公司对ECMAScript标准的一种实现。
- 如果你遇到了ECMAScript这个词,简单把它替换为JavaScript就可以了。
1.3、JavaScript版本
- 由于JavaScript的标准——ECMAScript在不断发展,最新版ECMAScript6标准(简称ES6)已经在2015年6月正式发布了。所以讲到JavaScript的版本,实际上就是说它实现了ECMAScript标准的哪个版本。
- 但是由于浏览器在发布时就确定了JavaScript的版本,加上很多用户还在使用IE6这种古老的浏览器,这就导致你在写JavaScript的时候,不能一上来就用最新的ES6标准写,否则IE6这种用户的浏览器是无法运行最新版本的JavaScript代码的。
二、第一个JavaScript程序
2.1、引入JavaScript
引入JavaScript有内部标签和外部引入两种方式。
内部标签
JavaScript代码可以嵌在网页的任何地方,不过我们通常把JavaScript代码放在<head></head>标签中。
<html>
<head>
<script>
alert('Hello, world');
</script>
</head>
<body>
...
</body>
</html>
由<script></script>包裹的代码就是JavaScript代码,它将直接被浏览器执行。
外部引入
外部引入就是把JavaScript代码放到一个单独的.js文件中,然后在HTML中引入这个文件。
<html>
<head>
<!-- 注意:script标签必须成对出现 -->
<script src="js/abc.js"></script>
</head>
<body>
...
</body>
</html>
<script></script>标签中的src属性值就是.js文件的路径。这样js/abc.js就会被浏览器执行。
- 把JavaScript代码放入一个单独的
.js文件中更利于维护代码,并且多个页面可以各自引用同一份.js文件 - 可以在同一个页面中引入多个
.js文件 - 还可以在页面中多次编写
<script></script>标签的代码,浏览器按照顺序依次执行 - 有时可能会看到
<script></script>标签中设置了一个type属性,但这是没必要的,因为默认的type就是text/javascript,所以不需要显式地把type指定为JavaScript
<script type="text/javascript"></script>
2.2、运行JavaScript
要让浏览器运行JavaScript,必须有一个HTML页面,在HTML页面中引入JavaScript,然后让浏览器加载该HTML页面,就可以执行JavaScript代码。
如果直接在硬盘上创建好HTML和JavaScript文件,然后用浏览器打开。这种方式运行部分JavaScript代码没问题,但由于浏览器的安全限制,以fttp://开头的地址无法执行如联网等JavaScript代码。
所以还是需要架设一个web服务器,然后以http://开头的地址来正常执行所有JavaScript代码。
<html>
<head>
<script>
// 注释
/* 注释 */
alter("Hello, JavaScript");
</script>
</head>
<body>
...
</body>
</html>
浏览器将弹出一个对话框,显示Hello, JavaScript。
2.3、调试
如何在浏览器中调试代码?
F12打开浏览器调试工具,点击Console(控制台),在这里输入JavaScript代码,按回车运行。
比如要查看一个变量a的值,在Console中输入console.log(a);,回车后显示的就是变量的值。
三、快速入门
3.1、基本语法
JavaScript的语法和Java相似,每个语句以;结束,语句块用{...}。
其实JavaScript并不强制要求在每个语句结尾加上 ;,浏览器中负责执行JavaScript代码的引擎会自动在每个语句的结尾补上 ;。
但是JavaScript引擎自动加分号在某些情况下会改变程序的语义,导致运行结果与期望不一致。所以尽量不要省略 ;。
-
普通赋值
var x = 1; -
代码块
<head> <meta charset="UTF-8"> <title>Title</title> <!-- JavaScript严格区分大小写 --> <script> // 1、定义变量 变量类型 变量名 = 变量值; var num = 1; var name = "new"; // 2. 条件控制 if (2 > 1) { alert("true"); } console.log(name);// 在浏览器的控制台打印变量,相当于sout </script> </head> <body> </body>
3.2、数据类型和变量
数值,文本,图形,音频,视频等都属于数据类型。
-
Number
js不区分浮点数和整数,统一用Number表示。123;// 整数123 123.1;// 浮点数123.1 1.23e3;// 科学计数法 -99; // 负数 NAN; // not a number,一个不是数字的数字类型。当无法计算结果时用NaN表示 Infinity; // 表示无限大。当数值超过了JavaScript的Number所能表示的最大值时,就表示为InfinityNumber还可以进行四则运算
1 + 2; // 3 (1 + 2) * 5 / 2; // 7.5 2 / 0; // Infinity 0 / 0; // NaN 10 % 3; // 1 10.5 % 3; // 1.5 -
字符串
字符串是以单引号或双引号括起来的任意文本。'abc'; "abc"; -
布尔值
true; false; 2 > 1; // 这是一个true值 2 < 1; // 这是一个false值// 逻辑运算 && // 与:只有都为true时,结果才为true || // 或:只要有一个为true,结果就是true ! // 非:把true变为false,把false变为true true && false; // 结果为false true || false; // 结果为true !true; // 结果为false -
比较运算符
当我们对Number作比较时,可以通过比较运算符得到一个布尔值2 > 5; // false 5 > 2; // true false == 0; // true false === 0; // false = 赋值 == 等于(类型不一样,值一样,也会判断为true) === 绝对等于(必须类型一样,值一样才会为true)==是JS的一个缺陷,尽量不要使用==比较NaN===NaN; // false /* NaN与所有的数值都不相等,包括自己 只能通过isNaN(NaN)函数来判断这个数是否是NaN */特别注意浮点数的相等比较:
console.log((1/3)===(1-2/3)); // false浮点数在运算过程中会产生误差,因为计算机无法精确表示无限循环小数。要比较两个浮点数是否相等,只能计算他们之差的绝对值,看是否小于某个阈值。
Math.abs(1 / 3 - (1 - 2 / 3)) < 0.000001; // true -
null和undefined
null // 表示一个空的值 undefined // 表示值未定义,只在判断函数参数是否传递的情况下有用 -
数组
Java的数组必须是一系列相同类型的对象,JS中不需要这样var arr = [1,2,3,4,5,'hello',null,true];数组用
[ ]表示,元素之间用,分隔。数组的元素可以通过索引来访问。arr[0]; // 返回的为索引为0处的1 -
对象
JavaScript中的对象是由一组键值对组成的无序集合,如:var person = { name: "zhang", age: 3, tags: ['js', 'java'] }JavaScript的键都是字符串类型,值可以是任意的数据类型。其中每个键又称为对象的属性,如person的
name属性为'张'。
如果需要获取一个属性的值,可以使用对象变量名.属性名的方式person.name; // "zhang" person.age; // 3
3.3、严格检查模式——strict
JavaScript在设计之初,并不强制要求用var声明变量。这个设计带来了严重的后果:如果一个变量没有通过var声明就被使用,那么该变量就自动被声明为全局变量。
i = 10; // i现在是全局变量
在同一页面的不同JavaScript文件中,如果都不用var声明,恰好都使用了变量i,将会造成变量间相互影响,产生错误。
使用var声明的变量则不是全局变量,它的范围被限制在该变量被声明的函数体内,同名变量在不同的函数体内不冲突。
为了修复这一严重缺陷,ECMA在后续的规范中推出了strict模式,在strict模式下运行的JavaScript代码,强制通过var声明变量,没有使用var的会导致运行错误。
启用strict模式的方法是在JavaScript代码的第一行写上:
'use strict';
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--
前提:IDEA需要支持ES6语法
严格检查模式,预防JavaScript 的随意性导致产生的一些问题
必须写在 JavaScript 的第一行
局部变量建议都是用 let 定义
-->
<script>
'use strict';
// 全局变量,加上 var 以后就是局部变量
i = 1;
// ES6中 使用 let 标识局部变量
</script>
</head>
3.4、字符串
用' '和" "括起来的就是字符串。
如果'本身也是一个字符,可以用" "括起来。比如:
"I'm OK";
包含的字符是I,’,m,空格,O,K这个六个字符。
如果字符串内部既包含'又包含",可以使用转义字符\来标识,比如:
'I\'m \"OK\"!';
表达的内容就是:I’m OK!
- 转义字符
\ ’ ’
\n 换行
\t table
\u4e2d \u### Unicode字符 中
\x41 Ascll字符 - 多行字符串编写
// 使用table键上面的~,将多行字符串包裹 var msg = ` hello world 你好 你好~ ` - 模板字符串
相当于+// table键上面的~ let name = "zhang"; let age = 3; let msg = `你好呀,${name}`; console.log(msg); // 你好呀,zhang - 操作字符串
字符串的常见操作如下:
(1)获取字符串的长度
(2)获取字符串某个指定位置的字符var student = "student"; console.log(student.length)
需要注意的是:字符串是不可变的,如果对字符串的某个索引赋值,不会报错,但也不会有任何效果// 类似于Array的下标取值操作,从0开始 var s = 'Hello world!'; s[0]; // 'H' s[1]; // 'e' s[12]; //undefined,超出范围的索引不会报错,一律返回undefined
所以JavaScript为字符串提供了一些常用方法。需要注意的是:调用这些方法本身不会改变原有字符串的内容,而是会返回一个新的字符串。var s = 'Test'; s[0] = 'X'; alert(s); // s仍然为Test
(3)字符串大小写转换
(4)获取字符串中指定字符第一次出现位置的下标// 注意:这里调用的是方法不是属性 // 把一个字符串全部变为大写 var student = "student"; console.log(student.toUpperCase()); // STUDENT // 把一个字符串全部变为小写 var student = "STUDENT"; console.log(student.toLowerCase()); //student
(5)返回指定索引区间的子串var student = "student"; console.log(student.indexOf('t'));// 返回结果为1,如果没有则返回-1var student = "student"; // 包前不包后 console.log(student.substring(0, 3))
3.5、数组
JavaScript的数组可以包含任意数据类型,并通过索引来访问元素。
var arr = [1,2,3,4,5]; // 通过下标取值和赋值
arr[0];
arr[0] = 1
- 如果要获取Array的长度,直接访问length属性
注意:如果给var arr = [1, 2, 3.14, 'Hello', null, true]; arr.length; // 6arr.length赋值,数组大小就会发生变化,如果赋值过小,元素就会丢失var arr = [1, 2, 3]; arr.length; // 3 arr.length = 5; arr; //变为[1, 2, 3, undefined, undefined] arr.length = 2; arr; // [1, 2] - Array可以通过索引把对应的元素修改为新的值
注意:如果通过索引赋值时,索引超出了范围,同样会引起var arr = ['A', 'B', 'C']; arr[1] = 99; arr; //['A', 99, 'C']Array的变化var arr = ['A', 'B', 'C']; arr[4] = 99; arr; //['A', 'B', 'C', undefined, 99]
注意:大多数编程语言不允许直接修改数组的大小,越界访问会报错。而JavaScript的Array不会有任何错误。所以在编写代码时,不建议直接修改Array的大小,访问索引时要确保索引不会越界。
-
与字符串类似,Array也可以通过indexOf()来搜索一个指定元素的位置
var arr = ['A', 'B', 'C']; arr.indexOf('B'); // 1 arr.indexOf(5); // 如果没有找到,返回-1 -
截取Array的一部分,返回一个新数组,类似于String中的subString
var arr = ['A', 'B', 'C', 'D', 'F', 'E']; arr.slice(0, 3); //从索引0开始,到3结束,但不包括3。['A', 'B', 'C'] arr.slice(3); // 从索引3开始,一直到末尾。 ['D', 'F', 'E']如果不给
slice()传参,它就会从头到尾截取所有元素。可以利用slice()来复制一个新的数组。var arr = ['A', 'B', 'C', 'D', 'F', 'E']; var arr2 = arr.slice(); arr2 === arr; // false -
操作尾部元素
/* push:将数据添加至尾部 pop:弹出尾部的元素 */ var arr = [1, 2]; arr.push('A', 'B'); // 返回Array的新长度:4 arr; // [1, 2, 'A', 'B'] arr.pop(); // pop()返回'B' arr; // [1, 2, 'A'] arr.pop().pop().pop(); //连续 pop 三次 arr; // [] -
操作头部元素
/* unshif:将数据添加至头部 shif:弹出头部的元素 */ var arr = [1, 2]; arr.unshif('A', 'B'); // 返回Array的新长度:4 arr; // ['A', 'B', 1, 2] arr.shif(); // shif()返回'A' arr; // ['B', 1, 2] arr.shif().shif().shif(); // 连续 shif 三次 arr; // [] -
Array排序
sort()可以对当前Array排序,它会直接修改当前Array的元素位置,直接调用时,按照排序方式var arr = ['C', 'B', 'A']; arr.sort(); arr; // ['A', 'B', 'C']在后面的函数会讲到如何自定义排序方式。
-
元素反转
会把Array的元素交换位置。var arr = ['C', 'B', 'A']; arr.reverse(); arr; // ['A', 'B', 'C'] -
splice():可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素
var arr = ['A', 'B', 'C', 'D', 'F', 'E']; arr.splice(2, 3, 'H'); // 从索引2开始删除3个元素,再添加'H' arr; // ['A', 'B', 'H', 'E'] arr.splice(2, 2); // 只删不加 arr; // ['A', 'B'] arr.splice(1, 0, 'Z'); // 只加不删 arr; // ['A', 'B', 'Z'] -
拼接数组,并返回一个新的数组
var arr = ['A', 'B', 'C']; var arrAdd = arr.concat([1, 2, 3]); arrAdd; // ['A', 'B', 'C', 1, 2, 3]concat()方法可以接收任意个元素和Array,并且自动把Array拆开,全部添加到新的Array里var arr = ['A', 'B', 'C']; var arrAdd = arr.concat(1, [2, 3]); arrAdd; // ['A', 'B', 'C', 1, 2, 3] -
连接符,打印拼接数组,使用指定的字符串连接数据内任意数据类型的元素
var arr = ['A', 'B', 'C']; arr.join('-'); // A-B-C -
多维数组。如果某个数组的元素是一个数组,则可以形成一个多维数组
arr = [[1,2],[3,4],["5","6"]]; arr[0][1]; // 2
3.6、对象
JavaScript的对象是一种无序的集合数据类型,由若干个键值对组成。
- 定义一个对象
/* 在JS中,使用{...}示一个对象,键值对描述属性xxx: xxx 多个属性之间使用逗号隔开,最后一个属性不加逗号 */ var person = { 属性名: 属性值, 属性名: 属性值, 属性名: 属性值 } var person = { name: "zhang", age: 3, email: "123456@qq.com" } - 获取对象的属性
// 对象.属性 var person = { name: "zhang", age: 3, email: "123456@qq.com" } person.name; // 'zhang' - 由于JavaScript的对象是动态类型,所以可以自由地给一个对象添加或删除一个属性
var person = { name: "zhang" } person.age; //undefined person.age = 3; // 新增一个age属性 person.age; // 3 delete person.age; // 删除一个属性。如果被删除的属性不存在,也不会报错 person.age; //undefined - 判断对象中是否存在某一属性
var person = { name: "zhang", age: 3, email: "123456@qq.com" } age in person; //true grade in person; // false // 注意:如果用 in 判断到一个属性存在,这个属性不一定是这个对象的,有可能是这个对象继承得到的 toString in person; // true - 判断一个属性是否是这个对象自身拥有的
因为toString定义在object对象中,而所有对象最终都会在原型链上指向object。
如果要判断一个属性是否是自身拥有的,而不是继承得到的,可以用hasOwnProperty()方法var person = { name: "zhang", age: 3, email: "123456@qq.com" } person.hasOwnProperty(age); //true person.hasOwnProperty(toString); // false
3.7、流程控制
- if 判断
var a = 3; if (age > 3) { alert("haha"); }else { alert("kuwa"); } - for循环
(1)基本语法
(2)遍历数组for (let i = 0; i < 100 ; i++) { console.log(i); }
(3)for…in,可以把一个对象的所有属性依次循环出来var arr = [1,2,3,4,5]; for (let i = 0; i < arr.length ; i++) { console.log(arr[i]); }
由于var person = { name: "zhang", age: 3, email: "123456@qq.com" } for(var key in person) { if (person.hasOwnProperty(key )) { console.log(key); // 'name', 'age', 'email' } }Array也是对象,而它的每个元素的索引被视为对象的属性,所以遍历出来是下标
注意:var ages = [1,2,3]; for(var num in ages) { if (age.hasOwnProperty(num)) { console.log(age); // '0', '1', '2' console.log(age[num]); // '1', '2', '3' } }for...in对Array循环得到的是String而不是Number
(4)forEach循环var ages = [1,2,3,4,5,6]; ages.forEach(function (value) { console.log(value); }); - while循环
age = 0; while (age < 100) { age = age + 1; console.log(age); } - do…while
age = 0; do{ age = age + 1; console.log(age); }while(age < 100)
3.8、Map和Set
Map和Set是ES6规范引入的新的数据类型
- Map。
key-value的键值对形式存储数据。初始化的时候需要一个二维数组,或者直接初始化一个空。// 学生的名字,学生的成绩 var map = new Map([['tom',100],['jack',90],['haha',80]]); var score = map.get('tom'); // 通过key获得value map.set('admin',123456); // 添加键值对 map.delete('tom'); // 删除键值对Map中一个key只能对应一个value,所以多次对同一个key放入value,只会保存最后一次放入的值。 - Set。无序不重复的集合。
var set = new Set([3,1,1,1]); // set中的重复元素会被过滤 set.add(2); // 添加 set.delete(1); // 删除 console.log(set.has(3)); // 是否包含某个元素
3.9、Iterator
遍历Array可以采用下标循环,遍历Map和Set就无法使用下标。
所以ES6标准引入了iterator类型。
具有iterator类型的集合可以通过新的for...of循环来遍历。
- 遍历数组
// 通过for of 实现 for in获取下标 var arr = [3,4,5]; for (var x of arr) { console.log(x); }var arr = [3,4,5]; arr.name = "213"; // 早期的漏洞,for...in打印下标时会把新增的这个name也打印出来 for (let x in arr) { console.log(x) } - 遍历Map
var map = new Map([["tom", 100],["jack", 90],["haha", 80]]); for (let x of map) { console.log(x[0] + '=' + x[1]); } - 遍历Set
更好的方式是直接使用var sett = new Set([5,6,7]); for (let x of sett) { console.log(x) }iterator内置的foreach方法。 - 遍历数组
var arr = [3,4,5]; a.forEach(function (element, index, array) { // element: 指向当前元素的值 // index: 指向当前索引 // array: 指向Array对象本身 console.log(element + ', index = ' + index); }); - 遍历Set
var s = new Set(['A', 'B', 'C']); s.forEach(function (element, sameElement, array) { // 由于set没有索引,所以回调函数的前两个参数都是元素本身 console.log(element + ', index = ' + index); }); - 遍历Map
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]); m.forEach(function (value, key, map) { console.log(value); });
本文介绍了JavaScript的基础知识,包括语言的历史背景、基本语法、数据类型、流程控制等内容,适合初学者快速掌握JavaScript编程。
341

被折叠的 条评论
为什么被折叠?



