Web前端基础回顾(JavaScript)

介绍

  1. 简称JS,是一种浏览器解释型语言,嵌入到网页中由浏览器负责解析和执行。可以实现网页动态效果,用户交互,实现网络请求或游戏制作。
  2. 组成
    1)核心语法(ECMAScript 5)
    2)BOM(浏览器对象模型),提供操作浏览器窗口的方法
    3)DOM(文档对象模型),提供操作HTML文档的方法

JS使用

  1. 元素绑定事件
    事件:用户的行为或元素的状态
    事件处理:元素监听到事件发生后作出的响应
    事件名称:onclick(单击事件) ondblclick(双击事件)
    语法:将事件名称以标签属性的形式绑定到元素上。 eg. <h1 onclick="JS 代码"></h1>
  2. 内嵌方式
    使用<script type="text/javascript"></script>书写JS语句。标签可以书写在任意位置,书写任意多次。浏览器在解析到script标签时会直接执行内部的脚本代码。
  3. 外联方式
    创建外部的JS文件(.js),HTML文件中使用<script src=""></script>引入。注意<script>既可以实现内嵌,也可以实现外链,但是二选一。
  4. 语法规范
    1)JS代码区分大小写
    2)JS语句可以使用;作为结束的标志,也可以省略。
    3)JS中注释
    // 单行注释
    /* 多行注释 */
  5. 输入语句
    console.log() 控制台输出
    alert("") 网页警告框
    prompt("") 带输入框的弹框
    document.write("") 在网页中输出,动态向body标签中写入内容,可以识别标签语法
    使用:
    1)代码的书写位置即为添加位置
    2)使用元素绑定事件的方式去动态添加,会造成页面重写。(事件发生之前,body可能就加载完毕了)

JS基础语法

  1. 变量与常量

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. 数据类型

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. 数据类型转换
    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. 运算符
    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
  • 相等与全等
    相等:包含自动类型转换,只要值相等,就成立
    全等:严格比较,不会转换类型。要求类型一致并且值相等才成立

运算符

  1. 赋值运算符
  2. 算术运算符
  3. 复合运算符
  4. 自增/自减
  5. 关系运算符
"hello" > "abc" // "h">"a" --> true
"10" > 2 // 10 > 2 --> true
"10" > "2" // "1">"2" --> false
"abc" > 10 //NaN > 10 --> false
  1. 逻辑运算:逻辑运算用于表示表达式之间的关系,结果永远为布尔值
    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. 三目运算符
    语法:表达式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. 分类:
    1)顺序结构,从上到下依次执行
    2)选择结构,根据条件是否成立,选择执行某一段代码
    3)循环结构,根据条件是否成立,选择是否重复执行某段代码
  3. 选择结构
    1)if语句
  • 基本结构
if(条件表达式){
	条件成立时执行
}
  • if-else语句
if(条件){
	条件成立时执行
}else{
	条件不成立时执行
}
  • 多重分支if-else if
if(条件1){
	条件1成立时执行
}else if(条件2){
	条件2成立时执行
}
...
else{
	条件n不成立时执行
}

2)switch语句
用于值的全等匹配
语法:

switch(变量){
	case1:
		匹配全等之后执行的代码段
		break;//结束匹配
	case2:
		匹配全等之后执行的代码段
		break;//结束匹配
	...
	default:
		所有case都不匹配时执行的默认操作
		break;
}

特殊:
1)break关键字可以省略,一旦省略,会从当前匹配到的case开始向后执行所有的代码语句,直至碰到break关键字结束匹配或执行至结束
2)多个case共用代码段

case1case2...
	//任一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. 循环结构
    控制代码的重复执行
    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. 函数用于保存一段待执行的代码,或者封装某个功能。
  2. 语法:
    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. 作用域
    全局作用域和函数作用域
    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>
  1. 匿名函数
    定义:没有名称的函数
    提示:函数的本质是对象,函数名的本质是对象的引用
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>
  1. 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>
  1. JS中的对象的分类
    (1)ES原生对象(百度搜MDN)
    Array、String、Math、Date…总共十几个
    (2)宿主对象(由浏览器提供的对象)
    window、document、location…等数百个
    (3)用户自定义对象
    var stu={ math:80,… }

  2. 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>
  1. 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
  1. 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节点操作

  1. 文档对象模型,提供操作HTML文档的方法。核心对象为document对象
  2. 节点对象。JS对HTML文档中的标签,文本,属性甚至注释都封装成对象,提供操作的方法。称为节点对象。分为:
  • 元素节点(标签)
  • 文本节点(文本内容)
  • 属性节点(标签属性)
  1. 获取元素节点
    1)根据标签名获取节点列表
  • document.getElementsByTagName(“h1”)

    2)根据类名(class属性值)获取节点列表

  • document.getElementsByClassName(“c1”)

    3)根据name属性值获取节点列表

  • document.getElementsByName(“n1”)

    4)根据id属性值获取元素

  • document.getElementById(“id1”)

  1. 操作元素内容
    元素节点提供三个属性,操作标签内容或值
    1)innerHTML:读取或设置元素节点的内容,可以识别标签语法
    2)innerText:读取或设置元素节点的内容,不能识别标签语法
    3)value:读取或设置表单控件的值

  2. 操作元素属性

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. 操作元素样式
    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. 节点的层次属性
    1)获取父元素
  • parentNode

    2)获取子元素列表

  • childNodes:获取所有子节点,包含文本节点

  • children:获取所有的子元素,不包含文本节点

    3)获取下一个兄弟节点

  • nextSibling

  • nextElementSibling:获取下一个元素兄弟节点

    4)获取上一个兄弟节点

  • previousSibling

  • previousElementSibling:获取前一个元素兄弟节点

    5)获取属性节点的列表(不常用)

  • attributes

  1. 节点的创建,添加和移除
    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事件处理

  1. 介绍
    事件:指的是用户的行为或元素的状态。
    事件处理:元素监听事件,并在事件发生后自动执行相关的操作
    例:<button onclick="alert()"></button>

  2. 事件分类
    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. 事件绑定方式
    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)
}
  1. 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>

效果图:
在这里插入图片描述

  1. 事件对象:事件对象跟随事件触发自动创建,保存与当前事件相关的信息。自动传入事件处理函数中,只需要接收。

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)
}

猜你喜欢

转载自blog.csdn.net/xiecheng1995/article/details/105855572