复习javascript入门到精通

javascript历史

作者是布兰登.艾奇,在网景公司任职期间于1995年利用十天时间完成了对javascript程序的设计,最初发布时候叫livescript后更名为javascript

javascript是什么

javascript是最流行的语言之一,是一种运行在客户端(自己的电脑)的脚本语言,现也可以基于nodejs技术进行服务器编程

脚本语言:不需要编译,执行过程中由js引擎逐行进行解释并执行

javascript的主要作用

最初只是为了实现表单数据动态校验

现在作用:网页特效,服务端开发(nodejs),桌面程序(electron),app(cordova),控制硬件(物联网ruff),游戏开发

浏览器如何执行js

浏览器分为俩部分:渲染引擎js引擎
渲染引擎:用来解释html和css俗称内核,比如谷歌的浏览器内核是blink,老版本是webkit
js引擎:也成为js解释器,用来读取网页中的js代码,对其进行后期处理并运行(v8引擎)

js由哪几部分组成

ECMAScript(js语法),DOM(页面文档对象模型),BOM(浏览器对象模型)组成
ECMAScript规定了js的编程语法和基础核心知识,是所有浏览器厂商共同遵守的一个js语法标准

js引入方式

行内js(直接在标签上写入)
可读性差,在编写大量html代码时候不方便阅读,特殊情况下使用

<input type=“button” onclick="alert('123')">

内嵌式js(由script标签包裹)
可以在head标签内部写入但是网页内容必须等待所有的Js代码解析、执行完后才开始呈现,这样会导致网页打开延迟,不利于用户体验,一般为了打开网页时无延迟会放在body标签下

外部js(script标签的src属性引入外部js文件)
美观,html结构跟js逻辑代码分离,也方便复用,适合代码量较大的情况下使用

<script src="top.js"></script>

js代码注释方式

单行注释`//`
多行注释`/*内容*/`
快捷键ctrl+/

js输入输出语句

alert浏览器弹出警示框
console.log浏览器控制台输出信息
prompt浏览器弹出输入框

js变量

什么是变量?

变量就是用于存放数据(存放于内存)的容器,我们通过变量名获取数据,或者修改

声明变量及变量赋值

var age 声明一个名为age的变量
var age =10 给这个变量赋值为10
var mtname = prompt('请输入你的名字')
alert(myname)会弹出用户在输入框内输入的值

var是一个js关键字,用于声明变量(后续es6中还新增let const声明方法)

更新变量

一个变量被重新赋值之后,它原有的值就会被覆盖,变量值以最后一次赋的值为准

声明多个变量

只需要写一个var,用逗号隔开即可

简写:
var a=1,
	b=2,
    c=3

特殊情况

声明不赋值结果为undefined
不声明,不赋值,直接使用会报错
不声明直接赋值使用也可以正常使用(不提倡)

变量命名规范

由字母、数字、下划线、$符号组成,不能以数字开头

不能是关键字和保留字,例如:for,while,this,name
区分大小写 规范
变量名必须有意义
遵守驼峰命名法
建议不要用$作为变量名

变量提升

在js预解析步骤中执行,会把所有的var提升到当前作用域的前面,且只提升变量不提升值

例子:
console.log(num)//undefined
var num = 10

变量提升执行过程则是这样:
var num;
console.log(num)
num = 10

数据类型

为什么需要数据类型

在计算机中,不同的数据所占的空间是不同的,为了便于把数据分成所需内存大小不同的数据,从而充分利用存储空间,所以定义了数据类型

变量的数据类型

变量的数据类型是根据变量的值来判断的,在代码运行时,js引擎会对变量值进行判断,从而确定变量的数据类型

数据类型的分类

主要分为俩大类:基本数据类型(简单数据类型),引用数据类型(复杂数据类型)

基本数据类型如下:
Number数字类型

数字类型中的三个特殊值:infinity无穷大 -infinity无穷小 NaN代表非数值

isNaN用来判断值是不是一个非数字,如果是数字返回false如果不是则返回true

String字符串类型

只要是被引号包裹的都是字符串

字符串转义符
\n换行符;\b空格;\t tab缩进

字符串长度可以用length来查看

字符串拼接使用多个+来拼接,不管什么类型和字符串进行拼接输出结果都会变成字符串
例子:‘12’+12 结果是‘1212’

Boolean布尔类型

有俩个值true和false,如果要相加时,true代表1,fasle代表0

Undefined未定义类型

undefined与字符串相加时会拼接起来,与数字类型的值进行相加时会变成NaN

Null空类型

Null与字符串相加会直接拼接,与数字进行相加结果直接是那个数字

Symbol表示独一无二的值
(symbol是后续es6新增)

引用数据类型如下
Object对象类型
Array数组类型
Function函数类型

检测数据类型

typeof可以用来检测变量的数据类型 typeof(变量)

转换数据类型

转字符串:
第一种变量.toString()
第二种String(变量)
第三种加号拼接字符串(隐式转换)

转数字:
第一种parseInt('字符串')转换成整数值类型
第二种parseFloat('字符串')转换成数字浮点类型78.12
第三种Number(string)强制转为数字类型
第四种隐式转换,通过- * /算数运算将字符串转为数字


转布尔值:
Boolean(1)
代表否定的几个值都会被转为false,例如‘’,0,NaN,null,undefined
其他值都会转换为true

什么是表达式什么是返回值

表达式是由数字运算符变量等能求得数值的组合
返回值是指表达式最后返回的结果

运算符

运算符也被称为操作符,是用于实现赋值,比较和执行算数运算等功能的符号

算数运算符

用于俩个变量间值的运算

  +  -  *  /  %   优先级:先乘除后加减,有小括号先算小括号里面的

取余运算符是为了判断一个数能不能被整除

递增/递减运算符

递增运算符和变量配合使用
前置递增(先自增后返回值)
++num
后置递增(先返回值后自增)
num++

前置运算符和后置运算符单独使用效果是一样的,只有在表达式中运算时才会发挥各自的不同之处

比较运算符

指俩个值之间进行比较所用的运算符,比较完成之后会返回布尔值
>  	<	  >= 	 <=  	==判断值是否相等 	 !=  	===判断值和数据类型是否相等  !==

逻辑运算符

多个条件判断时使用逻辑运算符
&& 与 (条件中只要有一个结果为假,结果就为假)
|| 或 (条件中只要有一个结果为真,结果就为真)
非 (直接否定)

短路运算(逻辑中断)

用通俗的话来将就是短路运算永远只会返回从左往右看能决定表达式真或假的那个表达式

逻辑运算符&&

如果表达式1结果为真,则返回表达式2,如果表达式一为假,则直接返回表达式一

console.log(123 && 456)  结果是456
console.log(0 && 456)      结果是0

逻辑运算符||

如果表达式1结果为真,则返回表达式1,如果表达式一为假,则直接返回表达式二…以此类推

console.log(123||456)结果是123
console.log(0||123||456)  结果是123
console.log(0||''||456)		结果是456
var num=3
console.log(123||num++)
console.log(num)//0
因为逻辑被中断了

赋值运算符

=	   -=		+=		*=		/=
age+=5		等于		age=age+5
...
...

运算符优先级

小括号=>一元运算符(++,--,!)=>算数运算符=>比较运算符=>相等运算符=>逻辑运算符=>赋值运算符=>逗号运算符=>

流程控制

在执行程序时,代码的执行顺序对程序的结果有直接影响,很多时候我们通过控制代码的执行顺序来实现我们想要的功能

流程控制主要有三种结构,分别是顺序结构(默认),分支结构(对条件判断)循环结构,这三种分别代表三种的代码执行顺序

分支结构
if语句语法结构

双分支语句
if(条件表达式){
	如果满足条件执行这里的语句
}else{
	如果不满足则执行这里的语句
}

多分支语句(无限套娃)
if(条件表达式){
	如果满足条件执行这里的语句
}else if(条件表达式){
	如果满足则执行这里的语句,不满足的话继续往下走
}else{
}

三元表达式

由三元运算符组成

条件表达式?表达式1:表达式2
var age = 11
var result = age>18'真的''假的'
console.log(result)

数字补零案例

var time = prompt('请输入一个0-59的数字')
var result = time<10?'0'+time:time
alert(result)

switch语句

多分支语句,可以实现多选一的效果

语法结构:
var 变量 = prompt(

)
switch(变量){
	case value:
			执行语句一
			break;
	case value2:
			执行语句二
			break;
	...
	default:
	执行最后的语句
}

switch语句和if else语句的区别

switch用来判断已知的固定值

if语句用来判断一个范围的值

循环结构

循环的目的:为了简便的重复执行某些语句

循环分为三类**for循环(常用) while循环,do while循环**

for循环

在程序中,一组被重复执行的语句被称为循环体,能否继续执行则是取决于循环语句中的终止条件

for循环语法结构
for(第一步var i = 0(初始化变量),第二步i<=100(条件表达式),第四步执行i++(操作表达式
)){
	第三步执行循环体
}

案例一:根据用户输入的班级人数以及成绩算出总成绩和平均成绩

		var num = prompt('请输入班级人数')
		var sum = 0;
		var avager = 0;
		for(var i =1;i<=num;i++){
			var score = prompt('请输入第'+i+'个学生的成绩')
			sum=sum+=parseFloat(score)
		}
		avager=sum/num
		alert(sum)
		alert(avager)

案例二:控制台输出九九乘法表

		var str = ''
		for(var i = 1;i<=9;i++){
			for(var j = 1;j<=i;j++){
				str +=j+'*'+i+'='+i*j+'\t'
			}
			str =str+'\n'
		}
		console.log(str)

while循环

while循环语法
while(条件表达式){
	循环体
}
	例子:
	var a = 1
	while(a<=100{
	alert("lalal")
	a++
}
执行过程跟for 类似,先判断后执行

do while循环

语法结构
do{
	循环体
}
while(条件表达式)
doc while是先执行一次循环体然后才去判断条件表达式

例子:
var a = 1
do{
	alert("aaaa")
	a++
}
while(a<=100)

continue和break区别

continue关键字用于立即跳出本次循环,继续下一次循环
break是直接跳出整个循环

例子:求1-100以内不能被七整除的整数和
var sum = 0
for(var i= 0;i<=100;i++){
	if(i%7==0){
		continue;
	}
	sum+=i
}
console.log(sum)

数组 Array

数组就是一组数据的集合,是一种可以将多个数据存储在一个变量名下的优雅方式

创建数组方式
使用new创建数组

var arr = new Array();

使用字面量创建数组【常用】

数组内的数据没有数据类型的限制
var arr = [1,'小张',3,4,5]

获取数组元素

通过数组的下标(索引)来获取指定的元素(数组下标从0开始)

var arr = [1,2,3]
arr[1]这里获取到的是数组元素2

遍历数组

length是数组的长度
var arr = [1,2,3]
for(var i = 0;i<arr.length;i++){
	console.log(arr[i])
}

案例一:求数组中元素的和以及平均值

var arr = [1,2,3,4,5]
var sum = 0
var avager = 0
for(var i = 0;i<arr.length;i++){
	sum+=arr[i]
}
avager=sum/arr.length
console.log('和'+sum+'平均值'+avager)

案例二:求出数组中的最大值

var arr = [1,2,3,4,5]
var max = arr[0]
for(var i = 1;i<arr.length;i++){
	if(arr[i]>max){
		max = arr[i]
	}
}
console.log('数组中的最大值是'+max)

案例三:将数组中的每一项分割为字符串

var arr = [1,2,3,4,5]
var str = ''
for(var i = 0;i<arr.length;i++){
	str+=arr[i]+','
}
console.log(str)

数组方法
https://blog.csdn.net/qq_47272950/article/details/119060637

函数

函数就是封装了一段可以多次重复执行的代码块,使用的时候直接调用就行

函数使用分为俩步:声明函数和调用函数
function getSum(num1,num2(形参)){
	return num1+num2
}
//函数调用,我们可以给函数不同的参数来实现不同的效果
console.log(getSum(1,100(实参)))//求出1-100的和
getSum(1,50)//求出1-50的和

函数的参数

参数的目的:在函数内部值不固定,可以通过调用函数来传递不同的值进去

形参:函数定义的时候传递的参数,当时并不知道是什么
实参:函数调用的时候写的实际的参数,实参是传递给形参的

函数返回值

我们的函数只是实现了某个功能,最终的结果需要返回值返回给该函数的调用者,函数如果没有返回值,将会是undefined

函数返回值格式:
function 函数名(){
	return 需要被返回的结果
}
函数调用()

案例一:利用函数返回值实现俩个数中的最大值

function getMax(num1.num2){
	if(num1>num2){
		return num1
	}else{
		return num2
	}
}
getMax(55,66)


三元写法:只需要把判断部分改为这个 return num1>num2?num1:num2

案例二:使用函数求数组中的最大值

function getArrMax(arr){
	var max = arr[0]
	for(var i = 0;i<=arr.length-1;i++){
		if(arr[i]>max){
			max=arr[i]
		}
	}
	return max;
}
var result = getArrMax([5,11,85,65,44,99])
console.log(result)

函数返回值注意事项

return后面的代码不会被执行,且只能返回一个值

return 终止函数
function getSum(num1,num2){
	return num1+num2
	alert('我是不会被执行的')
}
console.log(getSum())

return一个数组中的多个不同运算方式的值

function getSum(num1,num2){
	return [num1+num2,num1-num2,num1*num2,num1/num2]
}
var result = getSum(1,2)
console.log(result)

arguments的使用

arguments其实是当前函数的一个内置对象,arguments对象中存储了传递的所有实参,是一个伪数组(伪数组的特性:不是真正意义上的数组,是7
具有数组的length,元素按下标排列,没有数组的方法pop,push等)

function fn(){
	console.log(arguments)//1,2,3
}
fn(1,2,3)

函数相互调用

function fn1(){
	console.log(111)
	fn2()
	console.log('fn1')
}
function fn2(){
	console.log(222)
	console.log('fn2')
}
打印结果:111222,fn2,fn1

函数的声明方式

1.利用函数关键字自定义函数(命名函数)
function fn(){

}
fn()

2.函数表达式声明(匿名函数)
var fun(变量名) = function(){
	console.log('我是函数表达式')
}
fun()

函数提升

在js预解析步骤中执行,会把所有的函数声明提升到当前作用域的前面,且函数提升优先级要大于变量提升

命名函数提升

命名函数提升,函数不管在哪里调用都会执行
fun()
function fun(){
	console.log(111)
}
命名函数提升执行过程则是
function fun(){
	console.log(111)
}
fun()

匿名函数提升

匿名函数提升如果函数调用在作用域前则不起作用
fn()
var fn = function(){
	console.log(11)
}
匿名函数提升过程是
var fn
fn()
fn = function(){
	console.log(11)
}

作用域

代码名字(变量)在某个范围内起作用和效果就是作用域,目的是为了提高程序的可靠性,减少命名冲突
在es6之前作用域分为全局作用域局部作用域,es6新增块级作用域

全局作用域:

整个script标签,或者是一整个js文件,页面打开时候生成,页面关闭后销毁

局部作用域:

定义一个函数就开辟一个局部作用域,函数执行完之后销毁局部作用域,只能在函数内使用该变量

es6新增块级作用域

用let和const声明会产生一个块级作用域,外层作用域无法获取到内层作用域,非常安全明了。即使外层和内层都使用相同变量名,也都互不干扰。

变量作用域

全局变量指在任何地方都可以使用
局部变量只可以在函数内部使用
块级变量指let声明之前使用变量都是不可用的。语法上有个术语叫“暂时性死区

暂时性死区

let 和 const 声明的变量不存在变量提升,其作用域都是块级作用域,凡是在声明变量之前使用变量就会报错
所以,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”

作用域链

当在一个函数内部声明另一个函数时,就会出现函数嵌套的效果。若需要引入某个变量,首先会在当前作用域中寻找,若未找到,则继续向上一层级的作用域中寻找,直到全局作用域。我们称这种链式的查询关系为作用域链

预解析(结合前面的变量和函数提升的特性)

变量的声明会提前,赋值不提前,会按照顺序来,函数提升则分声明函数的方式来决定怎么提升(命名函数和匿名函数提升)

案例一

var num = 10
fn()
function fn(){
	console.log(num)
	var num = 20
}

执行过程为
function fn(){
	var num;
	console.log(num)
	num = 20
}
var num = 10
fn()
运行结果为undefined

案例二

var a = 10
fn1()
function fn1(){
	var b =9
	console.log(a)
	console.log(b)
	var a = '123'
}
执行过程为
function fn1(){
	var b =9
	var a;
	console.log(a)
	console.log(b)
	a = '123'
}
var a = 10
fn1()
运行结果是undefined和9

案例三

fn()
console.log(c)
console.log(b)
console.log(a)
function fn(){
	var a = b = c = 9
	console.log(a)
	console.log(b)
	console.log(c)
}

执行过程
function fn(){
	var a;
	a = b = c = 9
	相当于var a = 9;b = 9; c = 9,b和c没var声明,当全局变量看
	console.log(a)
	console.log(b)
	console.log(c)
}
fn()
console.log(c)
console.log(b)
console.log(a)
运行结果为:9 9 9 9 9 a is not defined

对象

在js中,对象是一组无序的相关属性方法的集合,所有的事物都是对象,例如字符串,数值,数组函数等

为什么需要对象

保存一个值的时候我们可以用变量,保存多个值可以用数组,如果要保存一个人的信息(姓名,年龄性别等)就需要用对象

创建对象的三种方式

字面量创建:

var obj = {
	name:'小明',
	sex:'男',
	say:function(){
		console.log('你好')
	}
}
{里面包含了对象的属性和方法,多个属性间用,隔开,方法冒号后面跟着匿名函数}
调用对象的某个属性则是使用  对象名.属性名   obj.name或者obj['name']

new创建对象new Object()

var obj = new Object()
通过以下方式对对象进行追加属性和方法
obj.name = 'zyb';
obj.sex = '男';
obj.say = function(){
	console.log('hahah')
}
属性和方法之间用分号隔开

构造函数创建对象

用构造函数创建对象的原因是它可以一次性创建多个对象,前面俩种方法只能一次创建一个对象

语法格式
function 构造函数名(){
	this.属性 =this.方法 = function(){}
}
new 构造函数名()

使用构造函数创建对象可以将多个相同属性和方法当作形参,调用构造函数时候在进行相应的赋值,从而封装起来

function Star(uname,age,sex){
	this.name = uname;
	this.age = age;
	this.sex = sex;
}
var ldh = new Star('刘德华',18,'男')
var zxy = new Star('张学友',20,'男')
var lm = new Star('黎明'177'男')
console.log(ldh.name)


构造函数创建对象注意事项

构造函数名必须大写
构造函数不需要return就能返回结果
调用构造函数必须用new 构造函数名

添加属性和方法前面必须加this
每调用函数就会返回一个对象

构造函数和对象的区别

对象指的是类的实例化,特指某一个
构造函数指的是类,指某一大类

使用构造函数创建对象的方式称为对象的实例化

new构造函数的执行过程

第一步new构造函数调用时是先创建了一个空的对象
第二步this就会指向刚才创建的空对象

第三步执行构造函数里面的代码,给这个空对象添加属性和方法
第四步返回这个对象

遍历对象的方法

for in对对象进行遍历语法格式
for(变量 in 对象){}
var obj = {
	name:"小明",
	sex:"男"
};
for(var k in obj){
	console.log(k)
	直接打印k出现的是属性名
	console.log(obj[k])
	打印obj[k]出现的是对象的属性值
}

内置对象

js中对象分为自定义对象内置对象浏览器对象
内置对象就是js自带的一些对象,这些对象供开发者使用,并提供了一些快速开发的功能

内置对象查询文档1(点我查看详情)
内置对象查询文档2(点我查看详情)

Math对象(点我查看详情)

Math数学对象不是一个构造函数,当我们要使用他的方法时不需要new来调用,而是直接使用里面的属性和方法即可

属性示例
	console.log(Math.PI) 圆周率
方法示例
	查看最大值
	console.log(Math.max(1,99,'zyb',55))
	属性值如果有不是数字类型的结果则会转化为NaN

	Math.min则与max相反
	
	Math.random()随机数
	console.log(Math.random(0,1))
	...
	...
}

随机得到俩个数之间的随机整数

function getRandom(min,max){
	//公式
	return Math.floor(Math.random()*(max-min+1)-min)
}
console.log(getRandom(1,100))

随机周末要干的事情

function getRandom(min,max){
	return Math.floor(Math.random()*(max-min+1)-min)
}
var arr = ['打篮球','看小说','敲代码','听音乐','看书','睡觉','逛街','看电影'];
console.log(arr[getRandom(0,arr.length-1)])

猜随机数大小

function getRandom(min,max){
	//公式
	return Math.floor(Math.random()*(max-min+1)-min)
}
var random = getRandom(1,10)
for(var i = 0;i<=3;i++){
	var number = prompt('猜1-10之间的数字');
	if(i==3&&number!=random){
		alert('不好意思您的机会已经用完')
		break;
	}else if(i==3&&number==random){
		alert('恭喜你猜对了');
		break;
	}else{
		if(number>random){
				alert('你猜大了')
		}else if(number<random){
			alert('你猜小了')
		}else{
			alert('恭喜你猜对了');
			break;
		}	
	}
}

date日期对象

Date()日期对象是一个构造函数,必须使用new 来调用创建我们的日期对象

var date = new Date()
console.log(date)
当前具体日期
var date = new Date(2022,1,1)
console.log(date)
输出的月份比现实要大一月
var date = new Date('2022,1,1')
console.log(date)
字符串类型的输出显示正常

日期对象方法
getFullYear() 获取当前年
getMonth() 获取当前月(0-11)
getDate() 获取当前日期
getDay() 获取星期几(周日0-周六6)
getHours() 获取当前时
getMinutes() 获取当前分
getSeconds() 获取秒

封装年月日星期几

var date = new Date()
var year = date.getFullYear()		//返回年
var month = date.getMonth() + 1		//返回月份(月份要+1)
var dates = date.getDate()			//返回当前日	
var arr = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'];
var day = date.getDay()			//返回星期几的数字(0是日,六是6)
console.log('今天是'+year+'年'+month+'月'+dates+'日'+arr[day])	//字符串拼接显示年月日星期几

封装时分秒

var date = new Date();
console.log(date.getHours())		//返回当前时
console.log(date.getMinutes())		//返回当前分
console.log(date.getSeconds())		//返回当前秒
function getTime(){					//返回拼接补零后的时分秒
	var time = new Date();
	var h = time.getHours();
	h=h<10?'0'+h:h;
	var m = time.getMinutes();
	m=m<10?'0'+m:m;
	var s = time.getSeconds();
	s=s<10?'0'+s:s;
	return h + ':'+m+':'+s;
}
console.log(getTime())

获取时间戳

四种方法
var date = new Date();
console.log(date.getTime())
console.log(date.valueOf())
var date1 = +new Date()//[常用]
console.log(date1)
//h5新增的获得时间戳
console.log(Date.now())

封装倒计时

思路:用将来的时间戳减去现在的时间戳得到的毫秒数在转换为时分秒
function daoJishi(time){
	var nowTime = +new Date()//返回的是当前时间总的毫秒数
	var inputTime = +new Date(time);//返回用户输入的时间总的毫秒数
	var times = (inputTime-nowTime)/1000;//剩余时间总的秒数
	var d = parseInt(times/60/60/24)
	d = d<10?'0'+d:d
	var h =	parseInt(times/60/60%24)
	h = h<10?'0'+h:h
	var m =	parseInt(times/60%60)
	m = m<10?'0'+m:m
	var s =	parseInt(times%60)
	s = s<10?'0'+s:s
	return d+'天'+h+'时'+m+'分'+s+'秒';
}
console.log(daoJishi('2022-2-27 18:00:00'))

数组方法点我查看详情

检查是否是数组

instanceof运算符

var arr=[]
console.log(arr instanceof Array)
返回true或者false

Array.isArray()

ie9以上才支持,h5新增

var arr =[]
console.log(Array.isArray(arr))

数组索引方法
indexOf()

查找数组中选定元素的索引,有的话返回索引,没有返回-1

var arr =['小明','小刚']
console.log(arr.indexOf('小刚'))

lastIndexOf()

查找数组中最后一个索引,有的话返回索引,没有返回-1

封装数组去重

function unique(arr){
	var newArr = [];
	for(var i = 0;i<arr.length;i++){
		if(newArr.indexOf(arr[i])===-1){
			newArr.push(arr[i])
		}
	}
	return newArr
}
var demo = unique(['小刚','小刚'])
console.log(demo)

字符串方法点我查看详情

堆和栈

栈中用来存储简单的数据类型,里面直接开辟一个空间用于存储值,还有就是存放复杂数据类型的内存地址(16进制表示)然后这个地址指向堆内存的数据

堆中用于存储复杂数据类型(一般由程序员分配释放,若程序员不释放,则由垃圾回收机制自动回收)

简单数据类型传参

更改的是值

var a = 10;
a = 20
console.log(a)  //20因为值是存在于占内存中,所以值被覆盖

函数的形参可以看作一个变量,当我们把一个值类型变量作为参数传递给函数的形参时,其实就是把栈内存空间里的值复制了一份给形参,所以在方法内部对形参不论做什么样的更改,外部变量都不会被影响

function fn(a){  //这里的a是10
	a++;   //执行++操作之后
	console.log(a)//最后是11
}
var x = 10;
fn(x)//把x的值复制给了a
console.log(x)//10   不受内部影响

复杂数据类型传参

更改的是内存地址

function Person(name){
	this.name = name
}
function fn(x){
	console.log(x.name)//小刚   这里的x内存地址已经指向了p
	x.name = '小明'			//重新赋值后修改了内存地址
	console.log(x.name)//小明
}
var p = new Person('小刚');
console.log(p.name)//小刚
fn(p)		//函数调用时才执行函数里的打印结果
console.log(p.name)//小明		最后执行这里的时候指针指向的是更改后的小明

DOM

文档对象模型,是Document Object Model的缩写,是W3c组织推荐的处理可扩展性标记语言(html/xhtml的编程接口),通过这些接口我们可以改变页面的内容结构和样式

Dom树
复习javascript入门到精通_第1张图片
获取元素
getElementById('#box') ------------根据id获取元素
getElementByTagName('p') ---------根据标签名获取一组标签
getElementByClassName('.box')—根据类名获取多个标签
querySelector('id/类名/标签')—获取指定选择器的第一个元素
querySelectorAll()----------------------获取指定选择器的所有元素

示例
var nav = document.getElementById('id';

获取特殊元素
document.body 获取body标签
document.documentElement 获取html标签

事件概述

由三部分组成:事件源(事件被触发的对象)事件类型(事件如何触发)事件处理程序(通过函数赋值的方式)

<p id='box'>按钮</p> 
var btn = document.getElementById('#box')
btn.onclick = function(){
	alert('lll')
}

事件执行流程

1.获取事件源
2.绑定事件
3.添加事件处理程序(函数)

鼠标事件【点我查看常用事件】

修改元素内容

innerText更改只包含文本,不保留空格和换行

<p>111</p>
p.innerText = '更改后的内容'

innerHtml更改包含文本以及标签且保留空格和换行

<p>111</p>
p.innerHtml = '啦啦啦啦'

src更改图片路径

<img src='路径1' id='img1'/>
var img = document.getElementById('#img1');
img.onclick = function(){
	img.src = '路径2'
}

还有href,title,alt等都可以进行修改操作

小练习,根据不同时间段用户点进来显示的内容和图片不一样

修改表单元素

.value更改表单的值内容

<input type='text' value='请输入内容'/>
获取元素
变量.onclick = function(){变量.value='更改后的内容'}

disabled禁用按钮(true是禁用,false非禁用)
type表单类型

小例子:模仿腾讯登录时输入密码后点击小眼睛显示密码原理

首先设置一个开关 flag = 0
判断开关等于0时,将密码框的类型更改为text,否则type为password
btn.onclick = function(){input.type = 'text'}
点击小眼睛时候更改密码框的type类型为text

修改样式

通过.style修改的样式权重比较高,产生的是行内样式(如果要更改的样式比较多,这种方式写会比较繁琐)

首先获取元素
然后给元素绑定触发事件
最后执行操作
this.style.backgroundColor='red'
this.style.color='red'
this.style.fontSize='200'
js采用驼峰命名法,处理background-color等一类的属性

通过类名className进行修改,不用写多个this.style…,但是如果有多个类名则会覆盖掉之前的

html
<p class='change'></p>
css中
.change{background-color:red;color:red;font-size:200px;}
js中
获取元素
绑定触发事件
执行操作
this.className = 'change'

小例子:练习获取焦点与失去焦点

	<input type='text' value='请输入内容' id='inpt'/>
	var inpt = document.getElementById('inpt');
		inpt.onfocus = function(){
			if(this.value=='请输入内容'){
				inpt.value=''
			}
			this.style.color='black'
		}
		inpt.onblur=function(){
			if(this.value==''){
				this.value='请输入内容'
			}
			this.style.color='gray'
		}

小例子:js获取多个按钮。点击单个按钮更改样式(百度换肤)

思路一:排他思想
获取一组按钮元素
for(var i=0;i<btns.length;i++){
	btns[i].onclick=function(){
	for(var j =0;j<btns.length;j++){
		btns[i].style.background=''
	}
	this.style.background='red'
	}
}

思路二:
通过获取焦点失去焦点来操作一组元素,当触发单个元素后,当前元素进行更改

小例子:表单的全选和取消全选

html布局省略
第一步获取全选按钮,并赋值给`tabAll`变量
第二步获取下面所有复选框的父级
第三步通过父级获取下面所有的复选框,并赋给`tabs`变量
第四步实现基本的全选取消全选功能
tabAll.onclick=function(){
	console.log(this.checked)拿到选中状态
	for(var i =0;i<tabs.length;i++){遍历下面的复选框
		tabs[i].checked = this.checked	更改选中状态
	}
}
上面基本功能已经实现
下面完善第五步:当下面的复选框有一个未选中时,上面全选按钮则也未选中

for(var i =0;i<tabs.length;i++){
	tabs[i].onclick = function(){
	var flag=true;
		for(var i =0;i<tabs.length;i++){
			if(!tabs[i].checked){
				flag = false;
				//break;
			}
		}
		tabAll.checked = flag
	}
}

获取自定义属性以及更改自定义属性

获取属性
console.log(div.id)
获取自定义属性
console.log(div.getAttribute('属性'))
更改自定义属性
setAttribute

ht新增自定义属性

目的是为了保存使用数据,有些数据可以保存到页面中不必要保存到数据库中,h5规定自定义属性data-开头并且赋值

<div data-index='2'></div>
获取自定义属性
console.log(div.getAttribute('data-index'))

节点操作

事件高级

俩种注册事件方式

传统的注册事件的方式有唯一性,同一个元素只能设置一个处理函数,后面的函数会覆盖掉前面的函数

addEventListener事件监听方式

ie9以上才支持

可选参数

type: 事件类型参数(例如click,nouseover,注意都不带on)
listener:事件处理函数,事件发生时会调用该监听函数

使用他可以对同一个元素绑定多个事件

btn.addEventListener('click',function(){
	console.log(11)
})
btn.addEventListener('click',function(){
	console.log(22)
})

解绑事件(删除事件)

传统方式

<div id='box'></div>
获取元素并赋值给变量box
box.onclick=function(){
	alert(11)
	box.onclick=null
}

removeEventListener解绑事件

<div id='box'></div>
获取元素并赋值给变量box
box.addEventListener('click',fn)
function fn(){
	alert(111)
	box.removeEventListener('click',fn)
}

Dom事件流

分为三大阶段:捕获阶段处于目标阶段冒泡阶段

捕获阶段:从window对象依次向下传播,到目标节点即为捕获阶段。捕获阶段不会响应任何事件

目标阶段:在目标节点触发事件,即为目标阶段

冒泡阶段:从目标阶段依次向上传播,到达window对象,即为冒泡阶段

事件对象

event就是一个事件对象,写到函数的小括号里,当形参来看,事件对象是我们事件一系列相关数据的集合

获取元素
div.onclick=functon(event){
	console.log(event)
}
简写event为e

事件对象常用的属性和方法

e.target				返回触发事件的对象
e.secElement			返回触发事件的对象  ie678使用
e.type					返回触发事件的类型
e.preventDefault()		该方法阻止默认事件			ie678使用e.returnValue
e.stopPropagation()		该方法阻止冒泡

事件委托

原理:利用事件冒泡原理,将子节点的事件绑定到父节点上去执行,优化了性能

鼠标事件点我查看详情

mouseenter事件跟mouseover的区别

当鼠标移动到元素上就触发mouseenter,移动到该元素的子元素上不触发,mouseover移动到该元素的子元素上也会被触发

contextmenu控制鼠标右键何时显示菜单

禁止鼠标右键菜单
document.addEventListener('contextmenu',function(e){
	e.preventDefault()
})

selectstart开始选中

禁止鼠标选中文字
document.addEventListener('selectstart',function(e){
	e.preventDefault()
})

小例子:让div跟随鼠标移动

css中设置绝对定位给一个初始位置,300,高200
html省略
js部分
	var pic = document.querySelector('div');
	document.addEventListener('mousemove',function(e){
		var x = e.pageX;
		var y = e.pageY;
		console.log(x,y);
		pic.style.left = x-150+'px'; //减去一半宽取中心点
		pic.style.top = y-100+'px'
	})

键盘事件

onkeyup和onkeydown不区分大小写,onkeypress区分

onkeyup 				当键盘被松开时触发
onkeydown				当键盘被按下时触发
onkeypress 				当键盘被按下时触发(不识别功能键,shift,ctrl等)

优先级高-低:keydown – keypress --keyup

键盘事件对象

keyCode		返回该键位的ASCII码值				替用code
document.addEventListener('keyup',function(e){
	console.log(e.keyCode)
})

小例子:当用户按下s键时,焦点聚焦到搜索框内

var search = document.querySelector('input');
	document.addEventListener('keyup',function(e){
		if(e.keyCode==83){
			search.focus()
		}
	})

BOM浏览器对象模型

bom是浏览器对象模型,他提供了与浏览器交互的对象,核心是window,定义在全局的变量和方法都会成为winow对象的属性和方法

BOM的构成

bom比dom大,bom包含dom

Dom(window)下面还有document,location,navigation,screen,history

window对象的常见事件

窗口加载事件

window.onload是窗口(页面)加载事件,当文档内容全部加载完成之后才会触发该事件

传统方式

window.onload=function(){
	只能写一个,如果写了多个则以最后一个window.onload为准
}

新方式`

window.addEventListener('load',function(){
	没有限制可以写多个
})

ie9以上支持(如果图片较多的情况下,使用这个可以不等图片全部加载完成就执行)

window.addEventListener('DOMContentLoaded',function(){
	当dom加载完成就执行,不等待样式,图片,flash动画等
})

调整窗口大小事件(css3中@mideo没出来前这么使用)

window.onresize = function(){}
window.addEventListener('resize',function(){
	console.log(改变了)
})

定时器

setTimeout()

该定时器在定时到期后执行函数(时间到了执行完之后就不会重复调用了)

单位是毫秒,默认是0
默认写法
	setTimeout(function(){},1000)

回调写法
	function callback(){
		console.log(执行)
	}
	var timer = setTimeout(callback,2000)
	var timer1 = setTimeout(callback,5000)
清除定时器
	clearTimeout(timer)

setInterval()

重复调用函数,每隔这个时间就去调用一次(重复执行,不清除定时器则永不停歇)

```csharp
单位是毫秒,默认是0
	setInterval(function(){},1000)
 	clearInterval()清除定时器

小例子:倒计时

<p id="time">60</p>
	var time = 60;
	var interval = setInterval(function  () {
	document.getElementById("time").innerHTML=time;
	time-=1;
	if(time==-1){
		clearInterval(interval)
		document.getElementById("time").innerHTML="倒计时结束"
	}
	},1000)

this指向

在全局作用域名下this指向全局对象window(定时器 里面的this也指向window)
函数方法中谁调用他this就指向谁
构造函数中this指向构造函数的实例

同步和异步

js最大的特点就是单线程,同一时间只能做一件事
单线程就意味着,所有的任务都需要排队,前一个任务结束后一个任务才能执行,导致了页面渲染不连贯,加载阻塞的问题,为了解决这个问题,js出现了同步和异步的概念

console.log(1);
setTimeout(function(){
	console.log(3)
},0);
console.log(2)
执行结果是123
因为定时器(click等onload等,promise)是异步任务,同步先执行完才去执行异步任务

同步任务放在主线程去执行,形成了一个执行栈,遇到异步任务则放入任务队列中,等主进程的同步任务执行完之后才来执行任务队列的异步任务

location对象
组成部分:

protocol 	通信协议,常用的http,ftp等

host		主机(域名)

port		端口号	http默认是80

path		路径	由零个或者多个/符号隔开的字符串

query		参数	以键值对的形式,通过&隔开

fragment	片段

location的属性

location.href		获取或设置整个url

location.host		返回主机(域名)

location.port		返回端口号

location.pathname	返回路径

location.search		返回参数

location.hash		返回片段

小例子:点击按钮五秒之后跳转页面

获取倒计时元素p
var p =document.querySelector('p');
	var timer = 4
	setInterval(function(){
		if(timer==0){
			location.href = 'http://baidu.com';
		}else{
			p.innerHTML = '您将在'+timer+'秒后进行页面跳转';
			timer--
		}
	},1000)

location对象的方法

location.assign()		跟href一样,可以跳转页面(也称为重定向页面)

location.replace()		替换当前页面,因为不记录历史,所以不能后退

location.reload()		重新加载当前页面,相当于刷新页面(如果参数为true则强制刷新)

navigator对象

它包含有关浏览器的信息,内含浏览器的很多属性

history对象

back()			可以后退功能

forward()		前进功能

go(参数)		前进后退功能,参数是1则前进一个页面,如果是-1则后退一个页面

元素偏移量offset

使用offset可以动态的获得到元素的位置(偏移量),返回的数值都不带单位

作用:获得元素距离父元素的位置,获得元素自身的大小(宽高)

offset属性

元素.offsetParent		返回该元素的带有定位的父级元素,如果父级都没定位则返回body

元素.offsetTop			返回元素距离父级上方的偏移量

元素.offsetLeft			返回元素距离父级左边的偏移量

元素.offsetWidth		返回自身包含padding,边框,内容区的宽度

元素.offsetHeight		与offsetWidth相反

offset和style的区别

1. offset可以得到任意样式表的样式值,style只能得到行内样式的样式值
2. offset系列包含的数值是没有单位的,style获得的值是带单位的
3. offsetWidth等属性是只读属性,不可修改的,style.width等属性是可读写的,可以赋值
4. offsetWidth包含padding+border+width,style.width获得到的是不包含padding+border的值
所以要获取元素的位置大小用offset,要给元素进行改值,则用style

仿京东放大镜效果

元素可视区client
属性:

元素.clientTop		返回元素上边框的大小

元素.clientLeft		返回元素左边框的大小

元素.clientWidth	返回自身包含padding的宽度,不包含border

元素.clientHeight	跟上面相反

元素滚动scroll
属性:

元素.scrollTop		返回被卷去的上方的距离  不带单位

元素.scrollLeft		返回左侧

元素.scrollWidth	返回自身实际的高度,不包含border

元素.scrollHeight	跟上面相反

简单的封装一个运动框架

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<style type="text/css">
		p{
			width: 300px;height: 300px;background: red;position: absolute;left: 0;
		}
		div{
			width: 300px;height: 300px;background: blue;position: absolute;left: 0;top: 500px;
		}
	</style>
	<body>
		<p >p</p>
		 <div >
		 	div
		 </div>
		 <button type="button">点击</button>
	</body>
	<script>
		//obj目标对象		target目标位置		time到目标的时间
		function animate(obj,target,time){
			// 当我们不断地点击按钮,元素速度会越来越快,因为开启了太多定时器
			// 解决办法:先清除上一个定时器,只保留当前的一个定时器执行
			clearInterval(obj.timer)
			obj.timer = setInterval(function(){
				if(obj.offsetLeft>=target){
					clearInterval(obj.timer)
				}else{
					obj.style.left = obj.offsetLeft+1+'px'
				}
			},time)
		}
		var p = document.querySelector('p');
		var div = document.querySelector('div');
		var btn = document.querySelector('button')
		animate(p,300,16)
		btn.addEventListener('click',function(){
			animate(div,100,30)
		})
	</script>
</html>

你可能感兴趣的:(js相关,javascript,前端,开发语言)