介绍
JavaScript 教程
JavaScript 能改变 HTML 内容,能改变 HTML 属性,能改变 HTML 样式 (CSS),能完成页面的数据验证;
JS 需要运行浏览器来解析执行JavaScript 代码;
JS 是 Netscape 网景公司的产品,最早取名为 LiveScript,后更名为 JavaScript,和 Java 没有关系;
- JavaScript 是一种解释型的脚本语言,C、C++等语言先编译后执行,而 JavaScript 是在程序的运行过程中逐行进行解释。
- JavaScript 是一种基于对象的脚本语言,可以创建对象,也可使用现有对象(有对象)。
- JavaScript 是弱类型的,对变量的数据类型不做严格的要求,变量的数据类型在运行过程可以变化。
- 跨平台性(只要是可以解释 JS 的浏览器都可以执行,和平台无关);
- 使用垃圾回收的编程语言,开发者不需要操心内存分配和回收,主流的垃圾回收算法是标记算法;
说明:
js代码可以写在 script标签中;
type="text/javascript" :表示这个脚本(script)类型是javascript,可以不写,但是建议写上;js 语句可以不写 ; 建议写上。
使用方式
方式1
script 标签 写 JS 代码;
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>script 标签中 写 JS 代码</title> <script type="text/javascript"> //在head内使用script写js alert("ok");//使用警告框来显示数据: </script> </head> <body> <script type="text/javascript"> //在body内使用script写js console.log("hi");//写入浏览器控制台 </script> </body> </html>
说明:
- scrpt标签位置可以在 head 和 body 嵌入,执行顺序从上到下;
- 建议放在head中
- alert 是 JavaScript 语言提供的一个警告框函数。它可以输出指定的内容, 变量等信息。
方式2
使用script标签引入js文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>使用 script 标签引入 JS文件</title> <script type="text/javascript" src="./js/test.js"></script> </head> <body> </body> </html> test.js文件JS代码: alert("我是 test.js 文件");
两种使用js的方式,是二选一,不能混用。
若都使用,不会报错,但是只有一个生效, 前面引入的js生效。好处:
- 可维护性
- 缓存。浏览器会根据特定的设置缓存所有外部链接的JavaScript文件,这意味着如果两个页面都用到同一个JavaScript文件,则该文件只需加载一次,这最终意味着页面加载更快。
内容
JS变量
JavaScript 变量表示存储数据的容器,通过
所有 JavaScript 变量必须以唯一的名称的标识,这些唯一的名称称为标识符。
标识符可以是短名称(比如 x 和 y),或者更具描述性的名称(age、sum、totalVolume)。
构造变量名称(唯一标识符)的通用规则是:
- 名称可包含字母、数字、下划线和美元符号
- 名称必须以字母开头
- 名称也可以
$ 和_ 开头(但是在本教程中我们不会这么做) - 名称对大小写敏感(y 和 Y 是不同的变量)
- 保留字(比如 JavaScript 的关键词)无法用作变量名称
序号 | 名称 | 数据类型 | 备注 |
1 | 数值类型 | number | |
2 | 字符串类型 | string |
可以双引号括起来, 也可以单引号括起来; "a book of JavaScript"、 'abc'、"a"、 ""; |
3 | 对象类型 | object | |
4 | 布尔类型 | boolean | |
5 | 函数类型 | function | |
6 | 不带有值的变量 | undefined | 未赋初始值时,默认 undefined |
7 | 空值 | null |
ES2015 引入了两个重要的 JavaScript 新关键词:
let 和const 。对比var与let、const
- let不具备声明提升,var具备声明提升
- let声明的范围是块作用域,而var声明的范围是函数作用域。
- let是ES6才引入的声明关键字
- for循环中的let声明
- const与let很相似,最大的区别是const必须初始化,且不能再次赋值。
结语:
大多数开发者尽量限制自己只使用let和const,有助于提升代码质量,因为变量有了明确的作用域、声明位置、以及不变的值。
const优先,let次之。使用const声明可以让浏览器运行时强制保持变量不变,也可以让静态代码分析工具提前发现不合法的赋值操作。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>数据类型-特殊值</title> </head> <body> <script type="text/javascript"> //1. typeof()是 JavaScript 语言提供的一个函数,返回变量的数据类型 //2. 3个特殊值 undefined 没有赋值就使用 null, NaN 当不能识别类型 var email; //特殊值undefined console.log("email= " + email); //undefined var address = null; console.log("address= " + address); //null console.log(10 * "abc"); //NaN= Not a Number alert(typeof(email)); </script> </body> </html>
变量的特点:
- 原始值大小固定,保存在栈内存中
- 从一个变量到另一个变量复制原始值,会创建该值得第二个副本
- 引用值是对象,存储在堆内存中
- 包含引用值的变量实际上只包含指向相应对象的一个指针,而不是对象本身
- 从一个变量到另一个变量复制引用值,只会复制指针,因此结果是两个变量都指向同一个对象
typeof 操作符可以确定值的原始类型,instanceof 操作符用于确保值的引用类型(针对数组变量时候,注意使用instanceof的前提是只有一个全局执行上下文);变量的执行:任何变量都存在于某个执行上下文中(也称为作用域)。这个上下文(作用域)决定了变量的生命周期,以及它们可以访问代码的哪些部分。
- 执行上下文分为 ① 全局上下文、② 函数上下文、③ 块级上下文
- 代码执行流每进入一个新上下文,都会创建一个作用域链,用于搜索变量和函数
- 函数或块的局部上下文不仅可以访问自己作用域内的变量,也可以访问任何包含上下文乃至全局上下文的变量
- 全局上下文只能访问全局上下文中的变量和函数,不能直接访问局部上下文中的任何数据
- 变量的执行上下文用于确定什么时候释放内存;
JS数组
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>数组定义</title> <script type="text/javascript"> //"Audi", "BMW", "Volvo"; //数组定义方式1 var cars1 = ["Audi", "BMW", "Volvo"]; console.log("cars1=" + cars1); console.log(cars1[1]);//表示访问 cars1 数组的第2个元素, 1表示下标/索引,从0开始编号 //数组定义方式2 var cars2 = [];//空数组 //添加元素 cars2[0] = "奥迪"; cars2[1] = "宝马"; cars2[2] = "奔驰"; console.log("cars2=" + cars2); console.log("cars2[2]=" + cars2[2]);//奔驰 console.log("cars2[10]=" + cars2[10]);//如果该元素不存在,返回的就是undefined //数组定义方式3 var cars3 = new Array("Audi", "BMW", "Volvo"); console.log("cars3=" + cars3); console.log("cars3[0]=" + cars3[0]);//Audi //数组定义方式4 var cars4 = new Array();//空数组 console.log(typeof cars4); //object cars4[0] = "法拉利"; cars4[1] = "保时捷"; cars4[2] = "yy";//相当于是给数组扩容 cars4[0] = "zz";//替换 cars4[8] = "红旗";//扩容, 如果是跳过了下标给赋值,那么中间没有赋值的元素为undefined console.log("cars4[3]=" + cars4[3]);//undefined console.log("cars4= " + cars4); //遍历数组 for (i = 0; i < cars4.length; i++) { console.log(cars4[i]); //log 方法会自动换行 } </script> </head> <body> </body> </html>
JS函数
函数是由事件驱动的,或者当它被调用时,执行的可重复使用的代码块;
执行函数的方式:1、主动调用;2、事件触发。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>使用函数方式1</title> <script type="text/javascript"> //定义没有返回值的函数 function f1() { alert("f1() 被调用..."); } f1(); //定义有形参的函数 //这里的形参,不需要指定类型, name的数据类型是由实参决定 function f2(name) { alert("hi " + name); } f2("jack"); //定义有形参和返回值的函数, 不需要指定返回类型, 返回类型由返回的数据来决定 //js的函数调用机制和java一样 function f3(n1, n2) { return n1 + n2; } alert("f3(10, 20)=" + f3(10, 20)); </script> </head> <body> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>使用函数的第二种方式</title> <script type="text/javascript"> //可以理解成f1指向了函数 var f1 = function () { alert("hi"); } console.log(typeof f1); f1();//调用函数 var f3 = f1; f3(); var f2 = function (name) { alert("hi " + name); } f2("小米"); var f4 = function (n1, n2) { return n1 + n2; } alert("res= " + f4(10, 50)); </script> </head> <body> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>函数使用注意事项和细节</title> <script type="text/javascript"> //1. JS 中函数的重载会覆盖掉上一次的定义 //2. 当你调用f1() 时候其实调用的是 f1(name) //3. 调用f1(name) 如果你没有传入实参, 那么这个name就是undefined function f1() { alert("ok jack~") } function f1(name) { alert("hi " + name); } f1(); // 2. 函数的 arguments 隐形参数(作用域在 function 函数内) // (1) 隐形参数: 在 function 函数中不需要定义,可以直接用来获取所有参数的变量。 // (2) 隐形参数特别像 java 的可变参数一样。 public void fun( int ... args ) // (3) js 中的隐形参数跟 java 的可变参数一样。操作类似数组 function f2() { //遍历 函数的 arguments 隐形参数,arguments 是数组 //如果我们希望通过 console.log输出对象的数据,使用, 连接而不是+ console.log("arguments= ", arguments); console.log("arguments长度= " + arguments.length) alert("f2()...") } f2(10, 20, 30, "java"); //3 (1)如果我们的函数有形参,在传入实参的时候,仍然按照顺序匹配 // (2)如果有匹配上,就赋给他, 如果没有匹配上,也无所谓 // (3)仍然会把所有的实参,赋给 arguments // (4)如果形参个数,大于了实参个数,则该形参的值为undefined function f3(n) { console.log("n=" + n);//100 console.log("arguments= ", arguments);//100, 90, 20 } f3(100, 90, 20); </script> </head> <body> </body> </html>
说明:
- 如果不调用函数,那么该函数时不会执行;
- JS中函数的重载会覆盖掉上一次的定义;
- 函数的arguments隐形参数(作用域在 function 函数内),在function函数中不需要定义,可以直接用来获取所有参数的变量,跟 java 的可变参数一样。操作类似数组 public void fun( int ... args );
- 实参、形参的类型、数量无需保持一致
JS自定义对象
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>自定义对象</title> <script type="text/javascript"> //自定义对象的方式1 //person是一个空对象,没有自定义的函数和属性 var person = new Object(); console.log("person类型=" + typeof(person));//object //增加一个属性name person.name = "jack"; //增加一个属性 person.age = 20; //增加函数 person.say = function () { //这里的this就是person console.log("person的信息 " + this.name + " " + this.age + " " + this.job); } //调用 //访问属性 console.log("name= " + person.name + " " + person.email); //访问方法 person.say(); //小细节, 如果没有定义属性,直接使用,就会出现变量提升, 显示undefined console.log("address= " + person.address); </script> </head> <body> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>自定义对象方式2:{} 形式</title> <script type="text/javascript"> //演示自定义对象方式2:{} 形式 var person = { name: "老韩", //说明多个属性和函数之间,使用,隔开 age: 20, hi: function () { console.log("person信息= " + this.name + " " + this.age); }, sum: function (n1, n2) { return n1 + n2; } } //使用 console.log("外部访问 name= " + person.name + " age=" + person.age); person.hi(); console.log("sum=" + person.sum(10, 30)); </script> </head> <body> </body> </html>
事件
事件是电脑输入设备与页面进行交互的响应;事件通常与函数配合使用,这样就可以通过发生的事件来驱动函数执行;
事件的注册(绑定): 当事件响应(触发)后要浏览器执行哪些操作代码,叫事件注册或事件绑定;
静态注册事件: 通过 html 标签的事件属性直接赋于事件响应后的代码;
动态注册事件:
- 通过 js 代码得到标签的 dom 对象,然后再通过 dom 对象.事件名 = function(){} 形式;
- 步骤:1. 获取标签<--->dom 对象; 2. dom 对象.事件名 = fucntion(){}
常用事件
onload加载完成事件
- onload : 某个页面或图像被完成加载
- 页面加载完成之后, 常用于做页面 js 代码初始化操作
onclick单击事件
- 常用于按钮的点击响应操作
onblur失去焦点事件
- 常用用于输入框失去焦点后验证其输入内容是否合法
onchange内容发生改变事件
- 常用于下拉列表和输入框内容发生改变后操作
onsubmit 表单提交事件
- 常用于表单提交前, 验证所有表单项是否合法
- 邮箱的正则表达式: var emailPatt = /^[w-]+@([a-zA-Z]+.)+[a-zA-Z]+$/;
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>onclick 单击事件</title> <script type="text/javascript"> //定义一个函数 function sayOK() { alert("你点击了sayOK按钮"); } //1. 在js中,将页面窗口 映射成 window dom对象 //2. window对象有很多的函数和属性,可以使用 //3. window.onload 表示页面被加载完毕 //4. 后面的 function (){} 表示加载完毕后,要执行的函数/代码 window.onload = function () { alert("动态注册 onload 事件"); // 动态注册 onclick 事件 //1. 先拿到 id=btn01 的 button对应dom对象(当页面加载完成后,即执行window.onload后,才能得到) //2. 通过 dom对象动态的绑定onclick事件 //3. 通过document的 getElementById获取对应的dom对象 // 挖坑~填坑 var btn01 = document.getElementById("btn01"); // alert(btn01); //[object HTMLButtonElement] btn01.onclick = function () { alert("你点击了sayHi按钮"); } } </script> </head> <body> <!--静态注册 onClick 事件--> <button onclick="sayOK()">sayOK按钮</button> <!--动态注册 onClick 事件--> <button id="btn01">sayHi按钮</button> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>onblur 失去焦点事件</title> <script type="text/javascript"> //静态绑定 function upperCase() { //1. 先得到fname 输入框的value -> 得到对应dom对象 var fname = document.getElementById("fname"); fname.value = fname.value.toUpperCase(); } //在页面加载完毕,完成动态绑定 window.onload = function () { //1.得到fname2的dom对象 var fname2 = document.getElementById("fname2"); fname2.onblur = function () { fname2.value = fname2.value.toUpperCase(); } } </script> </head> <body> 输入英文单词: <input type="text" id="fname" onblur="upperCase()" /><br /> 输入英文单词: <input type="text" id="fname2" /> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>onchange 内容发生改变事件</title> <script type="text/javascript"> function mySal() { alert("工资范围变化了~"); } //动态注册 window.onload = function () { //获取到sel01的dom对象 var sel01 = document.getElementById("sel01"); //给sel01绑定onchange事件 sel01.onchange = function () { alert("你换女友的~"); } } </script> </head> <body> 你当前工资水平: <!--静态注册 onchange 事件--> <select onchange="mySal()"> <option>--工资范围--</option> <option>10k以下</option> <option>10k-30k</option> <option>30k以上</option> </select> <br/> 你当前女友是谁: <select id="sel01"> <!-- 动态绑定 onchange--> <option>---女友---</option> <option>艳红</option> <option>春桃</option> <option>春花</option> </select> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>onsubmit 表单提交事件</title> <script type="text/javascript"> //静态注册表单提交事件 function register() { //先得到输入的用户名和密码 var username = document.getElementById("username"); var pwd = document.getElementById("pwd"); //判断是否为空"" if ("" == username.value || "" == pwd.value) { alert("用户名和密码不能为空, 不能提交"); return false;//不提交 } //表示要提交 return true; } //动态注册表单提交事件 window.onload = function () { //使用折半法, 观察原页面是否真的是最新的, 是不是修改的页面和访问的页面一致 (查看页面的源代码,可查看是否一致)-->查找问题; //得到 from2 表单dom对象 var form2 = document.getElementById("form2"); // //给form2绑定onsubmit事件, onsubmit 绑定的函数会直接将结果(f,t)返回给onsubmit form2.onsubmit = function () { if(form2.username.value == "" || form2.pwd.value == "") { alert("用户名和密码不能为空, 不能提交"); return false;//不提交 } return true; } } </script> </head> <body> <h1>注册用户1</h1> <!-- 静态注册表单提交事件 --> <form action="ok.html" onsubmit="return register()"> u: <input type="text" id="username" name="username"/><br/> p: <input type="password" id="pwd" name="pwd"/><br/> <input type="submit" value="注册用户"/> </form> <h1>注册用户2</h1> <!-- 动态注册表单提交事件 --> <form action="ok.html" id="form2"> u: <input type="text" name="username"/><br/> p: <input type="password" name="pwd"/><br/> <input type="submit" value="注册用户"/></form> </body> </html>
运算符
算术运算符
用于执行变量与/或值之间的算术运算;
赋值运算符
用于给 JavaScript 变量赋值;
关系运算符
在逻辑语句中使用,以测定变量或值是否相等;
注意事项:
等于: == 是简单的做字面值的比较
全等于: === 除了做字面值的比较之外,还会比较两个变量的数据类型
逻辑运算符
用于测定变量或值之间的逻辑;
注意事项
在 JavaScript 语言中,所有的变量,都可以做为一个 boolean 类型的变量去使用。
0 、null、 undefined、""(空串) 都认为是 false
&& 且运算,有两种情况 => (即 && 返回值是遵守短路与的机制)
|| 或运算, 有两种情况 => (即|| 返回值是遵守短路或的机制)
短路现象:当&&和||有确定结果后,后面的表达式不再执行;
条件运算符
类似 Java 的三元运算符。
<title>条件运算符</title> <script type="text/javascript"> // 规则 如果 (10 > 1) 条件表达式为 T, 返回第一个表达式的值 ;条件表达式为 F, 返回第 2 个表达式的值 var n1 = 90; var n2 = 1; var res = n2 > 9 ? "jack" + " 你好" : 800 + n1; alert("res=" + res); </script>