web前端 - 系统化知识入门系列一: Es5知识巩固

294 阅读20分钟

一 复习:

注意:该阶段属于语法规范,属于ECMAScript基础,还未涉及 Web API操作。

1:JS基础知识:

浏览器执行JS过程

浏览器由2部分组成:
渲染引擎: 用来解析 HTML 和 CSS, 俗称内核,比如chrome浏览器的blink,老版本的webkit
JS引擎: 也称为 JS 解释器, 用来读取网页中的JS代码,对其处理后运行, 比如chrome浏览器的v8引擎
注意:浏览器本身是不会执行JS代码的,是通过内置的解释器引擎,来执行JS代码的,JS引擎会逐行解释每一句源码(转换为机器语言),然后交由计算机去执行, 所以JS是脚本语言,会逐行进行解释

JS的组成

ECMAScript: ECMAScript规定了编程语法的基础核心知识,是所有浏览器共同遵守的一套JS语法的工业标准
BOM: 浏览器对象模型,通过BOM操作浏览器窗口,比如弹出框, 控制浏览器跳转,获取分辨率等···

JS变量

var
变量的价值:
因为有些数据需要保存,所有需要变量。变量是一个容器,用来存放数据的,方便我们以后使用里面的数据的。
变量是内存里的一块空间,用来存储数据。我们使用变量的时候,一定要先声明变量,然后赋值。
变量的本质就是去内存中申请空间。
声明变量并赋值,我们称之为变量的初始化。
变量命名必须规范化,见名知意:遵循驼峰命名。
避免使用关键字和保留字去命名,遵循变量名的合法性。

数据类型

数字类型:Number 
非数字:isNaN 判断变量是否为非数字, 返回true或者falseisNaN(变量名)
字符串类型:String   
字符串拼接: 数值相加, 字符相连。
Undefined 声明没有赋值
Null 一个变量声明的时候给null, 表示里面存储的值为空
判断变量类型:typeof 变量名 // 返回变量的类型: number, string, boolean, undefined, object
字面量:通俗来讲:就是字面意思,表示根据字面意思去理解这个变量。
number转换为字符串:number.toString() || String(number) || number + '' 。这3种方式都能将number转换为字符串。
保留整数:parseInt(3.14 | 3.95)// 3   parseInt('120px')// 120 保留整数      
保留小数点:parseFloat(3.14) // 3.14
Number转换:Number('12') // 12   隐式转换 ('133' - '130') // 3
Boolean()转换为布尔类型: 
    false :('') 0 NaN null undefined
    true:('小白')  12 // 有内容就是true

JS操作符

算术运算符: + - * / %取余,注意浮点数不能拿来比较,js有精度问题,会返回false。
表达式: console.log(1+1) // 要做的事情,都能称为表达式。
返回值:var num = 1 + 1 //可以理解就是,把右边的返回值给到左边。
++前置:先自加,后运算(先己后人)
后置++:先原值运算,后自加(先人后己) // 实际开发中一般后置++用的比较多,如:num++  num--。
比较运算符:一个=是赋值, 2个==是比较, 3个===要求的是值和类型必须一致,返回值才是true。
逻辑运算符:
1:逻辑与&&: false && true // false  ,两侧都是true才是true, 只要一侧是false就是false。 
2:逻辑或||:false || true // 两侧都是false才是false,只要一侧为true就是true。
3:取反! : 对布尔值进行取反
短路运算与&&: true && 表达式或者值 //只要左侧为true就hi执行右侧代码,左侧为false就不会执行右侧代码 。
短路运算或||:true || 表达式或者值 //如果左侧为true就会执行左侧,如果左侧为false,就会执行右侧代码。
赋值运算符:+= *= /= -=
运算符优先级:[] ()  ++  --   *  /  %  +  -  <  <=  >  >=  ==  !=  ===  !==  &&  ||  =  +=  -=  *=  /=  %= 

流程控制

流程控制:就是来控制我们代码的按照什么样的顺序结构来执行,大致分为:普通顺序结构, 分支结构, 循环结构。
if语句:if {···} 
双分支if elseif(判断语句) { 表达式 } else { 表达式 }
多分支if else ifif(判断语句) { 表达式 } else if (判断语句2) { 表达式 } else { 最后的表达式 }
三元表达式: 10 > 5 ? '是的' : '不是的' // 前面判断语句返回的是true执行表达式1, 判断语句的返回值是false执行表达式2.
多分支switchswitch(被判断的值) { case 待判断的值1: 表达式 break; case 待判断的值2: 表达式 break; default: 其他 }
switch注意项:switch被判断的值最好是===3个等号,每个case中一定要记得打上break。
多分支语句总结:一般情况下switchif else是可以相互替换的,switch一般判断比较固定的值比较死板,if else比较灵活。
效率上if else在分支比较少的时候,比switch要高些。但当分支语句比较多时,switch执行效率高,而且结构更清晰
ps: '其实程序员更喜欢用if else, 别问为什么,用就对了!'

循环

循环的目的:就是重复执行某部分代码!: for (var i = 1; i <= 99; i++) { console.log('爱老虎油to') }。
三种循环语句: for, while, do while1for循环
循环的执行过程:举栗子:for (var i = 1; i <= 100; i++) { 表达式 }//执行过程:1:i <= 100, 2:i++, 3:表达式,到达了3之后,在2重新跳回1:i<=100;。
从刚开始的执行顺序 1 2 3,后面一直都是 3 1 2 --> 3 1 2,直到i<=100,结束循环为止。(可以打断点调试看执行过程!)

案例:使用循环求1-100之间,找出能被3整除的数字,并计算能被3整除的数字的求和。(所有能被3整除数字的和)
var res = 0;
for (var i = 0; i <= 100; i++) {
  if (i % 3 == 0) {// 找出能被3整除的数
    res += i;// 并计算这些数的总和
  }
}
conosle.log(res)

双重for循环:外层循环一次,内层就要循环内层的所有次数(相当于时钟,(内层)秒钟转60一整圈,(外层)分钟却只走一步)
for (var i = 1; i <= 3; i++) {
  for(var j = 1; j <= 3; j++) {  // 内层我们一般习惯用 变量 j来声明变量
  }
}
用双重循环打印九九乘法表:
      var str = '' //用来接收并在控制台打印结果
      for (var i = 1; i <= 9; i++) {
        for (var j = 1; j <= i; j++) { //执行结果: 1, 1 2, 1 2 3, 1 2 3 4, ··· 1~9 
          str += j + 'x' + i + '=' + i * j + '\t' // 拼接字符串,/t制表符
        }
        str += '\n' // 换行符
      }
      console.log(str)
      
for循环总结:
for循环因为里面有计数器,可以重复执行多次相同的代码,双重for循环,外层循环一次,内层次数全部循环完。
一些核心的算法一时半会想不到,但是要学会分析总结它的执行过程。

2while循环: 
var score = prompt('考了多少分')
while (score !== '100') {
  score = prompt('到底考了多少分?')
}
console.log('100分,真男人!')

3do while循环:
var sum = 0;
var i = 1;   //计数器
do {
	sum += i;
    i++   //自增
} while (i <= 100)  //循环条件判断
console.log(sum)// 求 1-100之间的和

循环总结:3个循环很多情况下是可以互相替代的,如果是用来计算跟数字相关的,三者基本相同,但是码农一般喜欢用forwhiledo while执行顺序不一样, while先判断后执行, do while先执行一次,后再判断。

continue跳出 + break打断

continue跳出本次, 继续下一次
for (var i = 1; i <= 3; i++) {
	if(i == 2) {
	continue // 假设第二个是菜包我们不吃,直接跳到第3个
  }
  console.log('这是第'+i+'个肉包子')
}

break打断
for (var i = 1; i <= 3; i++) {
  if (i == 2) {
    break// 假设第二个不是肉包子,就不吃了
  }
  console.log('这是第'+i'个包子')
}

数组

数组Array: 就是一组数据的集合,存储在在单个变量的优雅方式

创建数组的2种方式:
var arr = new Array()// new Array()
var arr  =[] // 字面量方式
访问数组元素
var arr = [1, '迪丽热巴', true]
console.log(arr[1])//根据数组下标 迪丽热巴
遍历数组
var arr = ['red', 'green', 'blue']
for (var i = 0; i < 3; i++) {  // i必须是从0开始,因为数组的下标是从0开始的, 必须小于3,那就是0 1 2,刚好把数组遍历完。 
  console.log(arr[i])
}
数组长度 Array.length
var arr = [1, 2, 3]
for (var i = 0; i < arr.length; i++) {
  console.log(arr[i])
}

数组求和:以及求平均值
      var arr = [1, 2, 3]
      var sum = 0
      for (var i = 0; i < arr.length; i++) {
        sum += arr[i]
      }
      var average = sum / arr.length
      console.log(sum, average)  //数组求和 = 6, 平均值 2.

求数组中最大值:
var arr = [2, 4, 8, 6, 33, 4]
var max = arr[0]
for (var i = 0; i < arr.length; i++) {
 	if (arr[i] > max) {
      max = arr[i]
    }
}
console.log(max)

数组转换为字符串

var arr  = ['yes', 'hello', 'test'];
var str = ''
for (var i = 0; i < arr.length; i++) {
 str += arr[i] + '/'
}
console.log(str)// yes/hello/test/

新增数组元素

var arr [6, 9, 7]
arr[1] = 99 // 99
arr[3] = 88 // 88

往数组里存放 10个值
var arr = [];
for (var i = 0; i < 10; i++) {
 arr[i] = i;
}
console.log(arr)// (10[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
将大于10的放进一个新的数组
方法1:(不推荐)
var arr = [10, 20, 3, 6, 9, 12]
var newArr = []
var j = 0 //1 新数组的索引
for (var i = 0; i < arr.length; i++) {
	if (arr[i] > 10) {
		newArr[j] = arr[i] // 3 拿到了大于10的,并且每一个都有自己索引
		j++ // 2 新数组的索引递增
	}
}
console.log(newArr)//(2[20, 12]

方法二
var arr = [10, 20, 3, 6, 9, 12]
var newArr = []
for (var i = 0; i < arr.length; i++) {
	if (arr[i] > 10) {
		newArr[newArr.length] = arr[i]//newArr.length这种方式更简洁,相当于数组的索引。
	}
}
console.log(newArr) //(2[20, 12]
数组去重: 将数组中的0排除,剩下的形成一个新的数组
var arr = [0, 1, 2, 3, 0, 4, 5, 6, 0, 8, 9, 0]
var newArr = []
for (var i = 0; i < arr.length; i++) {
	if (arr[i] !== 0) { //核心算法,就是把不是0的数字,装进一个新的数组
		newArr[newArr.length] = arr[i]
	}
}
console.log(newArr)//(8[1, 2, 3, 4, 5, 6, 8, 9]

翻转数组:

翻转数组:把数组中的每项倒过来,核心算法,就是 i = arr.length -1, i >=0; i--.翻译过来就是,i=2 每次i--,直到减到 i>=0时循环停止
var arr = ['A', 'B', 'C']
var newArr = []
for (var i = arr.length - 1; i >= 0; i--) { // 因为数组的索引是从0开始的, 0 1 2,此处必须是i--
	newArr[newArr.length] = arr[i]
}
console.log(newArr) //(3["C", "B", "A"]

冒泡排序:

var arr = [1, 7, 9, 6, 5, 3, 12, 2]
for (var i = 0; i <= arr.length - 1; i++) {
	for (var j = 0; j <= arr.length - i - 1; j++) { // 注意此处的j <= arr.length -i -1;
		if (arr[j] < arr[j + 1]) { // 注意此处的arr[j] < arr[j+1]
			var temp = arr[j]
			arr[j] = arr[j + 1]
			arr[j + 1] = temp // 交换变量
		}
	}
}
console.log(arr) //(8[12, 9, 7, 6, 5, 3, 2, 1]

函数

函数就是封装了一段可以被重复执行调用的代码块,通常封装一个功能,这个功能会返回一个结果,目的就是让大量的代码重复使用
体验函数封装
function getSum(num1, num2) {
	var sum = 0
	for (var i = num1; i <= num2; i++) { // 注意这里是i <= num2
		sum += i
	}
	return sum
}
console.log(getSum(1, 100))
console.log(getSum(10, 100))

函数的含义:

1function 声明函数的关键字, 
2:函数是做某件事情,所以函数名一般是动词。
3:函数是不会自己执行,一般需要调用函数 : 函数名()

函数的参数

函数名里面的一般是形参, 它接收函数调用的时候,传递过来的实参,
function fn(arguments){
  console.log(arguments)//烫头发
}
fn('烫头发')

形参和实参个数不一致的问题
1:如果实参的个数大于形参, 程序正常执行,函数只会拿到自己匹配的实参个数,忽略掉多余的实参。:
2:如果实参的个数小于形参, 则多余剩下的形参,在函数中打印可以看到,这个多余的形参是Undefined未定义

函数的返回值 return
function getSum(a, b){
  return a + b
}
getSum(1, 2)

函数版:求数组中最大值
var arr = [1, 6, 34, 22, 64, 23, 54, 73, 18]
function getMax(arguments) {
	var max = arguments[0]
	for (var i = 1; i < arguments.length - 1; i++) {
		if (arguments[i] > max) { // 注意此处的判断,是arguments[i] > max
			max = arguments[i]
		}
	}
	return max
}
console.log(getMax(arr))//73

如果函数中,return同时导出多个返回值, 默认导出最后一个值。前面的值是被忽略的。
如果一个函数,没有使用return, 那么打印这个调用的函数,这个函数的返回值显示的是undefined

作用域和预解析

函数版冒泡排序
var arr = [1, 7, 9, 3, 4, 6, 7, 8, 2, 0]
function sort(argumnets) {
	for (var i = 0; i <= argumnets.length - 1; i++) {
		for (var j = 0; j < argumnets.length - i - 1; j++) {
			if (argumnets[j] < argumnets[j + 1]) {
				var temp = argumnets[j]
				argumnets[j] = argumnets[j + 1]
				argumnets[j + 1] = temp
			}
		}
	}
	return argumnets
}
console.log(sort(arr)) // (10[9, 8, 7, 7, 6, 4, 3, 2, 1, 0]

函数版翻转数组

var arr = [12, 15, 25, 33, 7, 9]
function reverse(arr1) {
	var newArr = []
    for (var i = arr.length -1; i>= 0; i--) {
      newArr[newArr.length] = arr[i]
    }
    return newArr
}
console.log(reverse(arr))

求闰年: 能被4400取余,不能被100取余
function isRun(year) {
	if ((year % 4 == 0 && year % 100 !== 0) || year % 400 == 0) {
		console.log('是闰年')
	} else {
		console.log('不是闰年')
	}
}
isRun(1999)
isRun(2000)

函数可以调用另一个函数

function sum(a, b) {
	return a + b;
}
function result() {
	var res = sum(1, 7);
    return res
}
console.log(result())//8

函数版: 2月的天数
function isRun(year) {
	var flag = false
	if ((year % 4 == 0 && year % 100 !== 0) || year % 400 === 0) {
		flag = true
	}
	return flag
}

function getDay() {
	if (isRun(2000)) { // 此时isRun的返回值是布尔值,如果是闰年返回值是true,不是闰年返回值是false
		console.log('是闰年2月份只有28天')// true 输出的结果
	} else {
		console.log('不是闰年2月份是29天')// false输出的结果
	}
}
getDay()
函数声明的2种方式:
1:命名函数:function fn()
2:匿名函数(函数表达式): var fun = function(message){} // 注意匿名函数也是可以传参的 fun('hello')
全局变量和局部变量
全局变量:在任何一个地方都可以使用,只有在浏览器关闭的时候销毁,因此比较占内存
局部变量:只在函数内部中使用,当它所在的代码块被执行时,会被初始化,当代码块执行结束后,就会被销毁,因为更节省内存。
注意: js是没有块级作用域的,在块级中定义的变量,在块外是能访问的到的。
作用域链:
var num =10;
function fn1() {
	var num = 20;
    function fn2(){
    	console.log(num) // 20
    }
    fn2()
}
fn1()

作用域查找规则: 当出现同名变量的时候,作用域查找规则,会根据就近原则,使用那个更近的同名变量

预解析:
预解析:我们的js引擎运行js代码,分为两步: 1:预解析, 2:执行代码
1:预解析:把我们的varfunction 提升带作用域的最前面
2:预解析分为变量提升,和函数提升
3:变量提升,就是把所有的变量声明提升到当前作用域最前面, 不提升赋值操作
4:函数提升,就是把所有的函数提升到作用域的最前面。但是不会调用函数
预解析案例:
 // 1:变量提升
console.log(num) //undefined 因为 var num 被提升了,但是赋值不会被提升
var num = 10

// 2:命名函数  // fn1 ,命名函数的调用,写在前面和后面效果是一致的。
fn1()
function fn1() {
	console.log('fn1')
}

//3:匿名函数(函数表达式)
fn()
console.log(fn)
var fn = function fn2() {
  console.log('fn2') // fn is not a function
}
匿名函数的预解析过程分析
// 先把变量提升上来,此时就被调用了一个fn(),此时这里就已经开始报错了,后面的代码注释掉,报错还是一样的fn is not a function。
// 原因很简单,变量声明会提升,但是函数表达式不会提升,所以在函数表达式的前面被莫名其妙的调用了一个不存在的fn()函数,目前它还没有被定义的,只有代码执行到后面才会赋值,但是js执行到这里就出现了报错,js就会中断程序不再向后执行,就把错误信息给抛出来了。
var fn
fn()
fn = function fun() {
	console.log(fn)
}

预解析面试题:

// 案例一:========================================================================
var num = 10;
fun()
function fun(){
	console.log(num);
	var num = 20
}
// 预解析过程
var num
function fun() {
	var num
	console.log(num)
	num = 20
}
num = 10
fun()

// 案例二:========================================================================
var num = 10
function fn() {
	console.log(num) // undefined
	var num = 20
	console.log(num) // 20
}
fn()

// // 预解析过程
var num
function fn(){
	var num
	console.log(num);// undefined
	num = 20
	console.log(num) // 20
}
num = 10;
fn()

// 案例三:========================================================================
var a = 18
f1()
function f1() {
	var b = 9
	console.log(a) // undefined
	console.log(b) //9
	var a = '123'
}
// // 预解析过程
var a
function f1() {
	var b
	var a
	b = 9
	console.log(a)
	console.log(b)
	a = '123'
}
a = 10
f1()

// 案例四:========================================================================
f1()
console.log(c)
console.log(b)
console.log(a)
function f1() {
	var a = (b = c = 9)
	console.log(a)
	console.log(b)
	console.log(c)
}
// 预解析过程
function f1() {
	var a //相当于 var a = 9,它是函数中的局部变量
	a = b = c = 9 // 而b c是没有使用var声明的变量,属于全局变量,所以只有第6个console.log(a)会报错,因为它访问不到函数中的局部变量
	console.log(a)
	console.log(b)
	console.log(c)
}
f1() // 函数的调用会在console.log的前面。
console.log(c)
console.log(b)
console.log(a)

对象

为什么需要对象:因为数组中存储的都是带索引的每一项,它不是属性值类型键值对形式的,而对象是属性值类型键值对形式的,这样表达节后更清晰,内容更强大,对象中可以嵌套方法

利用字面量方式创建对象:

var obj = {
	uanme: 'zs',
	age: 18,
	sayHi: function (hi) {
		console.log(hi)
	},
}
console.log(obj.uanme) //"zs" 属性访问方式1
console.log(obj['age'])//18 属性访问方式2
obj.sayHi('hello') // "hello" 调用对象中的方法

变量·属性·函数·方法·的区别
变量:单独声明并赋值,单独存在
属性:一般写在对象中,不用声明,直接使用,以键值对形式接收属性名:属性值。
函数:一般是由function关键字声明,一般是命名函数,或者函数表达式用=等号接收一个函数
方法:定义在对象中的函数一般就叫方法,而方法的声明方式和属性名:函数名,属于键值对形式的。和命名函数或匿名函数声明上不一致。
但是本质上相同。都是去实现某种功能或处理某件事情。方法的调用方式也有所不同,是对象.函数名去调用的。
new Object方式创建对象
var obj = new Object()
obj.name = 'zs'
obj.sayHi = function(hi){}
new Object方式去创建对象之后,属性接收方式和字面量创建方式的接收形式不一致,必须是对象名=属性值或者方法名。

我们为什么需要构造函数:如果一次性需要创建多个同类型同方法的对象,只有对象的属性值不一样而已。大量的创建多个对象,不如封装一个构造函数去构造一个对象类型的构造函数,在需要创建新的对象时,只需要new构造函数,并传递所需实参就能创建一个新的对象。
封装构造函数
function Hero(uname, age) {
	this.uname = uname
	this.age = age
	this.sayHi = function (message) {
		console.log(message)
	}
}
var liubei = new Hero('刘备', 35) //  console.log(liubei) ==>Hero {uname: "刘备", age: 35, sayHi: ƒ}
liubei.sayHi('曹贼,拿命来!')//曹贼,拿命来!
var zhangfei = new Hero('张飞', 42) //console.log(zhangfei) ==>Hero {uname: "张飞", age: 42, sayHi: ƒ}
zhangfei.sayHi('一夫当关,万夫莫开!')//一夫当关,万夫莫开!
构造函数与对象的区别:
1:对象指单独的某一个对象,他有自己的属性和方法,不需要向构造函数一样用this.属性名去接收每一个属性值。
2:构造函数也称为对象的实例化过程,一个构造函数可以实例化n个对象。

构造函数执行过程

构造函数new关键字做了些啥,分析它的执行过程
1: 在内存中创建了一个新的空对象
2:让this指向这个新的对象
3this.属性名接收的是调用函数传递过来的实参,通过this.属性名=属性值的方式,给该构造函数新增属性值。
4:构造函数不需要return,直接调用构造函数就能创建出一个新的对象。

遍历对象:

var obj = {
	name: 'zs',
	sex: '男',
	sayHi: function (hi) {
		console.log(hi)
	},
}
for (var k in obj) {
	console.log(k)// 返回的是属性名: name  age  sex
	console.log(obj[k])//返回的是属性值: zs 男 f(hi) {cosnole.log(hi)}
}
// 注意单独使用k的时候是属性名,用obj[k]相当于就是对象.属性名,所以返回来的都是该属性的值。

JS内置对象

JS对象分为3种:自定义对象,内置对象,浏览器对象

JS对象分为3种:自定义对象,内置对象,浏览器对象
前面2种对象是js基础内容,属于ECMAScript, 第三个浏览器对象属于我们js独有的。
内置对象:就是js语言自带的一些对象,这些对象供开发者使用,并提供了一些最基础而必要的功能(属性和方法)
内置对象最大的优点就是帮助我们快速开发。
JS提供了多个内置对象: Math, Date, Array, String

Math数学对象:

最大值:Math.max(1, 44, 56, 32) // 56
向下取整:Math.floor 忽略小数
console.log(Math.floor(4.3~4.75)) // 返回的都是 整数4
向上取整:Math.ceil 只要有小数就自增+1
console.log(Math.ceil(3.1~7.36))// 只要有小数,就会自增1, 返回的是4~8
四舍五入:Math.round
console.log(Math.round(3.2~7.6)) // 3~8
返回绝对值:Math.abs ,不管正负,返回的都是正数
console.log(Math.abs(-1 ~ 1)) //返回的都是 1 1,
console.log(Math.abs(-6 ~ 75)) // 6 7.5都会取整然后返回。
最大值:Math.max
console.log(Math.max(2, 8, 4, 6, 3)) // 8
最小值: Math.min
console.log(Math.min(3, 9, 5, 6, 2, 7)) // 2
生成随机数:Math.random
console.log(Math.random()) //随机生成0.1~0.9之间的浮点数
自己封装随机数方法
function getRandom(min, max) {
	return Math.floor(Math.random() * (max - min + 1)) + min //注意此处方法,去MDN看文档
}
console.log(getRandom(1, 10))//随机生成 1-10之间的随机整数\

生成随机数:Math.random

console.log(Math.random()) //随机生成0.1~0.9之间的浮点数

自己封装随机数方法

function getRandom(min, max) {
	return Math.floor(Math.random() * (max - min + 1)) + min //注意此处方法,去MDN看文档
}
console.log(getRandom(1, 10)) //随机生成 1-10之间的随机整数
var arr = ['小明', '小李', '小月', '小阳', '小海']
console.log(arr[getRandom(0, 4)])// 生成0-4之间的索引, 随机点名

封装最大值和最小值的数学函数:

var myMath = {
	max: function (arr) {
		var max = arr[0]
		for (var i = 0; i <= arr.length - 1; i++) {
			if (arr[i] > max) {
				max = arr[i]
			}
		}
		return max
	},
	min: function (arr) {
		var min = arr[0]
		for (var i = 0; i <= arr.length - 1; i++) {
			if (arr[i] < min) {
				min = arr[i]
			}
		}
		return min
	},
}
console.log(myMath.max([1, 6, 9, 2, 4])) //9
console.log(myMath.min([3, 6, 9, 2, 4])) //2
Date日期对象:
var date = new Date() // Fri Nov 13 2020 09:54:32 GMT+0800 (中国标准时间)
var date1 = new Date(2020, 11, 11) //Fri Dec 11 2020 00:00:00 GMT+0800 (中国标准时间)
数组的2种创建方式:
var arr = [1, 3, 5]; // 字面量方式
var arr1 = new Array(2, 4, 6); // new Array()方式
instanceof + Array.isArray检测是否为数组
var arr = [1, 2]
console.log(arr instanceof Array)
console.log(Array.isArray(arr))

数组方法

数组方法: push末尾添加  pop删除末尾 unshift开头添加  shift删除开头  reverse翻转  sort排序 
var arr = [1, 2]
arr.push(4) // (3) [1, 2, 4] 尾添加
arr.unshift(9) // (4) [9, 1, 2, 4] 头添加
arr.pop() //(3) [9, 1, 2] 尾删除
arr.shift() //(2) [1, 2] 头删除
arr.reverse()
var arr = [1, 3, 5, 7, 9]
arr.reverse() // (5[9, 7, 5, 3, 1]
arr1.sort()
var arr1 = [3, 7, 9, 4, 6, 2, 0, 1]
arr1.sort() // (8[0, 1, 2, 3, 4, 6, 7, 9]
arr.indexOf()
arr.indexOf('blue')//如果有多个同名项,会返回第一个找到的那项,返回的是那项的索引值。
var arr = ['red', 'green', 'blue']
arr.indexOf('green') // 1
arr.lastIndexOf()
arr.lastIndexOf('blue')// 如果数组中有多个同名项,会从尾到头反着找出那项,返回的是那项的索引值。
var arr = ['red', 'green', 'blue', 'yellow', 'deeppink']
arr.lastIndexOf('yellow') // 3
toString()
toString() 把数组转换为字符串,返回用逗号分隔的字符串
var arr = [1, 3, 5, 7, 9]
arr.toString() //1,3,5,7,9
arr.join()
arr.join() 把数组中的字符串,默认用返回用逗号分隔的字符串,如果join('-'),那返回的字符串每项字符都是用横线-隔开的
var arr = ['my', 'so', 'cool']
arr.join('-') //my-so-cool
数组去重
function repetition(arr) {
	var newArr = []
	for (var i = 0; i < arr.length; i++) {
		if (newArr.indexOf(arr[i]) === -1) { // 把确实不重复的每一项装进一个新的数组
			newArr.push(arr[i])
		}
	}
	return newArr
}
repetition([1, 3, 5, 7, 9, 3, 1, 7]) //(5[1, 3, 5, 7, 9]
数组转字符串的2种方式
var arr = [1, 2, 3]
console.log(arr.toString()) // 1,2,3
console.log(arr.join('%')) // 1%2%3
arr.concat(arr1)
var arr1 = [4, 5, 6]
console.log(arr.concat(arr1)) // (6) [1, 2, 3, 4, 5, 6]
splice(0, 3)
删除:splice(开始位置, 结束位置) 会返回一个新的数组
var arr2 = [1, 2, 3, 4, 5]
console.log(arr2.splice(0, 3)) // (3) [1, 2, 3]
slice(开始位置, 结束位置)
截取: slice(开始位置, 结束位置) 会返回一个新的数组。效果基本和splice一致!
console.log(arr2.slice(0, 3)) //(3) [1, 2, 3]

倒计时案例:画图分析 ↓↓↓

简单类型和复杂类型

new String(str)简单类型包装成了复杂类型
基本包装类型是有长度的, 通过new String(str), 把简单类型包装成了复杂类型,复杂类型才有属性和方法。
var str = 'andy'
var temp = new String(str) // String {"andy"}
str.indexOf('要') 根据字符串返回位置:
var str = '不管我就吃要吃肉肉'
console.log(str.indexOf('要')) // 5 根据字符串返回索引
求某个字符串出现的位置以及次数:
var str = 'jsdofhasfhsafwoeffsjdhsvafweffsdvsdsss'
var index = str.indexOf('f') // indexOf只能查找到第一次f出现的位置
var num = 0

while (index !== -1) {
// 不止出现一次,表示找到一个 ==-1表示没找到, !==-1表示找到了一个
num++ //统计次数
index = str.indexOf('f', index + 1) // 这就是算法,死记硬背就可以了
console.log('出现的位置:' + index) // 打印了每个f出现的位置,返回f出现的索引。
}
console.log('f出现的次数:' + num) //f出现的次数:8
根据位置返回字符串:
var name = 'annike'
console.log(name.charAt(2)) // "n"
console.log(name.charCodeAt(4)) // k
统计出现次数最多的字符串:
// 1:先算每个字数出现的次数
var str = 'aabbbccddeeff' // 13个字符串

var obj = {}
for (var i = 0; i < str.length; i++) {
	var num = str.charAt(i) // 找出每个字符串出现的次数
	if (obj[num]) {
		obj[num]++ // 如果该字符串再次出现一次就,属性值就累加
	} else {
		obj[num] = 1 // 如果只出现1次,就用1表示
	}
}
console.log(obj)
2:统计出现字数最多的那个字符串
var max = 0
var count = 0
for (var k in obj) {
	if (obj[k] > max) {
		// k 是属性名, obj[k]是属性值
		max = obj[k]
		count = k
	}
}
console.log(max) // 3
console.log('最多出现的字符串是:' + count) // 最多出现的字符串是:b

拼接以及截取字符串:

concat 拼接
var str = 'anni'
console.log(str.concat('ke')) // "annike"

substr 截取

var str1 = '川普下台啦!'
console.log(str1.substr(2, 2)) // "下台" (开始位置:包含该位置, 截取的个数)

替换字符串以及转换为数组:

replace替换
将数组中的o替换为*
var str = 'opfefopfefobfgbqwo'
while (str.indexOf('o') !== -1) { // !== -1,表示找到1个o, 就替换1个o。
	str = str.replace('o', '*') // ('等待被替换的', '即将替换成的')
}
console.log(str)
split分隔
将字符串替换成数组,并用 , 逗号分隔每项。
var str = 'a, ya, ya'
console.log(str.split(',')) //(3) ["a", " ya", " ya"]

var str2 = 'yes$blue$pink'
console.log(str2.split('$')) //(3) ["yes", "blue", "pink"]

数据类型内存分配: 画图分析↓↓↓

数据类型内存分配:
简单数据类型: 直接存放在栈里面,在栈里面开辟一块空间,存放的是属性的值。
复杂数据类型:它只在栈里面开辟一个地址引用,然后栈里的引用指向了堆里的存储的数据。

简单数据类型传参: 画图分析↓↓↓
当我们把变量当做实参在函数调用的时候传递带函数的形参位置,其实就是把该变量在栈里面直接复制了一份给到了函数的形参。
此时在函数中对该变量做任何的修改都是不会影响原来外部的变量的。因为他是复制的,也是独立一份存在的。

复杂数据类型传参: 画图分析↓↓↓
复杂数据类型在把变量当做实参传递到函数调用的形参中,其实只是把栈里的引用地址拷贝了一份。其实本质上他们2个的引用地址还是指向堆里的存储的数据。
所以在函数中修改了变量的属性名时,等效于修改了堆里的数据。所以堆里的数据被拷贝对象的地址引用给修改了。

2:Web APIs

Web APIs:

Web APIs 是W3C组织定义的标准,我们主要学习 DOM 和 BOM。Web APIs是JS独有的。主要是为了实现页面交互功能, 
需要前面学的ECMAScript语法基础做铺垫才能稳步上身。

API的含义:
预先定义好的功能,无须了解内部工作机制,直接拿来使用就可以了。因为有很多API,所以称为Web APIs.
它是浏览器预先定义好的接口给开发者使用,主要是做浏览器交互效果。
一般都有输入和输出(函数的传参和返回值), Web API很多都是方法(函数)。学习思路和前面学习JS语言内置对象一样的。

DOM文档对象模型

DOM:文档对象模型,是W3C推荐的可拓展语言的标准编程接口
W3C 已经定义了一系列的DOM接口, 通过这些DOM接口可以改变网页的内容,结构和样式。

Document Object Model(文档对象模型),就是把「文档」当做一个「对象」来看待。

相应的,Browser Object Model(浏览器对象模型),即把「浏览器」当做一个「对象」来看待。

DOM 中,文档中的各个组件(component),可以通过 object.attribute 这种形式来访问。

一个 DOM 会有一个根对象,这个对象通常就是 document

BOM 除了可以访问文档中的组件之外,还可以访问浏览器的组件,比如问题描述中的 navigator(导航条)、history(历史记录)等等。

文档对象模型:
文档对象模型: 一个页面就是一个文档, DOM中使用 document表示根对象。
元素: 页面所有的标签都是元素, DOM中使用element表示
节点: 网页中所有的内容都是节点, (标签,属性,文本,注释···), DOM中用node表示。
getElement获取元素
getElementById根据ID获取元素:getElementById('id名称')
getElementByTagName根据标签获取元素:getElementByTagName('li')
getElementByClassName根据类名获取元素: getElementByClassName
H5新增元素获取方式:
document.querySelector('.box') 根据类名获取元素
document.querySelector('#box') 根据id名获取元素
document.querySelector('li')   根据标签获取元素
document.querySelectorAll('.box || li') 获取所有该类名或者该标签的元素

获取body元素:document.body;
获取html元素:document.documentElement;
事件和样式操作
事件三要素:事件源 ==> 哪个触发的, 事件类型 ==> 用什么事件类型去处理该事件, 事件处理程序 ==> 处理过程和返回结果

事件类型:
点击事件:onclick 左键点击
鼠标移动事件一:onmouseover 鼠标进入   onmouseout 鼠标离开
输入框取事件:onfocus 输入框获取焦点    onblur失去焦点
鼠标移动事件二:onmousemove 鼠标移动触发  onmouseup鼠标弹起触发   onmousedown鼠标按下触发

innerText + innerHTML

操作元素 - 修改元素的内容:div.innerText  ||   div.innerHTML
innerText 和 innerHTML的区别:
innerText 不识别htnml标签, 非标准,同时会去除空格和换行。不管你也买呢如何空格换行,在控制台打印都会默认显示成一行,并去除掉标签,只显示内容。
innerHTML 识别html标签,识别html标签,是W3C标准,打印时会保留空格和换行,以及能把标签原文显示输出。
总结: 综合可见,能用innerHTML就不用innerText
操作元素 - 修改元素的属性:
点击按钮切换显示图片和图片的title提示:
var ldhBtn = document.querySelector('.ldh')
var zxyBtn = document.querySelector('.zxy')
var img = document.querySelector('img')
ldhBtn.onclick = function () {
	img.src = './images/zxy.jpg'
	img.title = '华仔海报,只卖9块9'
}
zxyBtn.onclick = function () {
	img.src = './images/zxy.jpg'
	img.title = '学友海报,只卖9块9'
}
修改表单属性
操作元素 - 修改表单属性:type  value  checked  selected  disabled
var btn = document.querySelector('.btn')
var input = document.querySelector('input')
btn.onclick = function(){
  input.value = 'Hi, 我在!'//修改输入框中的内容
  this.disable = true// 事件源是按钮, 所以点击会禁用按钮。
}
修改样式属性
操作元素 - 修改样式属性:元素名.style.属性 = ‘属性值’
var div = document.querySelector('div')
div.onclick = function(){
	this.style.backgroundColor = 'deeppink'
    this.width = '200px'
}
循环精灵图
循环精灵图:使用精灵图给页面上的每一个小li添加背景
var lis = document.querySelectorAll('li'); // 获取所有li
for (var i = 0; i < lis.length; i++ ) { //循环找出每一个li
  var index = i * 44; 拿到每个精灵图的坐标 44 88 132 ····
  lis[i].style.backgroundPosition = '-0' + index + 'px' //给每个精灵图设置坐标,一般精灵图都是负数。
}
calssName修改样式属性
使用calssName修改样式属性:
1:预先定义好类名,设置好样式(这样的好处就是,不用简化代码,不用给同一个元素用多行代码来设置样式。一个类名就搞定了)
.beautiful {
	width: 300px;
    height: 200px;
    color: #fff;
    background-color: "skyblue";
}
var box = document.querySelector('.box')
box.onclick = function() {
	this.className = 'first beautiful' // 可以同时存在多个类名,如果不需要之前的类名,就把新类名写上去,旧类名就被覆盖了。
}

操作元素总结:画图分析↓↓↓ 案例:

排他思想:

var btns = document.querySelectorAll('button')
for (var i = 0; i < btns.length; i++) {
	btns[i].onclick = function() {
    	for (var i = 0; i < btns.length; i++) {
        	btns[i].style.backgroundColor = 'none'
        }
        this.style.backgroundColor = 'deeppink'
    }
}

网页换肤:换背景图

var images = document.querySelector('.container').querySelector('img')
for (var i = 0; i < images.length; i++) {
	images[i].onclick = function(){
    	document.body.style.backgroundImage = 'url('+ this.src +')'
    }
}

鼠标经过表格改变背景色:

var trAll = document.querySelector('.container').querySelectorAll('li')
for (var i = 0; i < trAll.length; i++) {
	trAll[i].onmouseover = function () {
		this.style.background = 'skyblue'
	}
	trAll[i].onmouseout = function () {
		this.style.background = ''
	}
}

复选框全选案例:

var checkAll = document.querySelector('.one')
var childboxs = document.querySelectorAll('.child')
checkAll.onclick = function () { // 全选按钮
	for (var i = 0; i < childboxs.length; i++) {
		childboxs[i].checked = this.checked // 所有子按钮和父按钮的选中状态保持一致
	}
}
for (var i = 0; i < childboxs.length; i++) { //第一层循环给每一个子选框绑定点击事件
	childboxs[i].onclick = function () { // 子按钮事件,如果子按钮全选中,父按钮状态也被选中。
		var flag = true //设置标识符
		for (var i = 0; i < childboxs.length; i++) { // 第二层循环判断是否还有子按钮未选中
			if (!childboxs[i].checked) {
				flag = false
				break // 只要有1个按钮没被选中,程序就会被打断,就不会执行后面的语句
			}
		}
		checkAll.checked = flag // 循环之外,能走到这里,标识每个子按钮都已经被选中了。此时就让父按钮的状态和标识符一致。
	}
}

自定义属性操作

setAttribute getAttribute removeAttribute
<div index="1" class="box"></div>
var div = document.querySelector('div')
// 设置
div.setAttribute('index', 3)
// 获取
var id = div.getAttribute('index')
// 移除
div.removeAttribute('class')

tab栏切换 画图分析↓↓↓

H5新增自定义属性:

<div data-list-name="annike"></div>
var div = document.querySelector('div')

获取

console.log(div.getAttribute('data-list-name')) //"annike"

设置

div.setAttribute('data-time', 2020) //

H5方式:

console.log(div.dataset.time) //"2020" dataset它能获取data开头的自定义属性,需要使用驼峰命名法。
console.log(div.dataset['listName']) //"annike"

节点操作

节点概述:
节点概述:节点分为nodeType节点类型,nodeName节点名称,nodeValue节点值,这3个基本属性。
元素节点: nodeType 为 1
属性节点: nodeType 为 2
文本节点: nodeType 为 3(文本节点包含了,空格,换行等)
在我们实际开发中,节点操作,主要操作的是元素节点。
parentNode childNodes
1:操作父节点 box.parentNode // 返回的是该元素最近的父节点,如果找到父元素则会返回null
2:操作子节点:boxs.childNodes[1].nodeType // 子节点包含(文本节点包含了,空格,换行等)
firstChild lastChild
3:操作第一个节点和最后一个节点: 
方式一:ul.firstChild // ul下面的第一个子节点   ul.lastChild // ul下面的最后一个子节点
方式二:ul.firstElementChild // ul下面的第一个子节点    ul.lastElementChild  // ul下面的最后一个子节点
方式三(推荐):ul.children[0] // 实际开发中的写法,没有兼容性,又简洁。
4:操作兄弟节点:这2中方法都有兼容性问题,需要自己封装函数处理兼容
方式一:div.previousSibling // 上一个兄弟节点   div.nextSibling // 下一个兄弟节点
方式二:div.previousElementSibling //  上一个兄弟节点    div.nextElementSibling // 下一个兄弟节点
5:createElement 创建节点
var li = document.createElement('li')
li.innerHTML = 'hello!'
var ul = document.querySelector('ul')
ul.appendChild(li) // 在数组中的后面添加一项
ul.insertBefore(li, ul.children[0]) // 插入到指定的位置(要插入的元素, 要插入的位置)
removeChild删除节点
var ul = document.querySelector('ul')
var btn = document.querySelector('button')
btn.onclick = function () {
	if (ul.children.length === 0) {
		this.disabled = true //如果页面已经不存在li标签了,就禁用删除按钮
	} else {
		ul.removeChild(ul.children[0]) // 反之页面还存在,使用removeChild删除掉ul中的第一个元素。直到删除干净为止。
	}
}
7:复制节点:
var ul = document.querySelector('ul')
var liOne = ul.children[0].cloneNode(true) //true不但拷贝节点,还拷贝内容。深拷贝。
ul.appendChild(liOne) // 将拷贝出来的新元素,添加到数组的最后面。

8:留言板案例:发布和删除留言: 画图分析↓↓↓ 动态创建表格案例: 画图分析↓↓↓

三种创建元素的区别:

document.write是直接将内容写入内容流中,但是文档流执行完毕,则它会导致页面全部重新绘制
innerHTML是将内容写入某个DOM节点,不会导致页面重绘
innerHTML创建多个元素效率会更高,(不要拼接字符串,采取数组形式拼接), 结构稍微复杂。
createElement()创建多个元素效率稍微低些, 但是结构更清晰。
总结:不同浏览器下,innerHTML效率要比createElement高。

DOM回顾总结:

dom主要是对元素进行操作,主要有:创建,删除,修改,查询,属性操作,事件操作。

1:创建:
document.write
innerHTML
createElement
2:添加:
appendChild
insertBefore
3:删除
removeChild
4:改:
4:改: 主要修改dom的元素属性,dom元素的内容,属性,表单的值2等
修改元素属性: src  href  title 等
修改普通元素内容: innerHTML   innerText
修改表单元素: value   type   disabled 等
修改元素样式:  style  className
查:只要查询dom元素
DOM提供的API方法: getElementById  getElementsByTagName 这些方法比较古老,不太推荐
H5提供的新方法: querySelector  querySelectorAll (推荐)
利用节点操作获取元素: 父parentNode  子children  兄弟previousElementSibling  nextElementSibling
属性操作:
属性操作: 主要针对于自定义属性
setAttribute 设置元素的自定义属性
getAttribute  得到dom的属性值
removeAttribute 移除属性
事件操作:
事件操作: 给元素绑定事件, 一般是: 事件源, 事件类型 = 事件处理程序
点击事件:onclick 左键点击
鼠标移动事件一:onmouseover 鼠标进入   onmouseout 鼠标离开
输入框取事件:onfocus 输入框获取焦点    onblur失去焦点
鼠标移动事件二:onmousemove 鼠标移动触发  onmouseup鼠标弹起触发   onmousedown鼠标按下触发

事件详解

注册事件的两种方式:
1:btn.onclick = function(){} //传统注册方式,一个元素只能绑定一个事件
2:btn.addEvenetListener('click', function(){}) // 监听方式注册,一个元素可以绑定多个事件,依次执行。
3:div.attachEvent('onclick', function () {}) //其他浏览器没效果会报错,只有ie9之前的能识别。
删除事件绑定的两种方式:
btn.onclick = null // 传统方式
btn.removeEventListener('click', fn1)//接触事件监听('事件类型', 事件处理函数)
事件冒泡:
事件冒泡:事件传播过程
1:捕获阶段   2:当前目标阶段   3:冒泡阶段
捕获阶段:可以理解为向水里扔了一块石头,石头下沉到水里的过程,就是捕获阶段,由网景公司提出。
冒泡阶段:可以理解为石头沉到水底,触击了地面,触发了地面产生了水泡,水泡会越来越大,直到浮到水面,这过程就是冒泡过程。

事件冒泡: 画图分析↓↓↓

捕获过程:就是石头下沉水底的过程
div.addEventListener('click', function(){}, true) //它的过程是先document -> html -> body -> father -> son 先大后小
div.addEventListener('click', function(){}, false) //它的过程是先son -> father -> body -> html -> document 先小后大
window.event 事件对象
事件对象: e || window.event
事件对象:事件发生后,事件相关一系列的信息都在这个evnet事件对象里面。
btn.addEventListener('click', function(e){}) 
target和this的区别
e.target和this的区别: 还有一个currentTarget有兼容问题。
console.log(e) //MouseEvent {isTrusted: true, screenX: 2590, screenY: 19, clientX: 29, clientY: 19, …}
console.log(e.target) // <div>123</div>
console.log(this) // <div>123</div>

e.target 返回触发事件的那个元素

e.type 返回事件的类型 如: click

e.cancelBubble ie6-8使用,非标准。阻止冒泡。

e.preeventDefault 阻止默认行为,或者冒泡,如阻止a跳转,标准! 或者return false,但是阻止后,弊端是后面的代码也不执行了

e.stopPropagation 阻止冒泡 标准

冒泡的好处,可实现事件委托,如ul里面的每一个li是可以提高事件委托的方式,委托会ul,这样不用循环,每个li也是能点击的。节省DOM性能。 方式就是将事件委托在父元素上,利用了冒泡的原理,影响了里面的每一个li,实现了每一个li也能被点击。

事件委托案例

事件委托案例:委托给ul,让e.target当前点击的元素背景高亮。
var ul = document.querySelector('ul')
ul.addEventListener('click', function (e) {
	e.target.style.backgroundColor = 'skyblue'// 此处不能是this.style,否则整个ul都会有背景颜色。只能e.target让被点的li高亮。
})

禁用鼠标右键,禁用文字选中

了解2个新事件,一般不常用,禁用鼠标右键,禁用文字选中(不让文字被选中)
鼠标右键:contextmenu ==> e.preventDefault();
选中文字:selectstart ==> e.preventDefault();
document.addEventListener('contextmenu', function (e) {
	e.preventDefault()
})
document.addEventListener('selectstart', function (e) {
	e.preventDefault()
})
鼠标事件: MouseEvent 鼠标事件   KeyboardEvent键盘事件
e.clientX | Y 浏览器可视区域的坐标
e.pageX | Y   文档页面的坐标 IE9支持
e.screenX | Y 电脑屏幕的坐标

client screen page 关系图: 画图分析↓↓↓

常用的键盘事件:

onkeydown 键盘按下   onkeyup 键盘松开    ||    另一种:onkeypress 键盘按下,不识别功能键 如箭头 和ctrl + shift
document.addEventListener('keyup', function(){})

e.keyCode 键盘码 ==> 返回相应的ASCII码值

document.addEventListener('keyup', function(e){ e.keyCode })

模拟快递查询 画图分析↓↓↓

BOM浏览器对象模型

BOM介绍
什么是BOM:BOM浏览器对象模型,把浏览器当做对象来对待,BOM是浏览器厂商各自在浏览器定义的,兼容性差。它的核心对象是windowBOM由一系列相关对象构成,每个对象提供了许多方法和属性。
window.onload
window常见事件: 窗口加载事件,window.onload
load 等页面内容全部加载完毕,包含了图片,html,css,····。才会触发该函数,需要等待。
DOMContentLoaded 只要DOM文档对象模型加载完毕(不含图片,css···),就会去执行,不需要的等待,比load要快些。
window.addEventListener('load', function(){})
document.addEventListener('DOMContentLoaded', function(){})

window窗口发生改变触发 窗口大小事件:window.onresize || resize  一般用于响应式布局
window.onresize = function() {} 
window.addEventListener('resize', function(){})

定时器:

setInterval连续 || setTimeout一次性 , clearTimeout清除一次性 || clearInterval清除连续

1: setTimeout一次性:
setTimeout(function () {
console.log('砰!')
}, 1000)

function callback() {
console.log('爆炸了')
}
setTimeout(callback, 2000)

setTimeout 回调函数
setTimeout(function () {
div.style.display = 'none'
}, 3000)

清除一次性定时器:
var timeId = setTimeout(function () {
console.log('砰!')
}, 4000)
btn.addEventListener('click', function () {
clearTimeout(timeId)
})
2:setInterval 连续定时器
setInterval(function () {
console.log('hao a you')
}, 1000)

日期计算公式:
() / 1000
/ 60 /60 / 24
/ 60 /60 % 24
/ 60 % 60
% 60
页面倒计时案例:
function zero(n) {
return n < 10 ? '0' + n : n
}
getDate()
function getDate() {
var nowTime = new Date()
var targetTime = new Date('2020-12-12 18:00:00')
var time = (targetTime - nowTime) / 1000
var d = parseInt(time / 60 / 60 / 24)
var h = parseInt((time / 60 / 60) % 24)
var s = parseInt((time / 60) % 60)
var m = parseInt(time % 60)
document.querySelector('#day').innerHTML = zero(d) + '天'
document.querySelector('#hour').innerHTML = zero(h) + '时'
document.querySelector('#sec').innerHTML = zero(s) + '分'
document.querySelector('#minu').innerHTML = zero(m) + '秒'
}
setInterval(function () {
getDate()
}, 1000)

clearInterval 停止连续定时器
var timer = setInterval(function () {
console.log('爱老虎油')
}, 1000)
btn.addEventListener('click', function () {
clearInterval(timer)
})

发送短信倒计时案例:
btnSend.addEventListener('click', function () {
	var that = this
	var num = 5
	var timeMessage = setInterval(function () { // 所有事件都需要放在定时器中完成,包括清除定时器
		if (num == 0) { //2:如果计数器已经到了0,恢复按钮点击和修改按钮文字,清除掉定时器
			that.disabled = false
			clearInterval(timeMessage)
			that.innerText = '发送短信' 
		} else {
			num--
			that.innerText = '还剩' + num + '秒'
			that.disabled = true  // 1:先写定时器功能,点击之后修改文字倒计时,让按钮点击被禁用。
		}
	}, 1000)
})

this指向和js执行机制

this指向问题
this指向问题:this一般指向它调用的那个对象,谁调用或者谁触发就是谁,但是全局和命名函数以及定时器中this默认指向是window
console.log(this) //Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}

function fn() {
	console.log(this) //Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}
}
fn()

setTimeout(function () {
	console.log(this) // Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}
})

var obj = {
	sayHi: function () {
		console.log(this)
	},
}
obj.sayHi() //{sayHi: ƒ}

btn.addEventListener('click', function () {
	console.log(this)
}) // <button>点我</button>

function Fun() {
	console.log(this)
}
var fun = new Fun() // Fun {}

同步和异步

同步和异步:js是单线程,也就说同一个时间只能处理一件事情,如果js加载时间过长,页面就会有渲染阻塞的感觉。
同步: 有顺序的执行
function fn1() {
	var num = 10
	console.log(num) // 10
	function fn2() {
		console.log(num + 1) // 11
	}
	fn2()
}
fn1()

异步:打印的顺序 1 2 3,
console.log(1)
setTimeout(function () {
console.log(3)
}, 0)
console.log(2)
同步任务和异步任务执行过程:
先执行执行栈中的同步任务,异步任务放入任务队列中,等到所有同步任务执行完成,才会去把任务队列中的任务拿出来执行掉。
js的异步是通过回调函数来实现的,一般而言异步任务有三种类型:
1:普通事件: 如 click, resiz···
2:资源加载: 如load, error···
3:定时器: setInterval setTimeout···
异步任务将回调函数添加到任务队列中,任务队列也称为消息队列。

js执行机制:画图分析↓↓↓ 主线程不断的重复获得任务, 执行任务, 再获取任务, 再执行, 所以这种机制被称为事件循环 eventloop

location navgator history 对象

location常见属性:
location常见属性:
window对象给我们提供了一个location属性,用于获取或者设置浏览器URL,并且可应用于解析URL,因为这个属性返回的是一个对象,所以我们将这个属性称为location对象。
URL统一资源定位符是互联网上标准的资源的地址,互联网上每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
URL语法格式一般为:
proocol: //host[:prot]/path/[?query]#fragemnt
http://www.itcast.cn/index.html/?name=andy&age=18#link
url组成:
url组成:
protocol 通信协议常见http
host 主机(域名) www.baidu.com
prot 端口 默认80
path 路径, 一般由 /符号隔开的字符串, 一般用于表示文件路径以及层级目录地址
query 查询参数,以键值对形式,用&符号给开
fragment 片段 #后面的内容,常用于锚点链接
location对象的属性
location对象的属性
location.href 获取或者设置整个URL
location.host 返回主机域名 www.baidu.com
location.port 返回端口号
location.pathname 返回路径
location.search 返回参数
location.hash 返回片段 #后面内容, 常见于锚点链接。

5秒后跳转页面:

点击按钮,开启定时器,定时器内在5秒以后跳转到小米官网
btn.addEventListener('click', function () {
	var num = 5
	setInterval(function () {
		if (num == 0) {
			location.href = 'http:www.xiaomi.com'
		} else {
			num--
			a.innerHTML = '页面将在' + num + '秒后跳转到小米官网'
		}
	}, 1000)
})

location常见方法:

location.assign('http://www.mi.com') // 记录浏览器历史,实现后退功能,跟href一样,也叫重定向。
location.replace('http://www.itcast.cn') // 不记录浏览历史,所以不可以实现后退功能,替换当前页面。
location.reload(true) 重新加载页面,相当于按下了F5,如果是true表示强制刷新
history对象:
history.go(1) // 前进几个页面,参数可以是正值也可以是负值。
history.forward() // 前进功能
history.back() //后退功能

获取URL参数:画图分析↓↓↓

使用location.search获取到url参数,截取第一个字符串?,用split把=分隔的字符串转换为数组中2个单独的字符串,然后输出在页面。

offset client scroll系列用法:

offset 可以得到元素的位置偏移
offset 可以得到元素的位置偏移,大小等。获取元素距离带有定位父元素的位置。获取元素自身的大小(宽度高度),返回的值不带px。
常用:
offsetParent 返回子元素距离有定位父元素的位置
offsetTop  返回子元素距离有定位父元素上方偏移的位置
offsetLeft 返回子元素距离有定位父元素左边的偏移位置
offsetWidth 返回自身内容区的宽度,padding,边框,返回值不带单位
offsetHeight 返回自身内容区的高度,padding,边框,返回值不带单位

9:拖动模态框

var divs = document.querySelector('div')
divs.addEventListener('mousedown', function (e) {
	e = e || window.event
	var x = e.pageX - divs.offsetLeft
	var y = e.pageY - divs.offsetTop
	document.addEventListener('mousemove', move)
	function move(e) {
		divs.style.left = e.pageX - x + 'px'
		divs.style.top = e.pageY - y + 'px'
	}
	document.addEventListener('mouseup', function (e) {
		document.removeEventListener('mousemove', move)
	})
})

10:电商固定侧边栏广告

var twoTop = document.querySelector('.two').offsetTop
var hot = document.querySelector('.hot')

window.addEventListener('scroll', function (e) {
	if (window.pageYOffset >= twoTop) {
		hot.style.display = 'block'
		hot.style.position = 'fixed'
	} else {
		hot.style.display = 'none'
	}
})

offsetLeft offsetTop 元素偏移:画图分析↓↓↓

1: offsetLeft offsetTop 元素偏移:画图分析↓↓↓
offsetTop  返回子元素距离有定位父元素上方偏移的位置
offsetLeft 返回子元素距离有定位父元素左边的偏移位置

offsetWidth offsetHeight 元素大小:画图分析↓↓↓

2:offsetWidth offsetHeight 元素大小:画图分析↓↓↓
offsetWidth 返回自身内容区的宽度,padding,边框,返回值不带单位
offsetHeight 返回自身内容区的高度,padding,边框,返回值不带单位

offsetParent 返回子元素距离有定位父元素的位置

offsetParent 返回子元素距离有定位父元素的位置
console.log(son.offsetParent)  //<div class="father">···</div> 返回父元素
offset与style区别
offset与style区别
offset能获取到任意元素的值,包含块级和行内元素,获取的值没有单位,大小不含margin,只读属性,不能设置。一般用于获取元素位置。(获取)
style只能获取行内样式元素的值,获取的值带有px单位,style.width是纯大小,不包含padding+border.可读可写。一般用于设置元素样式。(设置)

4:获取鼠标在盒子内的坐标: 鼠标的位置e.pageX | Y · 画图分析↓↓↓

5:client系列: 一般用于获取该元素的边框,和元素大小(内容+padding,不含边框和border) 画图分析↓↓↓

立即执行函数:

6:立即执行函数:
方式一
function fn1() {
	console.log('fn1') //"fn1"
}
fn1()

方式二
;(function (a, b) {
	console.log(a + b) // 3
})(1, 2);

方式三
;(function getSum(x, y) {
	console.log(x * y) // 6
})(2, 3)

scroll系列:获取页面滚动出去的距离 · 画图分析↓↓↓

一图总结三大系列对比 :画图分析↓↓↓

offset 常用于获取元素的位置
client 常用于获取元素大小
scroll 常用于滚动距离
注意: 页面滚动的距离用 window.pageXOffset 获得

mouseover和mouseenter的区别:
mouseover和mouseenter的区别:
mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发。 mouseenter 只会经过自身盒子触发.
因为mouseenter不会冒泡,mouseenter搭配 鼠标离开 mouseleave 同样不会冒泡.
father.addEventListener('mouseenter', function(e) {
    console.log('123');
})

动画原理:

动画原理
1. 获得盒子当前位置
2. 让盒子在当前位置加上1个移动距离
3. 利用定时器不断重复这个操作
4. 加一个结束定时器的条件
5. 注意此元素需要添加定位, 才能使用element.style.left
var div = document.querySelector('div')
var timer = setInterval(function () {
if (div.style.left >= 400) {
    clearInterval(timer)
} else {
    div.style.left = div.offsetLeft + 1 + 'px'
}
}, 100)

简单动画函数封装:

var span = document.querySelector('span')
var div = document.querySelector('div')
function animate(ele, target) {
var timer = setInterval(function (e) {
    if (ele.offsetLeft >= target) {
    clearInterval(timer)
    } else {
    ele.style.left = ele.offsetLeft + 1 + 'px'
    }
}, 100)
}
animate(span, 200)
animate(div, 300)

动画函数-给不同元素记录不同的定时器:

function animate(obj, target) {
obj.timer = setInterval(function () {
    if (obj.offsetLeft >= target) {
    clearInterval(obj.timer)
    } else {
    obj.style.left = obj.offsetLeft + 1 + 'px'
    }
}, 100)
}
btn.addEventListener('click', function () {
animate(span, 300)
})

缓动动画原理:

1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
var span = document.querySelector('span')
var btn = document.querySelector('button')
function animate(obj, target) {
clearInterval(obj.timer)
obj.timer = setInterval(function () {
    if (obj.offsetLeft >= target) {
    clearInterval(obj.timer)
    } else {
    obj.style.left = obj.offsetLeft + 1 + 'px'
    }
}, 100)
}
btn.addEventListener('click', function () {
animate(span, 200)
})

缓动动画多个目标值之间移动:

function animate(obj, target) {
clearInterval(obj.timer)
obj.timer = setInterval(function () {
    var step = (target - obj.offsetLeft) / 10 //每一步
    step = step > 0 ? Math.ceil(step) : Math.floor(step) //保持整数前进
    if (obj.offsetLeft >= target) {
    clearInterval(obj.timer)
    } else {
    obj.style.left = obj.offsetLeft + step + 'px'
    }
}, 15)
}
btn500.addEventListener('click', function () {
animate(span, 500)
})
btn800.addEventListener('click', function () {
animate(span, 800)
})

缓动动画添加回调函数:

function animate(obj, target, callback) {
clearInterval(obj.timer)
obj.timer = setInterval(function () {
    var step = (target - obj.offsetLeft) / 10
    step = step > 0 ? Math.ceil(step) : Math.floor(step)
    if (obj.offsetLeft >= target) {
    clearInterval(obj.timer)
    callback && callback() //短路运算方式, 左边为true,执行的是右边
    } else {
    obj.style.left = obj.offsetLeft + step + 'px'
    }
}, 15)
}
var span = document.querySelector('span')
var btn500 = document.querySelector('.btn500')
btn500.addEventListener('click', function () {
animate(span, 300, function () {
    span.style.backgroundColor = 'skyblue'
})
})

动画函数的使用:

在该页面中调用animate函数,实现广告滑动出来。
// 鼠标经过广告箭头,右滑动出,鼠标离开,然后缩回去。
sliderbar.addEventListener('mouseenter', function () {
animate(con, -160, function () {
    this.children[0].innerHtml = '→'
})
})
sliderbar.addEventListener('mouseleave', function () {
animate(con, 0, function () {
    this.children[0].innerHtml = '←'
})
})

手写网页轮播图 - 实现完整代码算法 画图分析↓↓↓

节流阀返回顶部及筋斗云案例

逻辑中断

1:节流阀以及逻辑中断应用:
callback && callback() // 左侧为true, 执行右侧

带有动画的返回顶部

2:带有动画的返回顶部:
document.addEventListener('scroll', function () {
if (window.pageYOffset >= bannerTop) {
    sliderBar.style.position = 'fixed'
    sliderBar.style.top = sliderBarTop + 'px'
} else {
    sliderBar.style.position = 'absolute'
    sliderBar.style.top = '300px'
}
if (window.pageYOffset >= mainTop) {
    goBack.style.display = 'block'
} else {
    goBack.style.display = 'none'
}
})
goBack.addEventListener('click', function () {
window.scrollTo(0, 0)
})

3:筋斗云案例:

window.addEventListener('load', function () {
var cloud = document.querySelector('.cloud')
var lis = document.querySelectorAll('li')
var current = 0 // 1:初始化位置
for (var i = 0; i < lis.length; i++) {
    lis[i].addEventListener('mouseenter', function () {
    animate(cloud, this.offsetLeft)
    })
    lis[i].addEventListener('mouseleave', function () {
    animate(cloud, current) // 3:离开保存当前位置
    })
    lis[i].addEventListener('click', function () {
    current = this.offsetLeft // 2:点击记录当前位置
    })
}
})

移动端轮播图实现完整代码算法 画图分析↓↓↓ HTML5本地存储及记住用户名案例

本地存储特性:生命周期为关闭浏览器窗口,在同一个窗口(页面)下数据可以共享,以键值对的形式存储使用.
刷新不丢失数据,sessionStorage约5M、localStorage约20M,只能存储字符串,可以将对象JSON.stringify() 编码后存储.

1:本地存储之sessionStorage:

存储数据:sessionStorage.setItem('uname', val)
获取数据:sessionStorage.getItem('uname')
删除数据:sessionStorage.removeItem('uname');
删除所有数据:sessionStorage.clear();

2:本地存储之localStorage:

2:本地存储之localStorage:声明周期永久生效,除非手动删除 否则关闭页面也会存在,可以多窗口(页面)共享(同一浏览器可以共享),以键值对的形式存储使用
存储数据:localStorage.setItem('uname', val)
获取数据:localStorage.getItem('uname')
删除数据:localStorage.removeItem('uname');
删除所有数据:localStorage.clear();

3:记住用户名案例

btnChecked.addEventListener('click', function () {
if (this.checked == true) {
    localStorage.setItem('username', iptValue.value)
} else {
    localStorage.removeItem('username')
}
})

jQuery

jQuery介绍及常用API

1:jQuery介绍

1:jQuery介绍
仓库: 可以把很多东西放到这个仓库里面。找东西只需要到仓库里面查找到就可以了。
JavaScript库:即 library,是一个封装好的特定的集合(方法和函数)。从封装一大堆函数的角度理解库,就
是在这个库中,封装了很多预先定义好的函数在里面,比如动画animate、hideshow,比如获取元素等。
简单理解: 就是一个JS 文件,里面对我们原生js代码进行了封装,存放到里面。这样我们可以快速高效的使用
这些封装好的功能了。
比如 jQuery,就是为了快速方便的操作DOM,里面基本都是函数(方法)。
jQuery 是一个快速、简洁的 JavaScript 库,
j 就是 JavaScript; Query 查询; 意思就是查询js,把js中的DOM操作做了封装,我们可以快速的查询使用里
面的功能。
jQuery 封装了 JavaScript 常用的功能代码,优化了 DOM 操作、事件处理、动画设计和 Ajax 交互。
学习jQuery本质: 就是学习调用这些函数(方法)。
jQuery 出现的目的是加快前端人员的开发速度,我们可以非常方便的调用和使用它,从而提高开发效率。

3:jQuery概述

3:jQuery概述
轻量级。核心文件才几十kb,不会影响页面加载速度
 跨浏览器兼容。基本兼容了现在主流的浏览器
 链式编程、隐式迭代
 对事件、样式、动画支持,大大简化了DOM操作
 支持插件扩展开发。有着丰富的第三方的插件,例如:
树形菜单、日期控件、轮播图等  免费、开源

入口函数

4:jQuery基本使用-入口函数
$(function(){···})// 此处是页面 DOM 加载完成的入口
$(document).ready(function(···){}) //  此处是页面 DOM 加载完成的入口
1. 等着 DOM 结构渲染完毕即可执行内部代码,不必等到所有外部资源加载完成,jQuery 帮我们完成了封装。
2. 相当于原生 js 中的 DOMContentLoaded3. 不同于原生 js 中的 load 事件是等页面文档、外部的 js 文件、css文件、图片加载完毕才执行内部代码。 4. 更推荐使用第一种方式。

顶级对象$

5:jQuery顶级对象$
1.$ 是 jQuery 的别称,在代码中可以使用 jQuery 代替 $,但一般为了方便,通常都直接使用 $ 2.$ 是jQuery 的顶级对象, 相当于原生JavaScript中的 window。把元素利用$包装成jQuery对象,就可以调用
jQuery 的方法。
2. $同时也是jQuery的 顶级对象
jQuery(function () {
  jQuery('div').hide()
})

DOM对象和jQuery对象

6:DOM对象和jQuery对象
1. 用原生 JS 获取来的对象就是 DOM 对象
2. jQuery 方法获取的元素就是 jQuery 对象。
3. jQuery 对象本质是: 利用$对DOM 对象包装后产生的对象(伪数组形式存储)。
注意:
只有 jQuery 对象才能使用 jQuery 方法,DOM 对象则使用原生的 JavaScirpt 方法。

DOM对象和jQuery对象相互转换

7:DOM对象和jQuery对象相互转换
DOM 对象与 jQuery 对象之间是可以相互转换的。
因为原生js 比 jQuery 更大,原生的一些属性和方法 jQuery没有给我们封装. 要想使用这些属性和方法需要把
jQuery对象转换为DOM对象才能使用。
1. DOM 对象转换为 jQuery 对象: $(DOM对象)
$('div') 
2. jQuery 对象转换为 DOM 对象(两种方式)
$('div') [index] index 是索引号 
$('div') .get(index) index 是索引号
$('video')[0].play()
$('video').get(0).play()

jQuery选择器

基本和层级选择器

基本和层级选择器
 jQuery 基础选择器
原生 JS 获取元素方式很多,很杂,而且兼容性情况不一致,因此 jQuery 给我们做了封装,使获取元素统一标准。
$(“选择器”) // 里面选择器直接写 CSS 选择器即可,但是要加引号
$("#id")  $(".class")  $("div")  $("div,li,span")  $("li.current")

层级选择器

层级选择器
层级选择器最常用的两个分别为:后代选择器和子代选择器。
$("ul li")   $("ul>li")

隐式迭代

隐式迭代 // 被选中的元素都添加了样式,默认自带循环效果。
$('div').css('background', 'red')
$('ul li').css('color', 'blue')

筛选选择器

筛选选择器
筛选选择器,顾名思义就是在所有的选项中选择满足条件的进行筛选选择。常见如下 :
$("li:first")  $("li:last")   $("li:eq(2)")  $("li:odd")  $("li:even")

jQuery中还有一些筛选方法,类似DOM中的通过一个节点找另外一个节点,父、子、兄以外有所加强。

筛选方法-选取父子元素

筛选方法-选取父子元素
$('.son').parent() // 选取父子元素
$('.nav').find('p') // 查找该父元素nav中嵌套的p标签子元素
$(function () {
console.log($('.son').parent()) // w.fn.init [div.father, prevObject: w.fn.init(1)]
$('.nav').find('p').css('color', 'blue')  //find查找该父元素nav中嵌套的p标签子元素,全部会找出来。
})

新浪下拉菜单

$('.nav >li').mouseenter(function () {}) //鼠标经过
$('.nav >li').mouseenter(function () {}) //鼠标离开
$('ele').show() // 显示
$('ele').hide() // 隐藏
$(function () {    //鼠标经过显示下拉菜单
$('.nav >li').mouseenter(function () {
    $(this).children('ul').show()
})               //鼠标离开隐藏下拉菜单
$('.nav >li').mouseleave(function () {
    $(this).children('ul').hide()
})
})

其他筛选方法

siblings + eq + hasClass

$('ol >li').siblings('li') // 兄弟元素siblings 除了自身元素之外的所有亲兄弟
$('ul >li').eq(4) //查找该子元素
$('ul >li').eq(变量名) //查找该子元素
$('ol >li').hasClass('item')//判断是否有某个类名,返回布尔值。
$(function () {
// 1. 兄弟元素siblings 除了自身元素之外的所有亲兄弟
$('ol >li').siblings('li').css('background', 'yellow')
// (2) 我们可以利用选择方法的方式选择 更推荐这种写法
var index = 2
$('ul >li').eq(4).css('color', 'blue')
$('ul >li').eq(index).css('color', 'red')
判断是否有某个类名
console.log($('ol >li').hasClass('item'))//true
})

排他思想

$(function() {
    // 1. 隐式迭代 给所有的按钮都绑定了点击事件
    $("button").click(function() {
        // 2. 当前的元素变化背景颜色
        $(this).css("background", "yellow");
        // 3. 其余的兄弟去掉背景颜色 隐式迭代
        $(this).siblings("button").css("background", "");
    });
})

电商商品切换案例

index()方法,给元素创建自定义属性index
$('#content >div').eq(index).show().siblings('div').hide()//链式编程,根据鼠标经过的index显示对应的商品图片

$(function () { //隐式迭代,给所有的li绑定事件
$('#left > li').mouseenter(function () {
    var index = $(this).index() //index()方法,给元素创建自定义属性index
    $('#content >div').eq(index).show().siblings('div').hide()// 根据鼠标经过的index显示对应的商品图片
})
})

链式编程及样式操作

链式编程
链式编程
链式编程是为了节省代码量,看起来更优雅。
$(this).css('color', 'red').sibling().css('color', '');
链式编程-修改样式css方法
修改样式css方法
参数可以是对象形式,方便设置多组样式。属性名和属性值用冒号隔开, 属性可以不用加引号,
$(this).css({ "color":"white","font-size":"20px"});

$(function () {
$('div').css({
    width: '300', // 注意px单位是可以省略的
    height: '400px',
    backgroundColor: 'red', //复合属性则必须采取驼峰命名法, 如果值不是数字,则需要加引号
})
})
修改样式操作类
作用等同于以前的 classList,可以操作类样式, 注意操作类里面的参数不要加点。
$(“div”).addClass(''current''); 1. 添加类
$(“div”).removeClass(''current'');2. 移除类
$(“div”).toggleClass(''current'');2. 切换类

$('div').addClass('current')
$('div').removeClass('current')
$('div').click(function () {
    $('div').toggleClass('current')
})

tab栏切换案例

$(function () {
$('.tab_list > ul > li').click(function () {
    $(this).addClass('current').siblings('li').removeClass('current') // 点击让tab高亮
    var index = $(this).index() //拿到tab的index索引
    $('.tab_con > .item').eq(index).show().siblings().hide()//根据tab的索引,对应显示,其他兄弟元素隐藏
})
})

类操作和className区别

原生 JS 中 className 会覆盖元素原先里面的类名。
jQuery 里面类操作只是对指定类进行操作,不影响原先的类名。
var one = document.querySelector('.one')
one.className = 'three' // <div class="three"></div> js 覆盖了之前所有类名,只留现在这个类名

$('.one').addClass('two') // <div class="one two"></div> 追加类名 旧类名和新类名同时存在
$('.one').removeClass('two') // <div class="one"></div> 找到这个类名,把它从class中删掉

jQuery-动画

显示与隐藏效果

显示与隐藏效果
jQuery 给我们封装了很多动画效果,最为常见的如下:
- 显示隐藏:show() / hide() / toggle() ;
- 滑入滑出:slideDown() / slideUp() / slideToggle() ; 
- 淡入淡出:fadeIn() / fadeOut() / fadeToggle() / fadeTo() ; 
- 自定义动画:animate() ;

show显示语法规范

show([speed,[easing],[fn]])
2. 显示参数
(1)参数都可以省略, 无动画直接显示。
(2)speed:三种预定速度之一的字符串(“slow”,“normal”, or “fast”)或表示动画时长的毫秒数值(如:1000)。 (3)easing:(Optional) 用来指定切换效果,默认是“swing”,可用参数“linear”。
(4fn: 回调函数,在动画完成时执行的函数,每个元素执行一次。

$(function () {
$('button').eq(0).click(function () {
    $('div').show()
    })
$('button').eq(1).click(function () {
    $('div').hide()
    })
$('button').eq(2).click(function () {
    $('div').toggle()
    })
})

滑动slideDown slideUp slideToggle

$(function () {
$('button').eq(0).click(function () {
    $('div').slideDown()
    })
$('button').eq(1).click(function () {
    $('div').slideUp()
    })
$('button').eq(2).click(function () {
    $('div').slideToggle()
    })
})

停止动画排队stop

动画或效果队列
动画或者效果一旦触发就会执行,如果多次触发,就造成多个动画或者效果排队执行。
2. 停止排队 stop()
(1)stop() 方法用于停止动画或效果。
(2) 注意: stop() 写到动画或者效果的前面, 相当于停止结束上一次的动画。
$('.nav>li').hover(function () {
    $(this).children('ul').stop().slideToggle()
})

fadeIn fadeOut fadeToggle fadeTo

淡入淡出以及突出显示案例
$(function() {
    $("button").eq(0).click(function() {
        $("div").fadeIn(1000);
    })
    $("button").eq(1).click(function() {
        $("div"). (1000);
    })
    $("button").eq(2).click(function() {
        $("div").fadeToggle(1000);
    });
    $("button").eq(3).click(function() {
        $("div").fadeTo(1000, 0.5);
    });
});

animate动画

自定义动画animate方法
1. 语法 :animate(params,[speed],[easing],[fn])
2. 参数:(1params: 想要更改的样式属性,以对象形式传递,必须写。 属性名可以不用带引号, 如果是复合属性则需要采
取驼峰命名法 borderLeft。其余参数都可以省略
$(function () {
$('button').click(function () {
    $('div').animate({
    top: '300',
    left: 500, //如果是数字,可以不用加引号和px,但是建议加上引号和px单位。
    opactiy: 0.5,//.5不推荐,推荐写0.5
    width: 500,// backgroundColor在jquery中设置是无效的
    })
})
})

手风琴案例

$(function() {
    $(".king li").mouseenter(function() { // 鼠标经过某个小li 有两步操作:
        $(this).stop().animate({
            width: 224   // 1.当前小li 宽度变为 224px, 同时里面的小图片淡出,大图片淡入
        }).find(".small").stop().fadeOut().siblings(".big").stop().fadeIn();
        
        $(this).siblings("li").stop().animate({
            width: 69  // 2.其余兄弟小li宽度变为69px, 小图片淡入, 大图片淡出
        }).find(".small").stop().fadeIn().siblings(".big").stop().fadeOut();
    })
});

jQuery 属性操作

prop()

设置或获取元素固有属性值 prop()
所谓元素固有属性就是元素本身自带的属性,比如 <a> 元素里面的 href ,比如 <input> 元素里面的 type1. 获取属性语法
prop(''属性'')
2. 设置属性语法
prop(''属性'', ''属性值'')

attr()

设置或获取元素自定义属性值 attr()
用户自己给元素添加的属性,我们称为自定义属性。 比如给 div 添加 index =“1”。
1. 获取属性语法
attr(''属性'') // 类似原生 getAttribute()
2. 设置属性语法
attr(''属性'', ''属性值'') // 类似原生 setAttribute()
改方法也可以获取 H5 自定义属性

data()

数据缓存 data()
data() 方法可以在指定的元素上存取数据,并不会修改 DOM 元素结构。一旦页面刷新,之前存放的数据都将被移除。
1. 附加数据语法
data(''name'',''value'') // 向被选元素附加数据 
2. 获取数据语法
date(''name'') // 向被选元素获取数据 
同时,还可以读取 HTML5 自定义属性 data-index ,得到的是数字型

<a href="http://www.itcast.cn" title="都挺好">都挺好</a>
<div index="1" data-index="2">我是div</div>
<span>123</span>

$('a').prop('href', 'http://www.baidu.com')
//<a href="http://www.baidu.com" title="都挺好">都挺好</a> // 设置元素自有属性

$('div').attr('index', '3')
//<div index="3" data-index="2">我是div</div> // 设置元素自定义属性

console.log($('div').data('index')) // 2 获取时可以不用写data-xx,直接index即可
$('span').data('username', 'zs')
console.log($('span').data('username')) // <span>123</span>并未设置到元素上该自定义实行不可见,但是也能设置成功,并打印返回。

jQuery 内容文本值

html()

主要针对元素的内容还有表单的值操作。
1. 普通元素内容 html()( 相当于原生inner HTML)
html() // 获取元素的内容
html(''内容'') // 设置元素的内容

text()

2. 普通元素文本内容 text() (相当与原生 innerText)
text() // 获取元素的文本内容
text(''文本内容'') // 设置元素的文本内容

val()

主要针对元素的内容还有表单的值操作。
3. 表单的值 val()( 相当于原生value)
val() // 获取表单的值
val(''内容'') // 设置表单的值

<div>
    <span>我是内容</span>
</div>
<input type="text" value="请输入内容" />
console.log($('div').html()) // 获取内容包含标签 <span>我是内容</span>
$('div').html('333') //设置内容 <div>333</div>

console.log($('div').text()) // 获取内容       我是内容
$('div').text('666') //设置内容 <div>666</div>

console.log($('input').val()) // 获取内容 请输入内容
$('input').val('888') //设置内容 页面中输入框中的占位语句变成了888,但是实际的dom中还是<input type="text" value="请输入内容" />

parents 返回指定祖先元素

$('div').parents('.yeye') // 拿到祖先元素,爷爷

jQuery 元素操作

主要是遍历、创建、添加、删除元素操作。

$.each()遍历元素

7.1 遍历元素
jQuery 隐式迭代是对同一类元素做了同样的操作。 如果想要给同一类元素做不同操作,就需要用到遍历。
语法2: $.each(object,function (index, element) { xxx; }) 
1. $.each()方法可用于遍历任何对象。主要用于数据处理,比如数组,对象
2. 里面的函数有2个参数: index 是每个元素的索引号; element 遍历内容

// 1:设置每个div和文字颜色,求每个div中文字的求和
$(function () {
var sum = 0
var arr = ['pink', 'deeppink', 'blue']
$('div').each(function (i, ele) {
    console.log(i) // 0  1  2
    console.log(ele) // <div>1</div>···
    sum += parseInt($(ele).text()) // 求和 6
    $(ele).css('color', arr[i]) // 文字 粉 深粉 蓝色
})
console.log(sum)

// 2:遍历数组
$(arr).each(function (i, ele) {
    console.log(i) // 0  1  2
    console.log(ele) //  "pink"  "deeppink"  "blue"
})

// 3:遍历对象 (注意对象的遍历方式和其他的不一致,看代码)
var obj = {
    name: 'zs',
    sayHi: function () {
    console.log('hi')
    },
}
$.each(obj, function (i, ele) {
    console.log(i) // "name" "sayHi" 属性名
    console.log(ele) // "zs"  f() { ··· } 属性值
})
})

$(''
  • '')创建元素

    $(''<li></li>''); 动态的创建了一个 <li>
    

    append prepend 添加元素

    1. append prepend 内部添加 
    element.append(''内容'') 
    把内容放入匹配元素内部最后面,类似原生 appendChild。
    element.prepend(''内容'') 把内容放入匹配元素内部最前面。
    

    after before 外部添加

    2. after before 外部添加
    element.after(''内容'') // 把内容放入目标元素后面
    element.before(''内容'') // 把内容放入目标元素前面 ① 内部添加元素,生成之后,它们是父子关系。
    ② 外部添加元素,生成之后,他们是兄弟关系。
    

    remove empty html 删除元素

    element.remove() // 删除匹配的元素(本身)
    element.empty() // 删除匹配的元素集合中所有的子节点
    element.html('''') // 清空匹配的元素内容
    ① remove 删除元素本身。
    ② empt() 和 html('''') 作用等价,都可以删除元素里面的内容,只不过 html 还可以设置内容。
    
    $(function () {
    var li = $('<li>hello</li>')
    $('ul').append(li) // 在内部,数组后面添加元素
    $('ul').prepend(li) // 在内部,数组前面添加元素
    
    $('ul').before(li) // 在外部前面添加
    $('ul').after(li) //在外部后面添加
    
    $('ul').remove() // 删除内部元素
    $('ul').empty() //清空内部元素
    $('ul').html('')//清空html结构
    })
    

    jQuery 尺寸、位置操作

    jQuery 元素大小

    width() / height()纯宽高

    $(function () {
    1. width() / height() 获取设置元素 widthheight大小
    console.log($('div').width()) // 200纯宽高不包含任何东西
    $('div').width('300px') // 设置元素宽度
    

    innerWidth() / innerHeight() 包含padding

    2. innerWidth() / innerHeight()  获取设置元素 widthheight + padding 大小
    console.log($('div').innerWidth()) // 220 包含padding,不含border
    $('div').innerWidth('300px') // 设置元素宽度
    

    outerWidth() / outerHeight() padding + border

    3. outerWidth()  / outerHeight()  获取设置元素 widthheight + padding + border 大小
    console.log($('div').outerWidth()) // 250 90%包含,只是不包含margin
    

    outerWidth(true) / outerHeight(true) 全包含

    4. outerWidth(true) / outerHeight(true) 获取设置 widthheight + padding + border + margin
    console.log($('div').outerWidth(true)) // 290 全包含,包含了margin
    console.log($('div').outerWidth('300px')) // // 设置元素宽度
    })
    

    web前端 - 系统化知识入门系列一:Es6知识巩固