JavaScript学习笔记
JS基本内容
JS简介:
JS让网页可以互动,是web编程语言
JS是事件驱动型的编程语言,依靠事件去驱动,然后执行对应的程序
事件如click,对应事件句柄为onclick。事件句柄就是在事件单词前添加一个on,事件句柄是以HTML标签的属性存在
<body>
<input type="button" value="hello" onclick="window.alert('恭喜你开始了JS!')
window.alert('HHH')"/>
</body>
上面代码中,window可以省略不写
而且需要注意的是,第一条语句后面如果换行,则不需要分号
暴露在脚本块中的程序,在页面打开时执行,自上而下
<body>
<script type="text/javascript">
window.alert("Hello JS!");
</script>
</body>
javascript的脚本块在一个页面当中可以出现多次,且位置也没有要求
强类型:
java是强类型语言,编译阶段,数据类型等就固定,直到最终内存释放,一直都不变
javascript是弱类型语言,没有编译阶段,一个变量可以随意赋值
<body>
<script>
var i;
alert("i:"+i);
</script>
</body>
JS函数:
方式一:function 函数名(形式参数列表){函数体}
方式二:函数名 = function(形式参数列表){函数体}
JS函数没有重载一说,如果两个函数重名,即使形参不同,后面一个函数也会覆盖前面那个函数
<body>
<script>
function hello(userName){
alert("hello");
}
function hello(){
alert("hello javascript!");
}
hello("java");
hello();
</script>
</body>
这段代码只会弹出两次hello javascript!
全局变量与局部变量:
全局变量是在函数体之外声明的变量,生命周期随着浏览器的存货
局部变量是在函数体中声明的变量,包括形参,函数执行结束,局部变量就释放
<body>
<script>
// 全局变量
var userName = "zhangsan";
function hello(){
// 局部变量
var userName = "lisi";
// 就近原则
alert("userName:"+userName);
}
hello();
// 局部变量随着方法的消失而消失
alert("userName:"+userName);
</script>
</body>
如果在函数中,局部变量前未加var
,那么改该变量将变为全局变量
2022/1/20 更新
全局变量和局部变量的新理解:搞懂JavaScript全局变量与局部变量,看这篇文章就够了,参考这篇文章,再次进行理解
<script>
var a = 1; //全局变量
! function b() {
var a = 2; //局部变量a在这行定义
console.log(window.a); //a为1,这里的a是全局变量哦!
console.log(a); //a为2,这里的a是局部变量哦!
}()
console.log(a); //a为1,这里并不在function b scope内,a的值为全局变量的值
</script>
!function(){}()
表示立即运行的匿名函数
这个例子中,首先a是全局变量,但是到了函数中,a变为了局部变量,输出时就为局部变量的值,而函数调用完,则又变回了全局变量
<script>
var a = 3;
!function(){
console.log("a:"+a); // undefined
var a = 5;
console.log("a:"+a); // 5
}()
console.log("a:"+a); // 3
</script>
JavaScript这里比较奇怪,即使一开始是全局变量,如果函数中是局部变量,那么一开始就是未定义,如果函数中是全局变量,则为一开始的全局变量
<script>
var a = 3;
!function(){
console.log("a:"+a); // 3
a = 5;
console.log("a:"+a); // 5
}()
console.log("a:"+a); // 5
</script>
注意输出从undefined 5 3
变为了3 5 5
解释:变量在同一个范围内,就视为已经声明,所以第一个例子中,先声明var a;
,然后因为是局部变量,所以为undefined
。到了第二个例子,声明全局变量,那么就输出了3
,后面自然因为全局变量进行了修改,就输出了5
还有一个比较奇怪的地方,就是函数中,如果重新指定同名变量为局部变量,那么该变量就从全局变量变为了局部变量
<script>
function varTest() {
// var a = 1;
c = 6;
a = 5;
{
//var a = 2; // 这里如果不注释,a就成了局部变量,那么结尾输出a会报错
console.log("a:",a); // 2
}
console.log("a:",a); // 2
}
function letTest() {
let b = 1;
{
let b = 2; // 代码块中,新的变量
console.log("b:",b); // 2
}
console.log("b:",b); // 1
}
varTest();
letTest();
console.log("c:",c)
console.log("a:",a); // 如果在varTest函数中重新指定a为局部变量,那么此时报错
</script>
ES6之前,只有全局和函数块,ES6加入了代码块,代码块就是花括号,但是需要配合let等来使用,使用var并没有进入到代码块,只是方便阅读
而const表示只读
数据类型:
JS中的变量声明时不需要指定数据类型,但是赋值时,每一个数据还是有类型的
原始类型:
- Undefined、Number、String、Boolean、Null
引用类型:
- Object以及Object的子类
使用typeof可以在程序的运行阶段动态获取变量的数据类型,格式为:typeof 变量名
,结果为一下6个字符串之一(即需要带双引号)
- undefined、number、string、boolean、object、function
JavaScript中没有equals方法,请直接使用==
<body>
<script>
function sum(a,b){
if(typeof a == "number" || typeof b == "number"){
return a+b;
}else{
alert(a+","+b+"必须为数字");
}
}
var resValue = sum("abc","hello");
alert(resValue);
alert(typeof sum);
var x;
alert(typeof x);
var m = 1;
var n = "1";
var k = null;
var j = false;
alert(typeof m);
alert(typeof n);
alert(typeof j);
alert(typeof k);
</script>
</body>
Undefined类型只有一个值,这个值就是undefined
常用函数
Number中常用函数:
- isNaN(变量)
- parseInt(变量)
- parseFloat(变量)
- Math.ceil(变量)
String中常用函数:
- indexOf
- lastIndexOf
- replace
- substr
- substring
- split
Object:
属性:
- prototype(最常用)
- constructor
函数:
- toString
- valueOf
- toLocaleString
<body>
<script>
function sayHello(){
alert("Hello");
}
sayHello();
var say = new sayHello();
alert(say);
</script>
</body>
类的定义和函数定义,不能说一模一样,只能说完全一样
区别在于使用时,类使用new来创建,函数则直接调用
稍微深入
JS类中定义函数及prototype用法:
<body>
<script>
function myFunc(name,age,number){
this.name = name;
this.age = age;
this.number = number;
// 类中定义函数
this.getNumber = function(){
return this.number;
}
}
var myFunc1 = new myFunc("lisi",18,100);
var temp = myFunc1.getNumber();
alert(temp);
// 通过prototype动态扩展函数
myFunc.prototype.getAge = function(){
return this.age;
}
// 注意,这里的new不要去掉,去掉的话就不是一个类,会有问题
var zhangsan = new myFunc("zhangsan",20,120);
var age = zhangsan.getAge();
var number = zhangsan.getNumber();
alert(age);
alert(number);
</script>
</body>
同时,因为new出来的String也是Object,那么String也可以通过prototype添加函数
<body>
<script>
String.prototype.addFunc = function(){
alert("恭喜你添加了一个新函数");
}
"hello".addFunc();
</script>
</body>
比较Java和JavaScript的类的定义与创建对象
// java定义类
public class User{
private String username;
private String pasword;
public User(){}
public User(String username,String password){
this.username = username;
this.password = password;
}
}
// java创建对象
User user = new User();
User user = new User("zhangsan","123");
User = function(username,password){
this.username = username;
this.password = password;
}
var u = new User();
var u = new User("zhangsan");
var u = new User("zhangsan","123");
双等于和三等于
双等于比较值,三等于全都比较(类型)
<body>
<script>
alert(10=="10"); // true
alert(10==="10"); // false
alert(1==true); // true
alert(1===true); // false
alert(undefined==null); // true
alert(undefined===null) // false
</script>
</body>
JS常用事件:
- blur:失去焦点
- focus:获得焦点
- click:鼠标单击
- dblclick:鼠标双击
- keydown:键盘按下
- keyup:键盘弹起
- mousedown:鼠标按下
- mouseover:鼠标经过
- mouseout:鼠标离开
- mouseup:鼠标弹起
- reset:表单重置
- submit:表单提交
- change:下拉列表选中项改变,或文本框内容改变
- load:页面加载完毕
回调函数与调用:
<body>
<script type="text/javascript">
// 对当前程序来说,sum被称为回调函数
function sum(a,b){
alert(a+b);
}
sum(3,5);
userName = function(username){
alert("hello "+username);
}
</script>
<!-- 将函数sum注册到按钮上,等待click事件发生后,浏览器调用 -->
<button onclick="sum(6,9)">计算6和9的和</button>
<button onclick="userName('javascript');">点击欢迎</button>
</body>
事件注册的集中方式:
- 方式一:直接在html语句中加入事件
- 方式二:html给定id,然后在script中获取id,再用id注册事件
- 方式三:匿名函数注册事件
- 方式四:整合起来,不用中间过程,有点像Java中的链式
<body>
<button onclick="window.alert('Hello JS!')">直接注册</button>
<button id="button1">通过get获取</button>
<button id="button2">匿名函数</button>
<button id="button3">匿名函数整合</button>
<script>
myFunc1 = function(){
alert("Hello JS1!");
}
// 通过getElementById获取,然后注册
var id1 = document.getElementById('button1');
id1.onclick = myFunc1; // 注意这里给函数名,不是给函数,即id1.onclick = myFunc1();是错误的
// 通过匿名函数注册事件
var id2 = document.getElementById("button2");
id2.onclick = function(){
alert('Hello JS2!');
}
// 整合
document.getElementById('button3').onclick = function(){
alert('Hello JS3!');
}
</script>
</body>
JS执行顺序:
JS一般放在内容的后面,如果想放在内容前面,最好加上onload表示页面加载之后再执行js代码
<body>
<script>
window.onload = function(){
document.getElementById("btn").onclick = function(){
alert("Hello JS!");
}
}
</script>
<button id="btn">开始</button>
</body>
JS修改属性值:
<body>
<script>
window.onload = function(){
document.getElementById("btn").onclick = function(){
var textVal = document.getElementById("mytext");
textVal.type = "checkbox";
}
}
</script>
<input type="text" id="mytext">
<button id="btn">点击修改</button>
</body>
JS捕捉回车
<body>
<input type="text" id="btn">
<script>
document.getElementById("btn").onkeydown = function(event){
if(event.keyCode==13){
alert("正在验证登陆!")
}
}
</script>
</body>
void
void运算符执行表达式,但不返回任何结果,在超链接中可以运用上
javascript:
表示后面接的是一段JavaScript代码,而不是路径
void(0)
表示不返回任何结果
<body>
<div>首页</div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<div>尾部</div>
<a href="javascript:void(0)" onclick="window.alert('测试中')">点击</a>
<br><br><br>
</body>
数组变量
JavaScript中的数组遍历,如果使用for in语句,与Java有些不一样
<body>
<script>
var arr = [1,'t',false,true,null]
for(var i=0;i<arr.length;i++){
alert(i)
}
for(var i in arr){
alert(i)
}
</script>
</body>
上述输出都是数组下标,而不是数组元素
如果是对象的话,for in就变成了属性名,此时为字符串
<body>
<script>
UserName = function(username,password){
this.username = username
this.password = password
}
var obj = new UserName("张三","123456")
for(var i in obj){
alert(obj[i])
}
</script>
</body>
DOM
ECMAScript是js基础内容,DOM是文档对象模型,对HTML中的节点进行操作;BOM是浏览器对象,对浏览器本身操作,如前进、后退、弹窗等
BOM顶级对象是window
DOM顶级对象是document,实际上BOM包括DOM
相互影响
<body>
<input type="text" id="text">
<button id="btn">点击</button>
<script>
window.onload = function(){
document.getElementById("btn").onclick = function(){
var xxx = document.getElementById("text")
alert(xxx.value)
alert(document.getElementById("text").value)
document.getElementById("text").value = "hello"
alert(document.getElementById("text").value)
}
}
</script>
<hr>
<script>
window.onload = function(){
document.getElementById("id3").onclick = function(){
document.getElementById("id2").value = document.getElementById("id1").value
}
}
</script>
<input type="text" id="id1">
<br>
<input type="text" id="id2">
<br>
<button id="id3">切换</button>
<br>
<script>
window.onload = function(){
document.getElementById("tttt").onblur = function(){
alert(this.value)
}
}
</script>
<input type="text" id="tttt">
</body>
innerHTML
<body>
<script>
window.onload = function(){
document.getElementById("btn").onclick = function(){
document.getElementById("text").innerHTML = "<font color='red'>abcdefg</font>"
}
}
</script>
<div id="text"></div>
<button id="btn">写入文本框</button>
</body>
正则表达式
正则表达式主要用于格式匹配
对于自己来说,贪婪匹配,前置约束等内容不太熟悉
反向引用
最简单最有用的应用:查找文本中两个相同的相邻单词的匹配项的能力
如:
var str = "Is is the cost of of gasoline going up up";
var patt1 = /\b([a-z]+) \1\b/ig;
document.write(str.match(patt1));
修饰符
正则表达式的标记(修饰符)用于指定额外的匹配策略
标记不写在正则表达式里,标记位于表达式之外,如上面反向引用的最后面的ig
- i表示不区分大小写
- g表示全局匹配
- m表示多行匹配
- s表示特殊字符圆点
.
中包含换行符\n
(默认情况下的.
匹配除换行符\n
之外的任何字符)
JS的正则
方式一:
var regExp = /正则表达式/flags
方式二:
var regExp = new RegExp("正则表达式","flags")
邮箱验证
<body>
<script>
window.onload = function(){
document.getElementById("btn").onclick = function(){
var email = document.getElementById("text").value
var regExp = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/
var result = regExp.test(email)
if(!result){
document.getElementById("span").innerHTML = "邮箱格式错误!"
}else{
document.getElementById("span").innerHTML = "邮箱格式正确!"
}
}
document.getElementById("text").onfocus = function(){
document.getElementById("span").innerHTML = ""
}
}
</script>
<input type="text" id="text">
<button id="btn">点击</button>
<br>
<span id="span" style="font-size: 14px;color: red;"></span>
</body>
prototype+正则
在低版本的IE中,trim函数不能使用,这时需要通过动态扩展prototype结合正则表达式来进行重写trim函数
<body>
<script>
/*
window.onload = function(){
document.getElementById("btn").onclick = function(){
var result = document.getElementById("text").value
result = result.trim()
alert("----->"+result+"<-----")
}
}
*/
// 如果在低版本的IE中,trim函数不能使用,这时可以通过prototype进行扩展
String.prototype.trim = function () {
// alert("正在改写trim......")
return this.replace(/^\s+/, "").replace(/\s+$/, "")
}
// "hello".trim()
window.onload = function () {
document.getElementById("btn").onclick = function () {
var result = document.getElementById("text").value
result = result.trim()
alert("----->" + result + "<-----")
}
}
</script>
<input type="text" id="text">
<input type="button" value="按钮" id="btn" name="button">
</body>
表单验证
![image-20220117184554199](C:\Users\OptiPlex 7090\AppData\Roaming\Typora\typora-user-images\image-20220117184554199.png)
<body>
<script>
window.onload = function () {
document.getElementById("btn").onclick = function () {
var flag = true
var userRegExp = /^[A-Za-z0-9]{6,14}$/
var password1Reg = /^[a-zA-Z]\w{5,17}$/
var username = document.getElementById("text1").value
var result1 = userRegExp.test(username)
if (result1) {
// alert("true")
var password1 = document.getElementById("password1").value
var result2 = password1Reg.test(password1)
if (result2) {
// alert("true")
var result3 = document.getElementById("password2").value
if (password1 == result3) {
alert("注册成功!")
} else {
document.getElementById("password2Span").innerHTML = "两次密码不一致"
flag = false
}
} else {
// alert("false")
document.getElementById("password1Span").innerHTML = "密码不满足要求"
flag = false
}
} else {
// alert("false")
document.getElementById("textSpan").innerHTML = "用户名不满足要求"
flag = false
}
document.getElementById("text1").onfocus = function () {
document.getElementById("textSpan").innerHTML = ""
}
document.getElementById("password1").onfocus = function () {
document.getElementById("password1Span").innerHTML = ""
}
document.getElementById("password2").onfocus = function () {
document.getElementById("password2Span").innerHTML = ""
}
}
}
</script>
<div>注册界面</div>
用户名:<input type="text" id="text1">
<span id="textSpan"></span>
<br>
密 码 : <input type="password" id="password1">
<span id="password1Span"></span>
<br>
确 认 : <input type="password" id="password2">
<span id="password2Span"></span>
<br>
<input type="button" value="注册" id="btn">
<span id="btnSpan"></span>
</body>
正则表达式网上抄的,innerHTML中的内容写在head中的style里面
可以把点击按钮进行验证,改成onblur,这样条内容都会验证,而不是全部写完了再验证
复选框
<body>
<script>
window.onload = function () {
var first = document.getElementById("firstCheck")
var box = document.getElementsByName("box")
first.onclick = function () {
for (var i = 0; i < box.length; i++) {
// alert(box[i])
box[i].checked = first.checked
}
}
var total = box.length
for(var j=0;j<box.length;j++){
box[j].onclick = function(){
var checkCount = 0
for(var k=0;k<box.length;k++){
if(box[k].checked){
checkCount++
}
}
first.checked = (total == checkCount)
}
}
}
</script>
<input type="checkbox" id="firstCheck"><br>
<input type="checkbox" id="secondCheck" name="box">抽烟<br>
<input type="checkbox" id="thirdCheck" name="box">喝酒<br>
<input type="checkbox" id="lastCheck" name="box">烫头<br>
</body>
周期函数
有时候我们需要周期性执行某函数,那么此时需要用到周期函数
<body>
<input type="button" id="btn" value="时间">
<input type="button" id="stopBtn" value="停止" onclick="stop()">
<div id="text"></div>
<script>
document.getElementById("btn").onclick = function(){
start()
}
function start(){
varStop = window.setInterval("displayTime()",1000)
}
function displayTime(){
var date = new Date();
date = date.toLocaleString()
document.getElementById("text").innerHTML = date
}
function stop(){
window.clearInterval(varStop)
}
</script>
</body>
确认confirm
<body>
<input type="button" id="btn" value="删除">
<script>
function del(){
var flag = window.confirm("亲,确认删除吗?")
alert(flag)
}
window.onload = function(){
document.getElementById("btn").onclick = function(){
del()
}
}
</script>
</body>
后退:
window.history.back()
window.history.go(-1)
网址:
window.location.href
顶级窗口
// 窗口1
<body>
<iframe src="窗口2.html" frameborder="0"></iframe>
<script></script>
</body>
// 窗口2
<body>
<div>
<input type="button" id="btn" value="将当前窗口设置为顶级窗口" onclick="setTop()">
</div>
<script>
function setTop() {
if (window.top != window.self) {
window.top.location = window.self.location
}
}
</script>
</body>
JSON
数据交换格式
eval函数
<body>
<script>
window.eval("var i = 100")
alert("i:"+i)
</script>
</body>
使用json数据
<body>
<input type="button" value="显示" id="btn">
<h2>员工列表</h2>
<hr>
<table border="1px" width=50%>
<tr>
<th>员工编号</th>
<th>员工名字</th>
<th>员工薪资</th>
</tr>
<tbody id="tbody">
<!-- <tr>
<td>7369</td>
<td>SMITH</td>
<td>800.00</td>
</tr>
<tr>
<td>7369</td>
<td>SMITH</td>
<td>800.00</td>
</tr>
<tr>
<td>7369</td>
<td>SMITH</td>
<td>800.00</td>
</tr> -->
</tbody>
</table>
总共<span id="count">0</span>条数
<script>
var data = {
"total":4,
"emps":[
{"empno":7369,"ename":"SMITH","sal":800.00},
{"empno":7370,"ename":"SMIH","sal":1800.00},
{"empno":7371,"ename":"SMTH","sal":2800.00},
{"empno":7332,"ename":"SITH","sal":3800.00}
]
}
document.getElementById("btn").onclick = function(){
var emps = data.emps;
var html = ""
for(var i=0;i<emps.length;i++){
var emp = emps[i]
html += "<tr>"
html += "<td>"+emp.empno+"</td>"
html += "<td>"+emp.ename+"</td>"
html += "<td>"+emp.sal+"</td>"
html += "</tr>"
document.getElementById("tbody").innerHTML = html
}
document.getElementById("count").innerHTML = data.total
}
</script>
</body>
箭头函数
箭头函数类似python中lambda
使用如下:
> const add = (a,b) => a+b
< undefined
> add(3,7)
< 10
上述内容是在控制台进行输出
这里有点没搞懂?其实就是把箭头号左移看成function,当作匿名函数
> const add = function(a,b){ return a+b}
上面去掉花括号纯粹是为了装高手,让你我阅读难度增加,而且也省略了return语句
那么为什么要有箭头函数呢?参考箭头函数与普通函数不只是写法上的区别...,写下自己的思考
- 箭头函数的this,来源于作用域链,不会出现普通函数this指代不清的情况
- 二者本质上没什么区别
- 如果要用到所写函数来调用的方法,可能普通函数更好