介绍
- 简称JS,是一种浏览器解释型语言,嵌入到网页中由浏览器负责解析和执行。可以实现网页动态效果,用户交互,实现网络请求或游戏制作。
- 组成
1)核心语法(ECMAScript 5)
2)BOM(浏览器对象模型),提供操作浏览器窗口的方法
3)DOM(文档对象模型),提供操作HTML文档的方法
JS使用
- 元素绑定事件
事件:用户的行为或元素的状态
事件处理:元素监听到事件发生后作出的响应
事件名称:onclick(单击事件) ondblclick(双击事件)
语法:将事件名称以标签属性的形式绑定到元素上。 eg.<h1 onclick="JS 代码"></h1>
- 内嵌方式
使用<script type="text/javascript"></script>
书写JS语句。标签可以书写在任意位置,书写任意多次。浏览器在解析到script标签时会直接执行内部的脚本代码。 - 外联方式
创建外部的JS文件(.js),HTML文件中使用<script src=""></script>
引入。注意<script>
既可以实现内嵌,也可以实现外链,但是二选一。 - 语法规范
1)JS代码区分大小写
2)JS语句可以使用;作为结束的标志,也可以省略。
3)JS中注释
// 单行注释
/* 多行注释 */ - 输入语句
console.log() 控制台输出
alert("") 网页警告框
prompt("") 带输入框的弹框
document.write("") 在网页中输出,动态向body标签中写入内容,可以识别标签语法
使用:
1)代码的书写位置即为添加位置
2)使用元素绑定事件的方式去动态添加,会造成页面重写。(事件发生之前,body可能就加载完毕了)
JS基础语法
- 变量与常量
1)变量:
- 用于存储在程序运行过程中随时可以修改的数据。
- 使用var关键字声明变量
- 注意:
- 变量声明未赋值时,默认为undefined
- 未声明未赋值会报错
- 声明变量时可以省略关键字,影响作用域
// 变量声明时可以省略关键字var,一旦省略关键字,一律为全局变量
age=20;
// 变量声明未赋值,默认为undefined
var username;
console.log(username);
// 访问未声明,未赋值的变量,报错
console.log(n) // 报错not defined
console.log(num) // undefined
// 变量提升,浏览器在执行JS代码之前会检索所有的var关键字,只要在程序中有变量的声明,就不会报错,默认为undefined
var num = 1000
2)常量:
- 一经定义就不能修改的数据
- 使用const关键字声明常量,通常,常量名采用全大写字母表示
- 命名规范:自定义变量名,常量名,函数名或对象名时,可以由数字,字母,下划线和$组成,不允许以数字开头,不能与关键字冲突,尽量见名知意。多个单词组成时采用小驼峰表示。
// 常量
const PI = 3.14
console.log(PI)
PI=3.14 // 报错,不能修改
// 定义变量,表示半径,计算周长和面积
var r = 10
var len = 2 * PI *r
var s = PI * r * r
// 保留n位小数位 toFixed(n)
len = len.toFixed(2)
console.log(len,s)
- 数据类型
1)简单数据类型(值类型)
- number
整数可以使用十进制,八进制或十六进制表示
// 整数
var a = 100
//八进制以0为前缀
var b = 053 // 43
//十六进制以0x为前缀
var c = 0x53 // 83
// 输出一律按十进制输出
console.log(a,b,c)
// 小数
var d = 1.5
var f = 1.5e3 //1.5*10^3
- string
字符串使用引号表示,会自动为每一位字符分配下标;每位字符都有自身的Unicode编码
var s1 = "Hello"
var s2 = "100"
//获取指定下标对应字符的Unicode编码
var code = s1.charCodeAt(0);
console.log(code) // 输出“H”的Unicode编码
- boolean
布尔值,只有true / false
var flag = true
-
undefined
变量声明未赋值时默认为undefined -
null
空值,解除对象引用
2)引用类型
主要指对象(函数,内置类型,自定义的对象)
3)检测数据类型
typeof num;
typeof (num);
- 数据类型转换
1)强制类型转换
- 转换字符串:toString(),返回转换后的结果
- 转换number
- Number(n),将变量n转换为number值,返回转换后的结果,如果变量中存在非number字符,一律转换失败,返回NaN(Not a Number)
- parseInt(n) / parseFloat(n),解析number部分。过程:如果参数为非字符串,将自动转换成字符串,逐位进行解析,对每一位字符进行转Number操作,一旦解析失败,就停止向后解析,返回结果
console.log(parseInt(15.3)) //15
console.log(parseInt("123hello")) // 123
console.log(parseInt("h123")) // NaN
console.log(parseInt(true)) // NaN
console.log(parseFloat("15.3")) // 15.3
console.log(parseFloat("a15.3")) // NaN
console.log(parseFloat("15.3a")) // 15.3
console.log(parseFloat("15.3.5")) //15.3
- 转换布尔值
Boolean(n)将变量转换布尔值:除“零”值以外,所有值都为真
// true
console.log(Boolean(1))
console.log(Boolean("10"))
console.log(Boolean(" "))//包含空白字符
// false
console.log(Boolean(0))
console.log(Boolean(0.0))
console.log(Boolean(""))//空字符串
console.log(Boolean(undefined))
console.log(Boolean(NaN))
console.log(Boolean(null))
//特殊
console.log(Number(undefined)) //NaN
console.log(Number(null)) //0
2)自动类型转换
- 字符串与其他数据类型进行“+”运算,一律为字符串拼接。将非字符串数据自动转换为字符串进行拼接。
- 其他情况下,一律自动转换为number参与数学运算
var r1 = 10+5
var r2 = "10"+"5" //"105"
var r3 = 5+"20" //"520"
var r4 = true + "20" // "true20"
var r5 = null + "20" // "null20"
var r6 = undefined + "20" // "undefined20"
var r7 = 10 + 5 + "hello" // "15hello"
var r8 = 10 + "hello" + 5 //"10hello5"
var res1 = "10" - 5 // 5
var res2 = "10a" - 55 //NaN参与数学运算,一律为NaN
var res3 = "10" - true // 9
var res4 = "10" + false // “10false”
var res5 = true + true // 2
/*
undefined + 10 // NaN
null + 10 // 10
true + 10 // 11
其他情况:
string与其他类型做非加法运算
number值与其他类型做数学运算
布尔值参与运算,一律转number
*/
- 运算符
1)赋值运算符 =
2)数学运算符 + - * / %(取余)
3)复合运算符 += -= *= /= %=
4)自增或自减运算符 ++ –
在变量自身值的基础上加1或减1
使用:
- 单独与变量结合,做前缀或做后缀没有区别
var a = 10
a++
++a
console.log(a) // 12
var b = "10"
b+=1 // b=b+1
console.log(b)//"101"
// 包含自动类型转换,转成number进行值的+1或-1
b++
console.log(b)//102
- 与其他运算符结合使用时,前缀和后缀有区分,前缀就先++/–,后缀就后++/–
var c = 10
var r1 = c++//r1?c?
console.log(r1,c) //10 11
var r2 = ++c
console.log(r2,c) //12 12
var n = 10
var r3 = n-- //r3=10,n=9
var r4 = --n //r4=8,n=8
console.log(r3,r4,n) // 10 8 8
5)比较运算符/关系运算
> >= <= ==(相等) !=(不等) ===(全等) !==
"10" == 10 //true
"10" === 10 //false
- 关系运算的结果一定是布尔值
- 运算规则:
- 字符串与字符串之间的比较,逐位比较
- 其他情况下一律转换number进行比较,如果转换失败,变成NaN参与关系运算,结果一律为false
var res1 = "a">"b" //Unicode码值的比较 false
var res2 = "1">"10" //比较编码值 false
var res3 = "2">"10" // true
// 其他情况一律转number
var res4 = 100 > 10 // true
var res5 = "100" > 10 // 100>10 true
var res6 = "100" > true // 100>1 true
var res7 = "hello" > true // NaN>1 false
var res8 = "10" > null // 10>0 true
var res9 = true>false // true
- 相等与全等
相等:包含自动类型转换,只要值相等,就成立
全等:严格比较,不会转换类型。要求类型一致并且值相等才成立
运算符
- 赋值运算符
- 算术运算符
- 复合运算符
- 自增/自减
- 关系运算符
"hello" > "abc" // "h">"a" --> true
"10" > 2 // 10 > 2 --> true
"10" > "2" // "1">"2" --> false
"abc" > 10 //NaN > 10 --> false
- 逻辑运算:逻辑运算用于表示表达式之间的关系,结果永远为布尔值
1)逻辑与 &&:全1则1,只有表达式全部为true,最终结果才为true
2)逻辑或 ||:有1则1,只要有一个表达式成立,最终结果就为true
3)逻辑非 !:对布尔结果取反
注:优先级 逻辑非>逻辑与>逻辑或
练习:
定义变量表示年份,判断是否是闰年(能被4整除并且不能被100整除,或者能被400整除)
var year = prompt("请输入年")
//只有“零”值为假
if(year){
// 逻辑与优先级高于逻辑或
var res = year % 4 == 0 && year %100 !=0 || year % 400 ==0
console.log(res)
}else{
// 带输入框的弹框,参数为字符串表示提示信息,返回用户输入的内容
year = prompt("请输入年")
}
- 三目运算符
语法:表达式1?表达式2:表达式3;
使用:判断表达式1是否成立,成立的话执行并返回表达式2的结果,不成立执行并返回表达式3 的结果
var age = 20
var r1 = age>=18 ? "成年人" : "未成年"
var r2 = age>=18 ? "成年人" : age<=7 ? "不用上学" : "义务教育"
console.log(r1,r2)
流程控制
- 控制代码的执行顺序和执行次数
- 分类:
1)顺序结构,从上到下依次执行
2)选择结构,根据条件是否成立,选择执行某一段代码
3)循环结构,根据条件是否成立,选择是否重复执行某段代码 - 选择结构
1)if语句
- 基本结构
if(条件表达式){
条件成立时执行
}
- if-else语句
if(条件){
条件成立时执行
}else{
条件不成立时执行
}
- 多重分支if-else if
if(条件1){
条件1成立时执行
}else if(条件2){
条件2成立时执行
}
...
else{
条件n不成立时执行
}
2)switch语句
用于值的全等匹配
语法:
switch(变量){
case 值1:
匹配全等之后执行的代码段
break;//结束匹配
case 值2:
匹配全等之后执行的代码段
break;//结束匹配
...
default:
所有case都不匹配时执行的默认操作
break;
}
特殊:
1)break关键字可以省略,一旦省略,会从当前匹配到的case开始向后执行所有的代码语句,直至碰到break关键字结束匹配或执行至结束
2)多个case共用代码段
case 值1:
case 值2:
...
//任一case匹配全等后执行的操作
break;
练习:输入年月日,得到天数
// 1.接收用户输入
var year = prompt("请输入年")
var month = prompt("请输入月")
var day = Number(prompt("请输入日"))
// 2.表示总天数
var sum = 0
// 闰年判断
var isRun = year%4==0 && year%100!=0 || year%400==0
// 3.整月天数的累加(month-1个月)
switch(month-1){ // month-1的结果为number值
// month-1整月:1~11个整月
case 11:
sum+=30
case 10:
sum+=31
case 9:
sum+=30
case 8:
sum+=31
case 7:
sum+=31
case 6:
sum+=30
case 5:
sum+=31
case 4:
sum+=30
case 3:
sum+=31
case 2:
sum+=28
case 1:
sum+=31
}
// 4.当前月天数的累加
sum+=day
// 5.闰年判断
if(isRun && month>2){
sum++
}
console.log(sum)
- 循环结构
控制代码的重复执行
1)while循环
语法:
定义循环变量
while(循环条件){
条件成立时执行,循环体
更新循环变量
}
2)do-while循环
先执行循环体,再判断条件是否成立,决定是否开启下一次循环
语法:
定义循环变量
do{
循环体
更新循环变量
}while(循环条件)
与while循环的区别:
- while循环先判断条件,成立时执行循环体;
- do-while循环先执行循环体,再判断条件。不管条件是否成立。循环体至少走一次
练习:循环接收用户输入,输入“exit”表示退出,否则就在控制台中打印输入内容
// while
var input
while(input!="exit"){
input = prompt("请输入,exit表示退出")
console.log(input)
}
//do-while
do{
var input = prompt("请输入,exit表示退出")
console.log(input)
}while(input != "exit")
3)for循环
语法:
for(定义变量;循环条件;更新变量){
循环体
}
4)循环控制
break :跳出循环
continue:结束本次循环,开始下一次循环
5)循环嵌套
在循环中嵌套添加其他的循环
练习:控制台输出9*9乘法表
// i既是操作数,也代表行数
for(var i=1;i<=9;i++){
var show = ""
for(var j=1;j<=i;j++){
// 拼接当前行中所有的算式
show += i + '*' + j + '=' + i*j + '\t'
}
// 按行输出
console.log(show)
}
函数
- 函数用于保存一段待执行的代码,或者封装某个功能。
- 语法:
1)函数声明
function 函数名(参数列表){
函数体
return 返回值
}
2)函数调用
函数名(参数列表)
//1.无参数,无返回值的函数
function f1(){
console.log("f1被调用")
}
f1()
//2.带参数,无返回值的函数
function f2(a,b){ //形式参数
var r = a + b
console.log(r)
// 函数允许形参与实参个数不匹配
// 函数内部变量arguments,保存实际传递过来的参数
console.log(arguments)
}
//实际参数
f2(10,20)//传参
f2(100)
f2(100,200,30)
//3.函数的返回值:将函数内部的结果返回给外界使用
//return只能返回一个值,return后面的代码不执行
function f3(a){
if(a){
var r1 = a+a
var r2 = a*a
console.log(r1,r2)
return "合法"
}else{ //undefined 或 0
console.log("不合法")
return
}
}
var res = f3(5)
console.log(res)//合法
var res2 = f3()
console.log(res2)//undefined
- 作用域
全局作用域和函数作用域
1)全局变量:在程序任意位置都能访问。
- 函数外部定义的变量都是全局变量
- 函数内部省略var创建变量,一律为全局变量
2)局部变量:在函数体重使用var关键字声明的变量一律为局部变量,只能在当前函数体中使用,外界无法访问
var age = 20
function fn(){
unmae = "张三"
var n = 10
// 变量提升,当前作用域中使用var关键字声明变量age,浏览器执行过程中,一定使用局部变量,当前访问该变量时还未赋值
console.log(age) //undefined
var age = 100
}
fn()
console.log(uname)
console.log(n)// 报错,外界不能访问局部变量
练习:点击按钮,运行一个累加计算函数:recursiveAdd(),弹出对话框,接收两个整型输入,弹出他们的累加和。
调用函数:var result = 函数名(实参列表)
函数难点:边界?
分析:输入+运算+输出
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script>
function recursiveAdd(start,end){
var sum = 0
for(i=start;i<=end;i++){
sum += i
}
return sum
}
function doRecursiveAdd(){
// 输入
var num1 = Number(prompt("请输入开始数:"))
var num2 = Number(prompt("请输入结束数:"))
// 计算
var res = recursiveAdd(num1,num2)
document.getElementById("content").value = res
}
</script>
</head>
<body>
<button onclick="doRecursiveAdd()">点击</button>
<input type="text" id="content">
</body>
</html>
- 匿名函数
定义:没有名称的函数
提示:函数的本质是对象,函数名的本质是对象的引用
var age = 20 // age是变量名
function work(){} // work就是变量名
// 匿名形式的函数
var work = function(){} // work就是变量名
work()
var f1 = work
f1()
“有名函数”的致命问题:
JS中所有的全局变量 / 函数都会自动成为window对象的成员,可能出现“覆盖window原有成员”或者“不同开发者创建的同名函数互相覆盖”这样的问题——称为“window对象的污染”
解决方法:匿名函数
匿名函数的两种用法:
(1)匿名自调函数:
(function(形参){})(实参)
(function(num1,num2){
return num1+num2
})(1000,2000)
练习:创建一个匿名自调函数,计算1到100的累加和
(function(num1,num2){
var sum = 0
for(var i=num1;i<=num2;i++){
sum += i
}
console.log(sum)
})(1,100)
(2)匿名回调(callback)函数
在指定的事件(单击 / 时间到了)发生时由JS解释器自动调用的函数
eg.时间到了
//JS中的定时器函数:每隔指定的时间,就由JS解释器调用指定函数:参数1是要指定的任务;参数2是时间间隔(单位是ms)
setInterval(function(){
console.log('hello')
},1000)
eg.单击
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<button id="btn2">hello</button>
<script>
//页面中已经出现了的元素,有id的话,可以直接作为全局变量使用
console.log(btn2)//<button id="btn2">hello</button>
console.log(window.btn2)//<button id="btn2">hello</button>
//为按钮的单击事件指定“回调函数”
btn2.onclick = function(){
console.log('hello')
}
</script>
</body>
</html>
练习:创建一个定时器任务,
页面即将跳转…3
页面即将跳转…2
页面即将跳转…1
console.log(‘页面已跳转’)
<button id="btn3">跳转到百度(5s后)</button>
<script>
btn3.onclick = function(){
var time=5
// 设置一个间隔1s的定时任务(回调函数)
setInterval(function(){
console.log(time)
time-=1
if(time==0){
//让当前页面的地址引用另一个地址
location.href = 'http://www.baidu.com'
}
},1000)
}
</script>
- JS中的对象
对象:是一组数据(属性)和数据操作(方法)的集合
Object = Field + Method
JS中创建对象有很多种方法,最常用的是“对象直接量法”,语法:
var 实例名 = {
成员名:值,
成员名:值,
…
}
例如:
var user2 = {
userName:'dingding',
age:20,
isOnline:true,
login:function(){},
logout:function(){}
};
练习:创建一个对象表示一个矩形,包含成员属性:width、height,以及成员方法:getSize()、getPerimeter()输出该对象的周长和面积
var rect2 = {
// 声明对象中的成员属性
width:200,
height:100,
// 声明对象中的成员方法
getSize:function(){
return this.width*this.height
},
getPerimeter:function(){
return 2*(this.width + this.height)
}
};
console.log(rect2.width) //200
console.log(rect2.height)//100
var s = rect2.getSize()
console.log('矩形的面积为:' + s)
var p = rect2.getPerimeter()
console.log('矩形的周长为:' + p)
练习:创建一个对象表示一个学生,包含成员属性:stuName、chinese、math、english以及成员方法:getTotal()、getAverage(),输出该学生的总分和平均分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h2><span id="sname"></span>的成绩单</h2>
<hr>
<p id="math"></p>
<p id="chinese"></p>
<p id="english"></p>
<hr>
<p id="ttl"></p>
<p id="avg"></p>
<script>
stu2={
name:'叮当',
math:90,
chinese:80,
english:70,
getTotal:function(){
return this.math+this.chinese+this.english
},
getAverage:function(){
return this.getTotal()/3
}
};
// console.log(sname.innerHTML);获取元素的内容
// 把span中的HTML内容修改为数据对象的属性
sname.innerHTML = stu2.name
math.innerHTML = stu2.math
chinese.innerHTML = stu2.chinese
english.innerHTML = stu2.english
ttl.innerHTML = stu2.getTotal()
avg.innerHTML = stu2.getAverage()
</script>
</body>
</html>
-
JS中的对象的分类
(1)ES原生对象(百度搜MDN)
Array、String、Math、Date…总共十几个
(2)宿主对象(由浏览器提供的对象)
window、document、location…等数百个
(3)用户自定义对象
var stu={ math:80,… } -
ES原生对象——Array
数组:是一种特殊的对象,其中可以保存多个数据
1)创建一个新的数组:
var 数组变量名 = []; //长度为0的数组
var 数组变量名 = [值,值,值…];
var 数组变量名 = new Array(); //长度为0的数组
var 数组变量名 = new Array(100); //长度为100的数组,内容均为undefined
var 数组变量名 = new Array(值,值,值…);
2)获取数组的长度:数组变量名.length
3)修改数组中的某个数据:数组变量名[下标] = 新值;
4)读取数组中的某个数据:console.log(数组变量名[下标]);
5)在数组尾部添加一个新的数据:数组变量名[数组变量名.length] = 新值;
练习:创建一个数组,保存五个学生的高考成绩,试着在HTML页面中依次输出每个成绩
<ul id="ulScore"></ul>
<script>
var scoreArray=[500,600,100,200,300]
//把数组数据显示到页面中的列表中
var html=''
for(var i=0;i<scoreArray.length;i++){
html+='<li>' + scoreArray[i] + '</li>'
}
ulScore.innerHTML = html
</script>
6)遍历数组中的每个元素
for(var i=0;i<数组.length;i++){
console.log( 数组[i] )
}
数组变量名.forEach( function(val, index){} )
//使用ES6提供的新方法遍历数组
scoreList.forEach(function(value,index){
console.log('处理数组中的一个元素');
console.log(value);//打印所有值
consol.log(index);//打印所有值对应的下标
})
7)在数组末尾添加 / 删除元素——栈式操作
数组.push(新元素);//入栈,在数组尾部添加新元素
var 删除的元素 = 数组.pop();//出栈,在数组尾部删除元素
8)在数组头部添加 / 删除元素
数组.unshift(新元素);//在数组头部添加新元素
var 删除的元素 = 数组.shift();//在数组头部删除元素
9)拼接数组中的每个元素
var arr = [1,1,0,0]
var result = arr.join('-'); // '1-1-0-0'
var result = arr.join(''); // '1100'
10)删除 / 替换数组中部元素
arr.splice(index,count)
arr.splice(index,count,replacement)
11)数组倒序保存
arr.reverse()
12)指定元素第一次 / 最后一次出现的下标
arr.indexOf(e)
arr.lastIndexOf(e)
13)数组元素的排序
- 简单数组排序:
var arr = [600,400,500,1000,700]
// arr.sort() //比较每个元素的Unicode码
arr.sort(function(e1,e2){
// 返回负数,认为e1排在e2前
// 返回正数,认为e2排在e1前
// 返回零,认为e1等于e2
/*if(e1<e2){ //从小到大排序(更换+-1位置可变为从大到小排序)
return -1
}else if(e1>e2){
return 1
}else{
return 0
}*/
return e1-e2 //从小到大排序 e2-e1(从大到小排序)
})
- 复杂数组排序
var list = [
{uid:10,price:50,count:20},
{uid:20,price:60,count:10},
{uid:15,price:90,count:1},
{uid:12,price:10,count:8}
];
// 按照uid从小到大排序
list.sort(function(e1,e2){
return e1.uid-e2.uid
})
练习:
创建一个数组表示5个商品的价格;
将每个商品的价格调低10%;
输出每个商品的价格;
输出所有商品价格中最贵的价格;
输出第一个价格为90元的商品在数组的下标,若不存在则返回-1;
var priceList = [60,70,80,90,100]
// 将商品价格调低10%
for(var i=0;i<priceList.length;i++){
priceList[i]*=0.9
}
/*priceList.forEach(function(p){
p*=0.9; //此处不会影响到原始数组
})*/
// 输出每个商品的价格
for(var i=0;i<priceList.length;i++){
console.log(priceList[i])
}
priceList.forEach(function(p){
console.log(p);
})
// 创建函数,返回数组中所有元素中的最大值
function getMax(arr){
// 先假设第0个是最大值
var max = arr[0]
// 遍历后续的每个元素,看看哪个比max大
for(var i=1;j<arr.length;i++){
max = arr[i]>max ? arr[i] : max
}
// 返回遍历后得到的最大值
return max
}
var m = getMax(priceList)
console.log('所有商品价格中的最大值为:' + m)
// 创建函数,返回数组中第一次出现指定元素的下标;若从未出现,则返回-1
function indexOf(arr,e){
var index = -1 // 目标元素在数组中的下标
for(var i=0;i<arr.length;i++){
if(arr[i]===e){
index = i
break
}
} // 提示:此处使用forEach不方便
return index
}
var i= indexOf(priceList,90)
console.log('目标元素第一次出现的下标:' + i)
补充:用户信息常用表示方法:
1)数组的数组——二维数组
[
[1,'dingding',‘男’,'1990-1-1',true],
[1,'dingding',‘男’,'1990-1-1',true],
[1,'dingding',‘男’,'1990-1-1',true]
]
2)对象的数组
[
{uid:10,uname:'dingding',sex:'男',birthday:'1990-1-1',isOnline:true},
{uid:10,uname:'dingding',sex:'男',birthday:'1990-1-1',isOnline:true},
{uid:10,uname:'dingding',sex:'男',birthday:'1990-1-1',isOnline:true}
]
练习:二进制转换器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>二进制转换器</title>
</head>
<body>
<h2>二进制转换器</h2>
<input type="text" id="inputNum">
<button id="btn">转换成二进制</button>
<p id="pResult">转换结果...</p>
<script>
btn.onclick=function(){
// 获取输入框中的用户输入
var num = Number(inputNum.value)
// 把一个数字转换成二进制形式的字符串
var arr = []
while(num!=0){
arr.unshift(num%2)
num = parseInt(num/2)
}
var result = arr.join('')
pResult.innerHTML = result
}
</script>
</body>
</html>
- ES原生对象 —— Math
Math对象无需 / 不能实例化,其中的成员可以通过类名直接调用
(1)Math.PI
(2)Math.sin(Math.PI / 6)
(3)Math.floor() 向上取整 / celi() 向下取整 / round() 四舍五入
(4)Math.random() 产生一个伪随机数(0<=n<1)
总结:产生min~max之间的随机数,公式:Math.random()*(max-min) + min
// 产生一个伪随机数(0~100)
var n = Math.random()*100
// 产生一个伪随机整数(0~100)
var n = parseInt(Math.random()*100)
// 产生一个伪随机四位整数(1000~10000)
var n = 1000 + parseInt(Math.random()*9000)
// 公式:min~max间的随机整数
// Math.random()*(max-min) + min
- ES原生对象 —— String
String表示一个字符串,
注意:JS中所有字符串都是“不可变的”;所有的改变字符串内容的函数都无法真正的改变原字符串内容,而是返回一个新的字符串
var uname = 'ding'
uname = 'ya' // 原先的‘ding’字符串内容没变
(1)获取字符串中字符的个数
- s.length
var s = '马力2a'
console.log(s.length) //4
(2)返回字符串的大小写形式
- var result = s.toUpperCase()
- var result = s.toLowerCase()
var s = 'this IS mY wINdow';
//将字符串转换为大写形式
var s2 = s.toUpperCase()
console,log(s) //'this IS mY wINdow'
console,log(s2) //'THIS IS MY WINDOW'
(3)获取字符串中的第i个字符
- var c = s.charAt(i)
练习:生成一个四位的随机验证码,其中每个字符可能是任意的字母或数字
var pool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
pool += pool.toLowerCase()
pool += '1234567890'
var n1=parsetInt(Math.random()*pool.length)
var c1 = pool.charAt(n1)
var n2=parsetInt(Math.random()*pool.length)
var c2 = pool.charAt(n2)
var n3=parsetInt(Math.random()*pool.length)
var c3 = pool.charAt(n3)
var n4=parsetInt(Math.random()*pool.length)
var c4 = pool.charAt(n4)
var code = c1+c2+c3+c4
(4)获取字符串中的第i个字符对应的Unicode码
- var code = s.charCodeAt(i)
var s = 'azAZ09一二三'
var code = s.charCodeAt(0)
console.log(code) //97
var code = s.charCodeAt(1)
console.log(code) //122
var code = s.charCodeAt(2)
console.log(code) //65
var code = s.charCodeAt(3)
console.log(code) //90
var code = s.charCodeAt(4)
console.log(code) //48
var code = s.charCodeAt(5)
console.log(code) //57
var code = s.charCodeAt(6)
console.log(code) //19968
var code = s.charCodeAt(7)
console.log(code) //20108
var code = s.charCodeAt(8)
console.log(code) //19977
Unicode码表中:
数字的范围:48~57
字母的范围:65 ~ 90(大写)/ 97 ~ 122(小写)
中文的范围:19968 ~ 40869
(5)获取指定字符在原字符串中第一次 / 最后一次 出现的下标
- 第一次出现:var i = s.indexOf©
- 最后一次出现:var i = s.lastIndexOf©
var s = 'abcdefcdab'
console.log(s.indexOf('c')) //2
console.log(s.lastIndexOf('c')) //6
console.log(s.indexOf('x')) //-1
console.log(s.indexOf('cd')) //2
练习:输入框中用户输入了一个字符串,判定其中是否有且只有一个@符号
btn.onclick = function(){
//获取用户的输入
var input = inputData.value;
//开始判定是否“有且只有一个@”
var i1 = input.indexOf('@'); //第一次出现@的下标
var i2 = input.lastIndexOf('@'); //最后一次出现@的下标
if(i1==i2 && i1!=-1){
alert('有且只有一个@')
}else{
alert('不符合要求的输入')
]
}
(6)返回字符串中的一个子串
- var str = s.substring(start, end)
注意:包括start,不包括end
示例:
var s = 'abcdefghijk'
console.log(s.substring(3,6)) //def
console.log(s.substring(3)) //defghijk
console.log(s.substring(-3)) //ijk
练习:在输入框中用户输入了一个合法的邮箱地址输出该邮箱中的“用户名”部分,以及“域名”部分。
// 输出邮箱中的“用户名”部分,以及“域名”部分
btn.onclick = function(){
//获取用户的输入
var email = inputEmail.value;
//获取邮箱中不同部分
var i = email.indexOf('@'); //@的下标
// 获取用户名的部分:0~i
var uname = email.substring(0, i);
// 获取域名的部分:i+1~结尾
var hostname = email.substring(i+1);
pResult.innerHTML = '用户名:'+uname+'<br>域名:'+hostname
}
(7)拆分字符串(该方法与arr.join()互为反操作)
- s.split(拆分符)
例如:
var s = '丁丁#当当#豆豆#丫丫'
var arr = s.split('#') // ['丁丁','当当','豆豆','丫丫']
(8)替换字符串中的内容
- var str = s.replace(旧内容,新内容)
- var str = s.replace(正则表达式,新内容)
var s = '共产党诞生于上个世纪,共产党引导中国走向解放,共产党是我们的领路人'
// 替换字符串中的已有内容
// var str = s.replace('共产党','***')
// console.log(s)
// console.log(str) //只有第一个被替换了
// 替换字符串中的已有内容——使用正则表达式
var regexp = /共产党/gi // g:全局匹配,否则只能匹配一个,后续的会被忽略 i:忽视大小写
var str = s.replace(regexp, '***')
console.log(s)
console.log(str) //只有第一个被替换了
宿主对象 —— BOM对象
Browser Object Model:浏览器对象模型,即由浏览器提供的默认对象,专用于与浏览器交互。
BOM对象总共有七个(无需创建,直接使用):
(1)window:指代当前浏览器窗口对象
(2)document:指代当前浏览器渲染的HTML文档
(3)screen:指代当前屏幕对象
(4)location:指代当前浏览器渲染的页面地址
(5)history:指代当前浏览器的浏览历史记录
(6)navigator:指代当前浏览器对象
(7)event:指代当前的浏览器事件
window对象的常用API:
(1)三种弹出对话框
- 警告框:window.alert()
- 输入提示框:window.prompt()
- 确认框:window.confirm()
var choice = confirm('此操作不可恢复,您确认吗?')
if(choice){ // true,用户点击“确定”
console.log('开始删除')
}else{ //false,用户点击“取消”
console.log('删除操作取消')
}
(2)打开 / 关闭窗口
- window.close()
- window.open(url)
btClose.onclick = function(){
close() //等价于window.close()
}
btOpen.onclick = function(){
// 在新的窗口中打开
open('http://www.baidu.com')
// 在当前窗口中打开——页面跳转
location.href = 'http://www.baidu.com'
}
(3)两种定时器
- 周期性定时器:
- 启动:var timer = window.setInterval(cb, time)
- 停止:window.clearInterval(timer)
- 一次性定时器:
- 启动:var timer = window.setTimeout(cb, time)
- 取消:window.clearTimeout(timer)
//周期性定时器——每隔1s打印hello
var i = 0
setInterval(function(){
console.log('hello'+i)
i++
},1000)
//一次性定时器——1s后打印hello
setTimeout(function(){
console.log('hello')
},1000)
练习:做一个页面小时钟
<body>
<span id="hour">00</span>
:
<span id="minute">00</span>
:
<span id="second">00</span>
<hr>
<button id="btnStop">时间停止</button>
<script>
var timer = setInterval(function () {
//JS中获取当前系统时间 - ES原生对象Date
var now = new Date()
//获取系统时间对象中的小时部分
var h = now.getHours()
//获取系统时间对象中的分钟部分
var m = now.getMinutes()
//获取系统时间对象中的秒钟部分
var s = now.getSeconds()
hour.innerHTML = h
minute.innerHTML = m
second.innerHTML = s
}, 1000)
btnStop.onclick = function(){
// 取消周期性定时器
clearInterval(timer)
}
</script>
</body>
window对象的属性:
1)history:提供操作当前窗口历史记录的方法
属性:length 保存当前窗口访问过的历史记录数量
方法:
back() 返回上一个历史记录
forward() 前进下一个历史记录
go(n) 正值表示前进n条历史记录,负值表示后退n条历史记录
使用:
- 超链接修改地址栏中URL,会增加历史记录
- 前进和后退按钮不会增加历史记录,只是指针的移动
2)location:保存当前窗口的地址栏信息
属性:href 可读可写,读取或设置当前窗口的URL
方法:reload(false) 重载刷新页面,参数默认是false表示优先从缓存中加载,设置true表示强制从服务器根目录中请求
3)navigator / screen:当前浏览器对象信息 / 当前屏幕对象信息(了解)
4)document(见DOM)
DOM节点操作
- 文档对象模型,提供操作HTML文档的方法。核心对象为document对象
- 节点对象。JS对HTML文档中的标签,文本,属性甚至注释都封装成对象,提供操作的方法。称为节点对象。分为:
- 元素节点(标签)
- 文本节点(文本内容)
- 属性节点(标签属性)
- 获取元素节点
1)根据标签名获取节点列表
-
document.getElementsByTagName(“h1”)
2)根据类名(class属性值)获取节点列表
-
document.getElementsByClassName(“c1”)
3)根据name属性值获取节点列表
-
document.getElementsByName(“n1”)
4)根据id属性值获取元素
-
document.getElementById(“id1”)
-
操作元素内容
元素节点提供三个属性,操作标签内容或值
1)innerHTML:读取或设置元素节点的内容,可以识别标签语法
2)innerText:读取或设置元素节点的内容,不能识别标签语法
3)value:读取或设置表单控件的值 -
操作元素属性
1)标签属性都是元素节点对象的属性,使用点语法直接访问。注意操作类名时,需要将class更名为className。
h1.id = 'd1'
// h1.name = 'info' //不好使
h1.className = 'c1'
h1.className = 'c1 c2'
//移除属性
h1.id = ''
h1.className = null
2)元素对象提供相关的方法操作标签属性
- 设置属性:setAttribute(“attrName”, “value”)
- 获得属性:getAttribute(“attrName”)
- 移除属性:removeAttribute(“attrName”)
h1.setAttribute("id","box") //<h1 id="box"></h1>
console.log(h1.getAttribute("id")) //box
h1.setAttribute("class","c3 c5") //<h1 id="box" class="c3 c5"></h1>
h1.removeAttribute("id") //<h1 class="c3 c5"></h1>
- 操作元素样式
1)通过操作id和class属性,对应选择器的样式(不常用)
2)操作行内样式,操作style属性。访问style属性获取样式表对象,包含所有css的属性,可以使用点语法操作。所有出现连接符的css属性一律更改为驼峰标识。
p.style = "width:200px;height:200px;background:pink"
p.style.width = "300px"
p.style.fontSize = "32px"
- 节点的层次属性
1)获取父元素
-
parentNode
2)获取子元素列表
-
childNodes:获取所有子节点,包含文本节点
-
children:获取所有的子元素,不包含文本节点
3)获取下一个兄弟节点
-
nextSibling
-
nextElementSibling:获取下一个元素兄弟节点
4)获取上一个兄弟节点
-
previousSibling
-
previousElementSibling:获取前一个元素兄弟节点
5)获取属性节点的列表(不常用)
-
attributes
- 节点的创建,添加和移除
1)创建节点
-
var h1 = document.createElement(“h1”);
2)节点添加:节点的添加和移除只能由父元素操作
-
添加在父元素内的末尾
parentNode.appendChild(elem);
//body作为document对象的属性存在,可以直接访问
//动态创建的节点与页面元素一一对应,需要显示几个页面元素,就需要创建几个元素节点
document.body.appendChild(h1)
- 指定位置添加
parentNode.insertBefore(new, old); 在已有节点之前插入新节点
//动态创建h2标题,内容不限,插入到h1之前显示
var h2 = document.createElement("h2")
var text = document.createTextNode("哈哈")
// 文本节点作为标签内容,需要作为子节点追加到元素节点中
h2.appendChild(text)
//添加显示
document.body.insertBefore(h2,h1)
3)移除节点
- parentNode.removeChild(elem)
DOM事件处理
-
介绍
事件:指的是用户的行为或元素的状态。
事件处理:元素监听事件,并在事件发生后自动执行相关的操作
例:<button onclick="alert()"></button>
-
事件分类
1)鼠标事件
onclick 单击
ondbclick 双击
onmouseover 鼠标移入
onmouseout 鼠标移出
onmousemove 鼠标移动
…
2)键盘事件(了解)
onkeydown 键盘按键被按下
onkeyup 按键抬起
onkeypress 字符按键被按下
3)等待文档,窗口或元素加载完毕
window.onload = function(){}
4)表单事件
onfocus(表单控件获取到焦点)
onblur(表单控件失去焦点)
onchange(表单控件的值或状态是否发生变化)
oninput(实时监听输入)
onsubmit(监听表单数据是否可以发送)
<form action="/login" method="get" enctype="">
<p>
用户姓名: <!--autocomplete="off" 默认值为on开启自动补全,可以设置off,关闭-->
<input type="text" name="uname" placeholder="提示文本" maxlength="10" autocomplete="off">
</p>
<p>
用户兴趣:
<input type="checkbox" name="hobby" value="study" checked>学习
</p>
<input type="submit" value="提交">
</form>
window.onload = function(){
// 获取元素
var form = $("form")
var uname = $("input")
var hobby = $("input",1)
//输入框相关的事件
uname.onfocus = function(){
console.log("输入框获取焦点")
}
uname.onblur = function(){
console.log("失去焦点",uname.value)
}
uname.oninput = function(){
//实时监听输入
console.log(uname.value)
}
uname.onchange = function(){
// 监听输入框前后两次输入内容是否发生变化,只有内容不一致并且失去焦点时触发
console.log("onchange:", uname.value)
}
//按钮选中状态发生变化
hobby.onchange = function(){
console.log(hobby.checked)
}
// onsubmit:由form监听,在点击提交按钮时自动触发,允许在事件处理函数中返回一个布尔值,true表示允许发送,false表示阻止提交
form.onsubmit = function(){
// 用户名为空时不允许提交
if(uname.value.length == 0){
return false
}else{
return true
}
}
}
- 事件绑定方式
1)内联绑定:将事件名称作为标签属性直接绑定
2)动态绑定:为元素节点绑定事件
例如:btn.onclick = function(){};
轮播图的几种实现方式:
1)控制元素隐藏与显示
2)动态修改图片路径
- 以1)为例,2)类似
var imgs = banner.children
//保存图片下标,初始为0
var index = 0
var timer = setInterval(autoPlay,1500)
function autoPlay(){
//当前图片隐藏
imgs[index].style.display = "none"
// 更新下标
index++
if(index == imgs.length){
index = 0
}
// 元素显示
imgs[index].style.display = "block"
};
//鼠标移入和移出
banner.onmouseover = function(){
// 停止定时器
clearInterval(timer)
}
banner.onmouseout = function(){
//重启定时器
timer = setInterval(autoPlay,1500)
}
- this:指代函数的调用对象或者事件的触发对象
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<style>
ul, ol{
list-style: none;
margin: 0;
padding: 0;
background: red;
width: 100px;
text-align: center
}
ol{
background: yellow
}
ul li:hover li{
display: block
}
ol li{
display: none
}
ol li:hover{
background: green;
cursor: pointer;
}
</style>
<body>
<ul>
<li>
<span id="demo_id">北京</span>
<ol>
<li>北京</li>
<li>上海</li>
<li>广州</li>
<li>深圳</li>
</ol>
</li>
</ul>
<script>
// 等待文档加载完毕后获取元素
var li = document.getElementsByTagName('ol')[0].children
for(var i=0;i<li.length;i++){
console.log(i)
li[i].onclick = function(){
// 传值
// this指代事件的触发对象
demo_id.innerHTML = this.innerHTML
/*
点击事件触发时,循环已经执行完毕,i保存的是最终值(4),因此下面这行执行后取不到元素
demo_id.innerHTML = li[i].innerHTML
*/
}
}
</script>
</body>
</html>
效果图:
- 事件对象:事件对象跟随事件触发自动创建,保存与当前事件相关的信息。自动传入事件处理函数中,只需要接收。
eg. 鼠标事件对象
btn.onclick = function(event){
console.log(event)
// 获取鼠标在元素坐标系中的位置(相对元素自身)
console.log(e.offsetX,e.offsetY)
// 获取鼠标在电脑屏幕坐标系中的位置(相对电脑屏幕)
console.log(e.screenX,e.screenY)
// 获取鼠标在浏览器屏幕坐标系中的位置(相对浏览器内有效屏幕)
console.log(e.clientX,e.clientY)
}
eg. 键盘事件对象
onkeydown = function(e){ //keyCode和which 不区分 大小写
/*
key:获取按键名称(字符)
keyCode:获取按键编码,在keydown事件中,字母键一律返回大写字母的ASCII码,keypress事件中区分大小写字母的编码。
which:获取按键编码
*/
console.log("keydown:",e.key,e.keyCode,e.which)
}
onkeypress = function(e){ //keyCode和which 区分 大小写
console.log("keypress:",e.key,e.keyCode,e.which)
}