js第一篇(基础)

JavaScript:依赖HTML的脚本语言(网景公司的Netscape)

script标签:三种写法(行内,内联,外联)

外联后script里面不需要写代码

script可以和style一样放在页面任意位置

初期建议放在/body和/html之间

注释:

//
/**/

输出语句:

  1. 加载至文档流:document.write();
  2. 用户提示:alert();
  3. 删除前的进一步提示:confirm();
  4. 输入框:prompt();
  5. 调试,控制台输出:console.log();

js语法要求:

单双引号尽量保持一种
分号可加可不加,要加都加,要不加都不加

变量:

本质就是存数据的容器—放在内存中

显示声明:var a = 5;

隐式声明:b = 5;

var a= b=c = 5;相当于 var a = 5;b = 5;c = 5;

一次性定义多个变量:var a = 3,b,c,d;

规则:
  1. 变量名不能数字开头,字母数字下划线美元符号组成
  2. 关键字不能作为变量名。



变量类型:

number:

var a = 10;

String:

若干个 任意字符 引号号包含起来

boolean

true,false

undefined未定义类型

var a ;.//undefined

object对象类型

三种表现形式:

数组:

var arr =[1,2,3]

json对象
null关键字

小数问题解决方案

js进行小数计算会精度损失

var a = 0.2,b = 0.1;
var c = a + b ;
console.log(c);//0.30000000000000004

解决方案:

方法一:乘以10除以10

var a = 0.2;
var b = 0.1;
var c = (a*10 + b *10) / 10;
console.log(c);

方法二:强直保留小数点后几位
console.log(c.toFixed(3));



NaN(not a number)

var a = 10;
var b = 'abc';
var c =a -b;//NaN
console.log(c);//NaN

特点:

跟任何数据饭都不相等,包括自己

isNaN():检测一个数字是不是数字//true不是一个数字,false是数字
100a时显示true


字符串类型

单引号和双引号不可以嵌套他们自身

原因:引号虽然是字符,但是有特殊含义

解决:单嵌套双或相反;转义字符

注意:字符串拼接可以用加号

js可以输出标签的,doucment.write("


");

输出字符串长度:str.length

字符串也可以+=

运算符

赋值运算:

= ,+=,-=,…
作用;将右边的值赋给左边的变量

数字运算符

+                -                 *                /                %

字符串拼接:加号两边都是数字才运算



比较运算符

>       <等等

其中 ==是比较值的, ===是先比较类型,再比较值

因为 == 和!=是会自动进行数据类型转换的,转成数字再比较







强制类型转换



转为number:

Number():字符串纯数字才可以转为数字型,不然NaN

布尔true为1,false为0

undefined转数字是NaN

null转数字是0



parseInt();字符串前面的整数获取到

"12.34"==>12

parseFloat()字符串前面的小数获取到

"12.34"==>12.34

转boolean

Boolean(要转换的数据);

会转为false的情况;

NaN,0,’’,undefined,null

转字符串:

String():就是加个引号
数据.toString();
直接加上"";


自动类型转换

  1. 字符串拼接时,一边为字符串,另一边转为字符串

  2. 比较运算时,左右有一个是数字,另一个也会被转为数字比较

  3. 当进行除了加法以外的数学运算,会将两边转为数字再运算


逻辑运算

&& 与
||或
!非
通常连接两个表达式




控制台黑色数字为字符串类型,蓝色数字为数字类型

三元运算符

1 ? 2 :3;
1是正确的执行2,否则执行3
常用于双分支的替代
也可以将整个表达式赋值或者输出

进行数字加法运算的时候一定要检测是不是数字类型

逻辑分支

单分支:

if(条件){满足条件执行}
小括号内自动转换为boolean型


双分支

if(条件){当条件满足执行}else{不满足时执行}


多分支

if (条件) { 代码块 } else if ( 条件 ) { 代码块 } else if ( 条件) { 代码 块 }…else { 代码块 }(最后这个可写可不写)

单个多分支是多选一,多个单分支是多选多

分支语句可以简写



switch多路判断:

类似于多分支,只能判断一个变量跟某些值是否全等

var num =1;
switch(num){//switch小括号里面的值只能是变量
case 1:num ===1;(重点)
执行语句;
break...
default:
执行语句;break}

break是可以省略的,称为case穿透

当num=2:
case 2:	console.log(“hello”)//这里省略break	
case 3:console.log(“hello”);break;//这个就不判断了
当num=3case 3:跳过了case 2;但是倒过来写会执行case 2

注意:

  1. switch的运行效率是高于分支的,因为直接到达符合条件的地方,不需要从上往下判断
  2. 当判断是否相等时更加精确



分支语句的细节

小括号里面的可以放任何值,最终都转为boolean类型

自增自减运算

前缀先运算在操作,后缀先操作再运算

总结:
字符串的比较是逐位比较的,"|10">"2"为false
switch倒着写可以实现累加的效果
剩下的多少秒:秒数%60
剩下小时 = 小时数 %24



循环

目的:处理重复
循环小括号的变量为全局变量

while循环:

var i =15;
while(i > 10){
	i--;
	console.log(i);
}

do-while循环(while循环的变异)

var i = 15;
do{
i--;
}while(i<10);

至少执行一次

for循环

for(var i = 15;i<10;i--){
	console.log(i);
}

var i = 0; 
for(;i<10;i++){
	console.log(a);
}
for (var i = 0; i < 10; i+2){
console.log(i);
}
for (var i = 0;i < 10; salary = salary *0.1 ){
i++;
}
循环跳转:

break:跳出当前循环;
continue:跳出·此次循环,执行下次循环
continue的书写顺序要靠前,放在最后执行了效果等于没执行

循环的嵌套

for循环里面的还可以继续嵌套

DEBUG:









函数:

目的:处理重复
可以重复利用的工具

如何定义函数(%):

语法:function 函数名(){
代码段;
}

函数的定义其实是赋值过程,在内存中开辟fn的空间,fn存放代码

函数的调用:

函数名();//调用函数内部的代码
fn()中fn其实是数据类型(function),里面存放的是function后面的代码

定义一个函数:

function fn(){
	console.log(123);
}

在内存的显示:

f   fn(){
	console.log(123);
}
function 		//返回类型

在这里插入图片描述

形参:形式上的参数

实参:实际意义上的参数,用于给形参赋值,调用时候的小括号内,类型和个数需要和形参相对应



函数的优点:重复执行,模块化编程
函数的书写:先写核心代码,然后用函数包裹起来

匿名函数:

var fn=function(){//定义变量fn,赋值一个函数
	console.log(123);
}
fn();//调用

使用场景:事件中

总结:函数可以没有名字,然后将函数赋值给一个变量----同样能使用

原因:函数的定义过程,其实就是在内存空间中开辟了空间,存放一段代码作为值

fn里面的值:
fn的内容

自调用函数(匿名函数使用小括号包起来):

匿名函数的fn代表的是:

function(){
	console.log(123);
}

那么fn()就是

(function(){
	console.log(123);
})();

也可以写成:

! function(){
	console.log(123);
}();

!可以换成~,能看懂别人这么写就可以

好处是什么?省去了调用

函数提升篇:

代码执行顺序:

从上而下,从左至右,逐字符依次执行。只有有名字的函数才叫函数的定义(打%的地方)。

预解析:

从所有代码中找到变量的定义和函数的定义,找到了就会将变量的定义和函数的定义放到所有代码的最前面,然后再执行。

注意:函数的大括号可以约束声明提升,但是if语句等的大括号不具有约束性

var a = 10;
分为两个步骤:定义a,将a赋值为10



题目检测:

console.log(fn);
fn();
var fn = function(){
	console.log(123);
}

运行结果:
undefined
报错

fun();
var fn = function(){
	console.log("我是fn函数");
}
function fun(){
	console.log("我是fun函数");
}
fn();
fn = 100;
fn();

运行结果
我是fun函数
我是fn函数
报错

fn();
function fn(){
	console.log("我是一个fn函数");
}
fn();
var fn = 100;
fn();

运行结果
我会fn函数
报错

这里预解析的时候函数和变量重名,保留函数

var a= b;
a = 0;
b = 0;
console.log(a);
console.log(b);

直接报错
因为b没被定义就被使用,一定要先定义再使用

var  fun = 200;
fun();
var fun  = function(){
	console.log("我是一个fun函数");
}

直接报错,因为预解析后fun这个空间的值是200,不是函数,无法调用

function fn(a){
	console.log("我是fn函数");
	a();
	functio a(){
		console.log("我是函数a");
	}
}
fn(10);

我是fn函数
我是函数a

注意:形参赋值是在函数提升和参数提升之前的

console.log(num);
if(false){
	var num = 100;
}

undefined

注意:不会执行的代码也是要预解析的

return关键字

让一个函数返回值,后面的语句都不会执行
return只能停止函数,break只能停止循环和switch
函数中的循环可以加return
循环中的函数可以加break;

没有return的函数默认返回undefined


函数的书写步骤

  1. 先写核心代码
  2. 再写上函数外壳
  3. 然后寻找形参,提出来



作用域

能起作用的区域

在不同地方定义的函数和变量,起作用的范围是不同的

不在任何函数内定义的变量称为全局变量

在函数内定义的变量称为局部变量

全局变量在局部范围内有效
局部变量在全局范围内无效

函数定义好了就相当于创建了个作用域,任何函数都可以创建作用域

作用域可以嵌套作用域链





作用域链的使用规则:

赋值:
先从当前作用域查找变量的定义,没有找上一级,直到全局,全局有就赋值给全局变量;全局没有就隐式定义这个变量-----不过不存在提升过程。

运算、比较、输出等操作,先从当前作用域查找变量的定义,没有就杀上一级,直到全局,全局没有就报错,有则使用。


递归函数:

注意内存溢出错误(Maximum call stack size encoded)

先定义一个空函数,然后往空函数里面输入值:

function fn(){
		if(num ==1){
			return 1;
		}
		return num*fn(num-1);
}

注意一定要写return





事件

匿名函数的应用:

目的:

	处理用户在网页上的行为,如点击,右击等

事件三要素:

  1. 事件源:

    能触发某种行为的HTML标签
    
  2. 事件类型:

    拖拽,移动
    
  3. 事件处理程序:

    函数
    

在js中使用标签id代表标签,不要使用常见的关键字(name,start,stop)


语法(事件的定义):

事件源.onclick = function(){
console.log(123);
}

常见的事件类型

事件类型含义
click单击
dblclick双击
mouseover鼠标移入
mouseout鼠标移出
submit事件源form,点击的是submit
常见于表单验证,点击之后,跳转页面
keydown键盘按下,window.onkeydown
keyup键盘抬起,window.onkeyup
focus获得焦点/光标
blur失去焦点
load等页面所有加载完后最后开始加载,window.onload
,可以让script放在任何位置,不用考虑加载顺序问题




注意,知识点来了:事件的函数是由系统来调用的,事件的类型有系统提供的


事件的书写

第一种:

div.onclick = function(){
	console.log(123);
}

第二种;

btn.onclick =fn;
function fn(){
	console.log(123);
}

第三种:行内书写

onclick ="javascript:console.log(123);"//只能写一个语句
onclick=onclick(){} 

js的关键字:

this:在全局中表示window(浏览器窗口),在事件中代表事件源

对象

对象分为数组/json对象/null

json:

定义:

多个数据(键值对)组成的集合
直接定义:

var obj ={
	name:"张三",
	age:12
}

构造函数:

var obj =new Obj({
	name:"张三"
});



对象数组的组成:

键值对形式:

键必须是字符串,在定义的时候可以不加键中包含连字符“-”,那就须要加上引号

值是任意类型(可以是函数)

对象的操作:

增删改查:
操作写法
对象.键 = 值;/对象[“键”] = 值 ;
delete 对象.键/delete 对象[“键”]
存在那个键值对,增的形式就可以修改
console.log(obj.name/obj[“name”])
对象的遍历:

js提供了特殊的for

for(var attr in obj){
obj[attr];
}

attr是键,obj是对象

**注意:**错误写法如下

var a ="name";
obj.a;//这么写是错误的,因为obj里面没有a这个键

正确写法:

var a = "name";
obj[a];

对象的方法

对象的值如果是函数,那么这个键就叫做对象的方法

如果碰到多个键值对,就用对象



构造函数初体验

被用来new创建对象的函数都是构造函数

任意函数都可以new来当构造函数,当一个函数被用来创对象,就可叫构造函数

系统提供了一些构造函数来创建对象

//系统内置的构造方法
var num = new Number(12);
String();
Booelan();
这里的num是对象型,可以参与数学运算并得到结果

原理:js的底层处理任何的数据都是对象处理的,为了让开发者更加接近于正常的理解,js提供了基本数据类型,供开发者使用。

数组

也是多个数据的集合,但是相较于对象,数组在内存是按顺序排列的



数组的定义

一:直接定义

var arr=[1,2,3,4,5];

二:构造方法

var arr =new Array(5);
创建了5个empty
不建议使用

上面两种方式的区别只存在都给里面放个数字

var arr=['a'];
vae arr = new  Array('a');
//这两个是一致的



数组的特性:

数组对象里面有属性length,可通过arr.length获取数组长度

数组第一个下标为0,最后一个下标为arr.length-1

数组的操作

操作写法
arr[i]= [1,2,3]
delete arr[i] 或者arr.length = 0;
arr[i ] =“d”,arr[i]已经存在
arr[i]

数组遍历:

方法一:

var length = arr.length;//因为每次判断都要取值一次,浪费时间
for(var i = 0;i <length;i++){
	console.log(arr[i]);
}

方法二:

for(var i in arr){
	console.log(arr[i]);
}

这个方法是遍历对象的,当然可以遍历数组



二维数组:

数组的元素类型没有限制,所以是数组类型也可以

嵌套两层为二维数组,嵌套三层为多维数组

查看三维数组中的某个元素arr[0][2][1];



建议:数组里面只放一种数据类型,对象里面放多种数据类型

数组的操作方法:

  1. splice(开始位置,删除个数,增加元素)

参数一和参数2必须写,参数三为可选项
最常用,插入删除修改数组
被操作数组被修改

pop():删除最后一个元素
unshifted():开头加上元素
shift():开头减少元素
push():末尾加上一个任意类型元素

  1. concat()数组拼接:

var res =arr1.concat(arr2);
var res1 = arr1.concat(“a”,“b”);//也是拼接在arr1数组末尾
拼接在数组末尾,arr2数组元素拼接进arr1中

  1. 数组的排序sort:

arr.sort(function(a,b){
return b-a;//降序 return a - b;为升序
})

  1. 连接join:

arr.join("-")
按照指定字符拼接成字符串

利用数组写页面


    var arr = [
        {
            name: "手机",
            img: "https://www.baidu.com/img/dong_8ff048ec89a4c8b4d638def4ce4dafda.gif",
            price: 50,
            desc: "真便宜,没好货"
        }
    ]
    document.write("<ul>");
        document.write(" <li><img src="+arr[0].img +" alt=\"\"><p>"+arr[0].name+"</p><span>50</span> <div>"+arr[0].desc+"</div></li>");
        document.write(" <li><img src="+arr[0].img +" alt=\"\"><p>"+arr[0].name+"</p><span>50</span> <div>"+arr[0].desc+"</div></li>");
        document.write(" <li><img src="+arr[0].img +" alt=\"\"><p>"+arr[0].name+"</p><span>50</span> <div>"+arr[0].desc+"</div></li>");
    document.write("</ul>");









基本类型的内存机制:

栈内开辟空间,放入数据,b=a就是将a内存里面的数据复制一份到b

引用类型的内存机制:

数组在栈内开辟空间,将数组内容放在堆内存,栈内存存放数据的地址,b=a赋值的是数组的地址,修改的是堆内存的数组,对a的值也会产生改变

冒泡算法

算法原理:每相邻的两个元素比较大小,不符合规则就交换两个元素的位置

var arr=[1, 5, 3, 7, 6, 14, 9, 1, 4, 8, 2];
var length = arr.length;
for(var i = 0; i<arr.length;i++){
	for(var j = 0;j<length -1;j++){
		if(arr[j]>arr[j+1]){
			var tmp =arr[i];
			arr[j] = arr[j+1];
			arr[j+1] =tmp;
		}
	}
}
console.log(arr);

选择排序

原理:每次选择最小的或最大的值放在合适的位置

var arr = [1, 5, 3, 7, 6, 14, 9, 1, 4, 8, 2];
for(var j = 0; j <arr.length - 1 ; j ++ ){
    var min = arr [j];
    for(var i = j+1 ;i <arr.length; i++ ){
        if(arr[j]> arr[i] ){
            var tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;
        }
    }
}
console.log(arr);

ES5 简单认识

ES5 兼容性最好的版本

ES6也称为ES2005

ES:ECMAScript的简写

严格模式:

“use strict”;

要求:

  1. 不允许隐式定义变量
  2. 不允许普通函数内this代表window
  3. 不允许形参重名(js函数形参重名是可以执行的,但是不建议这么写)

写法:

在script的最前面或者在函数的最上面写上"use strict";

好处:

消除怪异语法,更加规范化
运行效率更高

严格模式也受到作用域限制



数组方法:

  1. indexOf():查第一个值在数组中第一次出现的下标,查不到返回-1
  2. map():将数组的每个值处理,返回新元素组成的新数组
arr.map(function(v,i,a){
	return v*0.3;
})
v:数组元素,i:数组下标;a:数组本身
i,a是可选项
  1. filter方法:
    过滤函数
    满足条件的元素组成新数组返回。
    参数和map一致
爱如如.filter(function(v,i,a){
	return v< 60;
	})

4.reduce方法:归并

arr.reduce(function(v,i,a){
	return v<60;
})

a:第一次值为arr[0],之后是上一次函数的return,没有返回undefined
b:a[次数];

map和filter用的最多


字符串

字符串的比较规则

从左到右逐个字符比较的

字符大小规则遵循ASCII码

数字<大写字母<小写字母

排名越靠前越小(a<z)

字符串的操作

操作形式
str[i]
增删改没有,都会形成新的字符串
遍历字符串

for(var char of String){
console.log(“字符”+char);
}

常见的API

  1. charAt():通过指定的下标获取字符串的字符(极其鸡肋,不要记)
    str.charAt()
    2.charCodeAt():通过指定下标获取字符对应的ASCII码

3.固定写法:String.fromCharCode()-----通过ASCII码返回一个字符

var num= 97var s = String.fromCharCode(num);
console.log(s); 
  1. indexOf()
    查字符在字符串中第一次出现的下标,没有返回-1

  2. lastIndexOf():
    查字符串最后一次出现的下标,返回值为下标或者-1

  3. substr():
    截取字符串,参数一开始截取的下标,参数二截取长度(不写默认截取到尾)

  4. substring():截取字符
    参数一:开始下标
    参数二:结束下标(不写默认到结尾,不包含参数二的)

  5. slice()
    截取字符串,和substring一样的
    截取从左到右,不是从右到左
    开始下标为负数的话,-1表示倒数第一个
    数组里面也有slice方法

  6. split():
    把字符串转成数组(俗称“炸”)
    使用指定的分隔符将字符串分割成很多小字符串,组成数组并返回
    没有参数将整个字符串当做元素放入数组
    split(""):每个字符都当成元素组成新数组

  7. replace():
    替换字符串中的指定内容,只能替换一次,循环才可以替换多次
    str.replace(“html”,“css”);
    var s = str.replace("")

  8. trim()
    去除左右的空格,可分为trimLeft()和trimRight()

toLowerCase();//全部小写
toUpperCase()//全部大写








Math Date

math对象:系统内置的对象

math不像String和Date是对象的类,因此没有构造函数Math(),像Math.sin()这样的函数只是函数,不是某个对象的方法。无需创建,通过把慢作为对象使用就可以调用其所有的属性和方法

格式功能
Math.PI圆周率
Math.round()四舍五入
Math.pow(底数,幂数)次方
Math.random()获取随机数
Math.floor()向下取整
Math.ceil()向上取整
Math.max()最大值
Math.min()最小值
Math.abs()求绝对值

对Math.random()进行封装

function Random(a,b){
	var res = parseInt(Math.random()*(b-a))+a;
	return res;
}

生成一个[a,b)的随机整数


进制转化

除了十进制以外的进制都是字符串形式

10进制转为其他进制:
num.toString(8);//转为八进制
其他进制转为10进制:
var res = parseInt(str,n);
//str为进制字符串,n为str是什么进制的


Date对象

系统提供的构造函数

var date =new Date();
console.log(date);//当前时间

date对象在我们打印日期的时候自动调用toString方法。

格里尼治时间戳:从格林尼治的1970.1.1.0.0.0到现在的毫秒数,就是现在的时间戳

获取:

var date =new Date();

获取什么格式
获取年var year = date.getFullYear()
获取月var month = date.getMonth()
获取日var day = date.getDate()
获取时var hour = date.getHours()
获取分var minute = date.getMinutes()
获取秒var seconds = date.getSeconds()
获取毫秒var milisecond = date.getMiliseconds()
获取时间戳var time = date.getTime()
获取星期几var week = date.getDay()
快速获取时间戳var res =+new Date();

注意:js里面的月份是0~11,输出时需要加1

设置:

get改为set就可以了

星期是不可以设置的

设置时间戳:date.setTiems(0)//格林尼治时间
在线运行js

设置·指定时间的时间戳
var date = new Date(“2020-10-10 11:21:05”);
var date = new Date(1010,10,10,0,0,0);

通过构造方法设置时间戳:
var d = new Date(0);

获取当前代码执行时的时间戳

Data.now()

格式化输出时间日期:
date.toDateString();//只看年月日
date.toLocaleTimeString();//只看时分秒
date.toLocaleString();//都看


BOM(浏览器对象模型)

Browser Object Model

操作浏览器都是使用对象来操作的:window对象(浏览器窗口)

window有子对象,每个子对象都针对着一个操作

js实现跳转的方法

window.open():
window.location.href=“地址”
window.location.assign():
window.location:

window子对象:BOM中的顶级对象

注:window可省略

navigator(获取浏览器信息)

没什么卵用,对于学爬虫的估计有用
window.navigator.appCodeName 浏览器内核名称
window.navigator.appName浏览器名称
window.navigator.appversion:浏览器版本
window.navigator.userAgent:浏览器信息

history历史记录(你打开的网页记录)

前进:
history.back();
后退:
history.forward()
刷新:
history.go();//正数前进,负数后退,0刷新当前页面

location:地址栏

href属性:
location.href是完整的地址栏地址,赋值可以实现跳转

search属性:
获取地址栏数据
location.search
也可以赋值设置,注意是键值对形式

hash属性:
获取地址栏的锚点:
location.hash="#bottom"

页面重定向(跳转方法):
location.assign(“地址”);

新地址替换当前地址:
location.replace();

刷新当前页面:
location.reload();

window弹出方法:

alert();
prompt();
confirm();

注意:
全局变量其实是window的属性,全局函数是window的方法,只不过平时省略了window,全局中的普通函数中的this代表的就是window对象。

window获取浏览器的尺寸

innerWidth/innerHeight 包含滚动条,相当于视窗的宽高(去掉了window)

window事件(重点):

window.onload = function(){
//页面加载完再执行
//放在同步中就是同步加载完的最后,异步中就是异步最后
}

window.onreszize = function(){
//改变窗口大小就执行
}

window.onscroll = function(){
//浏览器滚动条滚动时执行
}

定时器(重点):

分两种:每隔一段时间执行一次和延时一段时间只执行一次

第一种:

var timer =window.setInterval(function(){
console.log("123");
},1000)

清除:

clearInetrval(timer);
//形参是当前页面第几个定时器,一般为定时器返回值或者数字,会执行一次

注意:定时器一定要停,不然内存溢出

之前的内存溢出的情况(死循环,递归函数)



第二种:

window.setTimeout(function{
	console.log(123);
},2000)
//也有返回值,也用来清除,同样代表第几个定时器

清除:clearTimeout();

重点:定时器的返回值

timer这个返回值其实是最后一次点击的定时器的返回值

清除定时器的时候,其实是清除了最后一个定时器,前面几次点击产生的定时器没有清除,也清除不掉了

同步操作和异步操作

同步:
上面的语句执行完,下面才会执行,排队等待



异步:
同时执行(和同步)

运行流程:

  1. js是单线程的(同时只能做一件事)
  2. 当js线程看到异步代码(栈空间),将异步交给浏览器(多线程)
  3. 浏览器等异步操作执行时机,时机成熟放入一各队列等待时机
  4. js线程如果将所有的同步执行完,会从队列中找到需要执行的代码才会执行。

总结:
定时器和延时器不一定精准(因为异步的定时器会受到同步时间的耽误)
所有异步都是在同步执行完之后执行的
异步效率高













DOM操作


dom(document object model)文档对象模型

操作HTML文档 的方法

之前我么使用id来表示这个标签,如:

<div id="box"></div>
box.onclick (function(){
	console.log(123);
}) 


如何获取标签元素

操作写法
使用id名获取document.getElementById(“id名”);
类名获取元素document.getElementsByClassName(“box”);
标签名document.getElementsByTagName(“”);
使用name属性获取document.getElementsByName(“sex”);
CSS选择器获取元素document.querySelector(“选择器”),只能获取满足css选择器的第一个
CSS选择器选择元素的集合var oDiv = Document.querySelectorAll(“li”)

注意:2,5,6条低版本IE不兼容

在编写过程中使用name作为变量名,控制台输出出现异常,不能用name作为变量名


属性操作:

操作写法
元素对象.getAttribute(“属性的键”)
removeAttribute("键”)
有则改,无则增setAttribute(键,值)

特殊的: img.src和input.value

最重要的:input.checked



内容操作


元素.innerText,值为标签内容,设置标签样式是不生效的
元素.innerHTML:标签内容,值为标签生效

特殊情况

表单元素的值:
document.querySelector(“input”).value;


设置样式:

写在行内的style标签里面的

类名操作:

标签.className="";
这么写清空类名

滚动过的距离

垂直滚动document.documentElement.scrollTop
水平滚动document.documentElement.scrollLeft

当文档声明没有时,documentElement换成body

文档声明就是<!DOCTYPE html>

兼容写法

var t = document.documentElement.scrollTop||document.body.scrollTop

立即回到顶部:

	t = 0;(就是设置document.documentElement为0,t只是存变量值的)也可以定时器不断减少慢慢变化

html基本结构获取写法

部位写法
htmldocuemnt.documentElement
bodydocument.body
headdocument.head
titledocument.title









节点

节点:html文档的组成部分




DOM节点分(了解):
元素节点(标签),属性节点(),文本节点(文本内容),注释节点(注释)


注意:
文本节点:标签内的文本和标签之间的换行空格(为什么写移动端最好别换行空格,因为算文本,会被当做文字放大)都算文本节点




获取节点:

上面的getElementById等都是获取节点,但是这里的获取节点是依靠关系,不是直接获取

重点:

获取什么怎么获取
子节点childNodes
子标签children
父节点parentNode
父标签parentElement
第一个节点firstChild
最后一个节点lastChild
子元素中第一个标签firstElementChild
子元素中最后一个标签lastElementChild
获取上一个节点previousSibling
获取下一个节点nextSilbling
获取上一个节点元素previousElementSibling
获取下一个节点元素nextElementSibling
获取所有属性节点atributes



节点属性

都是属性,不是方法

写法作用
nodeType获取节点类型
nodeName获取节点名
nodeValue获取节点值

nodeType返回值:
1表示元素节点;3表示文本节点;8表示注释节点;2表示属性节点

nodeName:
标签节点为标签名的大写形式(DIV),文本节点为(#text),注释节点为(#comment)

nodeValue:
标签为null,文本节点为文本内容,注释节点为注释内容



节点操作

操作写法
删除当前元素元素.remove()
新建元素createElement(“元素名”)
父元素加子节点(追加在子元素最末尾)父元素.appendChild(oDiv)
将子节点插到某个子节点之前父元素.insertBefore(新元素 ,被插队的节点)
替换节点父元素.replace(新节点,旧节点)
删除节点removeChild(被删除的子节点)
复制节点自身元素.cloneNode()

复制节点传参true可以将里面的内容也复制



下面全程高能

获取样式:

var styles = window.getComputedStyle(元素);
styles.属性

低版本IE不兼容

兼容写法

function getStyle(){
	try{
		return window.getComputedStyles(ele[attr]);
	}catch(e){
			return ele.currentStyle[attr];//IE兼容写法
} 
获取元素大小
clientWidth/Heightnumber型,不含边框
offsetHeight/Width含边框

都是只读类型,offsetHeight对于行内一直为0

获取元素的位置
offsetLeft/offsetTop获取到设置过定位父元素的距离{机制和定位机制一样,逐级向上寻找定位元素}
offsetParent获取设置过定位的父元素,最终到body
获取窗口大小:
window.innerHeight/Width含滚动条
document.documentElement.clientWidth/clientHeight不含滚动条



变量定义技巧

一个局部想要使用另一个局部的变量,可以将变量定义在全局


使用自调用函数传参(形成保留作用域)

  for (var i = 0; i < ulis.length; i++) {
                   ( function(i) {
                        ulis[i].onclick = function () {
                            that.className="";
                            that =this;
                            for (var j = 0; j < ulis.length; j++) {
                                ulis[i].className = "";
                            }
                           this.className = "active";
                            for (var j = 0; j < olis.length; j++) {
                                olis[j].className = "";
                            }
                            olis[i].className = "active";
                        }
                    })(i);
                }

下拉框select>option里面的value可以

document.querySelector(“select”).value获取到







事件

为了提高浏览器检索优先级:能不用标题标签就别用

事件:用户的动作(单击,右击等)




下面是事件类型:

鼠标类

右击contextmenu
鼠标按下mousedown
鼠标抬起mouseup
鼠标移入mouseover
鼠标移出mouseout
鼠标滚轮mousewheel(火狐里面用DOMmousescroll)
鼠标单击click
鼠标双击dblclick
鼠标移动mousemove
移入mouseenter
移出mouseleave
document.documentElement.addEventListener('DOMMouseScroll',function(){
  console.log("火狐");
   })



mouseover和mouseenter的区别:

相同点:没有子元素时候行为一致

mouseover用的比较多,mouseenter经常被忘掉

mouseenter不会冒泡,mouseover会

不论鼠标指针穿过被选元bai素或其子元素,都会du触发 mouseover 事件。对应mouseout
只有zhi在鼠标指针穿过被选元dao素时,才会触发 mouseenter 事件。对应mouseleave
这样的话,mouseenter子元素不会反复触发事件,否则在IE中经常有闪烁情况发生。(复制自百度)



键盘类

keypress键盘按下
keydown看英文,不解释
keyup按键抬起(一定要注意执行时机,获取按下那个键的键盘码不能用这个)

区别自己百度,使用最多的是keyup

表单事件

focus光标点进去
blur光标(闪烁的竖杠)丢失就触发该事件
change下拉框改变就触发
input实时监听文本框的内容变化(类似百度的搜索框,IE中是propertychange)
submit给submit标签绑定的(form.submit,必须要结合提交按钮使用)





事件流

事件从开始触发到执行结束的流程(一连串的事情)
捕捉阶段:从文档由外向内找目标元素
目标阶段:找到目标文件,执行文件
冒泡阶段:执行完就要离开

事件外的元素也绑定了事件的话,冒泡阶段由内向外会触发外面的事件

事件侦听器(一个事件绑多个函数)

onClick的缺点:一个元素绑多个onClick会被覆盖

事件侦听器(兼容性):

元素.addEventListener(“click”,function(){
//可以实现多个不覆盖,但是IE不行
})
元素.attachEvent(onclick,function(){

})

function bindEvent(btn,type,handler){
	try{
		btn.addEventListenter("type",handler);
	}catch(e){
		btn.attachEvent(on+"type",handler);
	}
}

第二种:

function bindEvent(btn ,type,hander){
if(btn.addEventListener){
btn.addEventListener(type,hander)	
}else if(btn.attachEvent)){
btn.attachEvent("on"+type,handler)
}else{
        btn["on"+type] = handler
    }
}

第三种:

function bindEvent(btn,type,handler){
    try{
        btn.addEventListener(type,handler)
    }catch(err){
        try{
            btn.attachEvent("on"+type,handler)
        }catch(e){
            btn["on"+type] = handler }}}

访问对象中不存在的属性是undefined

好处:
  1. 同一类型事件可以绑定多次:
  button.addEventListener("click",function(){
        console.log("点击");
    });
    button.addEventListener("click",function(){
        console.log("点击");
    });
    button.addEventListener("click",function(){
        console.log("点击");
    });
  1. 可以指定当前事件在捕获阶段执行
  2. 有第三个参数,代表是否在捕捉阶段执行(默认false表示冒泡阶段执行)
    attachEvent没有第三个参数,因为IE浏览器的事件流,没有捕获阶段



事件解绑

按钮能点击,说明加载到内存中了,所以点击才能生效


点击完后还能点击,希望只执行一次,减少内存负担(所需要解绑)
null为引用类型的空,undefined为基本类型的空
btn.onclick = null;//解绑



事件监听器解绑

前提里面的函数不能是匿名函数了

var fn = function(){
	console.log(123);
}
解绑:
事件源.removeEventListener("click",fn);
事件源.detachEvent("onclick",fn);

解绑又有兼容性问题----封装函数:

	function unbindEvnet(ele,type,handler){
		if(ele.removeEventListener){
			ele.removeEventListener(type,handle)
		}else if(ele.detachEvent){
			ele.detachEvent(“on”+type,handle);
		}else {
			ele[“on”+type] = null;
		}
	}



阻止事件冒泡

事件时有系统调用的,不是我们手动调用的,系统将事件对象放在小括号内,存放和当前事件相关的一系列信息。

small.onclick = function(e)
{
	console.log(e);
	e.stopPropagation();//阻止事件冒泡
}

在IE中的兼容写法
事件对象:window.event
阻止冒泡:e.cancelBubble=true;

事件对象的简单操作

e.type事件类型如“click”等
e.button鼠标按键信息左键是0,右键是2,滚轮是1
e.keyCode键盘码回车13,数字字母遵循ASCII码
e.shiftKey/ctrlKey/altKey组合键true或者false
e.offsetX/Y光标在元素上的坐标位置
e.clientX/Y指光标在浏览器上的位置指视窗距离,不包含滚动过的距离
e.pageX/Y光标在房钱页面上的绝对位置包含滚动过的距离

注意:键盘码低版本火狐不兼容
兼容写法:

var keycode =e.keyCode||e.which



简单的拖拽效果

  var div = document.querySelector("div");
  //拖拽一定先按下鼠标   
  div.style.position="absolute"
  div.style.left="0"
  div.style.top="0"
  
  div.onmousedown = function(e){
    //这里代吗都是在鼠标按下的时候执行的-----按下后再移动鼠标(鼠标移动事件)
    var e = e ||window.event;
    var x = e.offsetX;
    var y =e.offsetY;
    div.onmousemove = function(ev){		//这里写div可以将鼠标甩出来,换成										document,解绑也需要document
        //鼠标移动只会执行这里的代码
        var ev = ev ||window.event;
        var x1 = ev.clientX;
        var y1= ev.clientY;
        var l = x1 - x;
        var t = y1 - y;
        div.style.left=l+"px";
        div.style.top = t+"px";
    }
  }  

只要鼠标在div上,触发onmosemove,外面的onmousedown就不会停止,需要解绑里面的


这时需要解绑:
  div.onmouseup= function(){
      div.onmousemove =null;
  }

存在点击后快速离开,解绑无效果,那么把移动的事件源由div改为document(就算被甩出div范围也依旧在document范围)

拖拽限制

    var div = document.querySelector("div");
    //拖拽先按下鼠标   
    div.style.position = "absolute"
    div.style.left = "0"
    div.style.top = "0"

    div.onmousedown = function (e) {
        //这里代吗都是在鼠标按下的时候执行的-----移动鼠标-----鼠标移动事件
        var e = e || window.event;
        var x = e.offsetX;
        var y = e.offsetY;
        document.onmousemove = function (ev) {
            //鼠标移动只会执行这里的代码
            var ev = ev || window.event;
            var x1 = ev.clientX;
            var y1 = ev.clientY;
            var l = x1 - x;
            var t = y1 - y;
            if (l < 0) {
                l = 0;
            }
            if (t < 0) {
                t = 0;
            }
            if (l > document.documentElement.clientWidth - div.offsetWidth) {
                l = document.documentElement.clientWidth - div.offsetWidth;
            }
            if (t > document.documentElement.clientHeight - div.offsetHeight) {
                t = document.documentElement.clientHeight - div.offsetHeight;
            }
            div.style.left = l + "px";
            div.style.top = t + "px";
        }
    }
    div.onmouseup = function () {
        document.onmousemove = null;
    }

阻止默认行为

链接的跳转,鼠标右键出现的窗口都是默认行为

  1. return false(事件函数最后加上)
  2. e.preventDefaulte          e.returnValue =false(IE中)(利用事件对象来阻止)
  3. 将链接地址改为javascript:;




事件委托

将子元素的事件委托给父元素:例如点击事件,委托后每个子元素都可以有点击

好处:你新增的元素不需要再次单独绑定事件,十分方便

兼容写法:

target = e.target ||e.srcElement;(兼容低版本IE)
target代表的是所有子元素

<ul>
        <li>11111111111</li>
        <li>22222222222</li>
        <li>33333333333</li>
        <span>4444444444</span>
    </ul>
    <button>添加</button>
</body>
<script>
 
    var ul = document.querySelector("ul");
  ul.onclick = function(e){
        var e = e||window.event;
        var target = e.target ||e.srcElement; 
        if(target.nodeName=="LI"){
            target.innerText="修改";//加条件限制target范围
            console.log(target);	
        }
    }

注意点

  1. 拖拽的时候一定是事件嵌套,事件的事件对象是不一样的
  2. mouseover和mouseout是一对,mouseenter和mouseleave是一对,尽量不要混用
  3. 在head里面写script标签,要将代码写在这个事件内部;script在body的底部,就不要加了,加了也没用,还会覆盖前面的
  4. 键盘事件通常是keyup
  5. 获取键盘码时有些特殊键盘码无法显示,大小写有时候会混乱,不要研究为什么

offset的一个坑

没有设置小盒子的时候,光标就是大盒子上的位置,就是offsetX
一旦设置了小盒子的位置,光标立马就会在小盒子上,此时的offset就是光标在小盒子上的位置。

拖拽效果不要使用offsetX/Y

e.clientX/Y都是只读数据





正则表达式

用处:验证字符串,提取满足的字符串,替换字符串

但是还有很多用法,无法说清,不仅仅只是简单地实现表单验证

书写规则:

  1. 创建:
    var reg =new RegExp();
    var reg = /规则/;

  2. 可接受写法
    var reg = /html/;
    var reg =/^html$/;
    var reg = /\w$/;
    var reg =/\d$/;
    var reg =/^\d{5,12}$/;

符号意义
^放在规则前表示必须是这个开头
$放在规则结尾表示必须以这个结尾
{m,n}至少m个,至多n个
{n,}至少n位,多了不限制
{n}必须是n位
\w任意字母数字下划线
\d任意数字
.代表一个字符(注意字符是重点)
\s代表一个空格
[a-z]小写a到小写z,不是固定解法,[a-zA-Z]表示任意一个字母
\u4e00 -\u9fa5汉字,不要记,会查就行
+至少一个
?最少0个,最多1个
*{0,},任意个
()表示包起来的是一个整体,还有个用法是用来捕获变量
手机号:

方式一:

	var str = "28715260980";
	var reg =/^1[3-9][0-9]{9}$/;
	var res= reg.test(str);
	console.log(res);

方式2:

	var str = "28715260980";
    var reg =/^1[3-9]\d{9}$/;
    var res= reg.test(str);
    console.log(res);
qq邮箱
var reg = /^[1-9]\d{4,11}@qq\.com$/;		//.有特殊意义,需要转义
var res = reg.test("1974744790@qq.com");
console.log(res);
网易邮箱
var reg = /^[a-zA-Z]\w{5,17}@(163|162)\.com$/;
var str = "shaoguoqing10@163.com";
console.log(reg.test(str));

注意:空格也算在规则内
QQ邮箱+网易邮箱:
var  reg= /(^[1-9]\d{4,11}@qq\.com$)|(^[a-zA-Z]\w{5,17}@(163|162)\.com$)/;
var str = "1974744790@qq.com";
console.log(reg.test(str));

方法:

test正则方法,验证是否满足规则
search验证是否有满足规则的那一段,有返回下标,没有返回-1
exec正则方法,找到匹配的输出为数组的第一个元素,找不到为null
match字符串方法,没有匹配返回null,和exec没什么区别
replace(reg,“str”)将str里和reg匹配的替换成js,只能替换一次,替换多次/html/g;多次忽略大小写/html/gi;

注意
exec(): 正则方法
在字符串中找到匹配的为输出的数组第一个元素,找不到为null
如果想要具体的某个值,可以给那个值加上(),第二个元素为小括号内的值

文件格式检测:
	var reg = /^\w{1,}\.(jpg|jpeg|bmp)$/
    var str ="1.jpg";
    var res= reg.test(str);
    console.log(res);
字符串首行去空格
	var str="     ab   dc    ";
var reg = /(^\s+)|(\s+$)/g;
var replace  = str.replace(reg,"");
console.log(replace);





ES5,ES6语法

表单验证要么都是失去焦点的验证,要么都是提交按钮的验证,不然冲突,失去焦点优先级高,提交按钮无效。

数组方法

v,i,a形参,名字随便起的,代表数组元素,下标,调用数组,一般第二第三个参数都是省略不写的
foreach()只能遍历,没有返回值
some判断数组中至少有一个满足条件
every判断数组中是否所有元素都满足条件
find()查找数组中第一个满足元素的元素
findIndex()满足条件的下标(用法类似find)

foreach:

arr.forEach(function(v,i,a){
	console.log(v);
})

some:

	var res = (function(v,i,a){
		return v>30;
	})

every:

	var res = arr.every(function(v,i,a){
		return v==60;
	})

find:

	var res = arr.find(function(){
		return v>5;
	})





ES6:



定义变量:

var的特点:能预解析,全局变量属于window


两个关键字定义变量: const,let
特点:不能预解析;不在window上(因为自己的作用域)

let定义的变量,创建了一个作用域

	for(let i = 0; i<3;i++){};
	console.log(i);//报错,表示i未定义	

let定义过的变量,不能重复定义
好处:以前事件外循环参数需要函数传入,现在将循环参数改为let就可传入,因为let创建了个作用域

	var button = document.querySelectorAll("button");
    for (let i = 0; i < button.length; i++) {
        button[i].onclick = function () {
            console.log(i);
        }
    }
function f2(){
 var i = 5;
 for(var i=0;i<=10;i++){
 
 }
 console.log(i); // 11
 
 var j = 5;
 for(let j=0;j<=10;j++){
 
 }
 console.log(j); // 5
 
}
f2();

const:常量,值可被初始化,但不能赋值。也不在window上,也不能预解析,不希望改变的量就用const来定义



箭头函数

形参列表只有一个参数,小括号可以省略
大括号内只有一行代码,省略大括号
若一行代码内只有return关键字,return关键字可以省略

let fn = res=> res;

let fn= function (res){
	return res;
}

函数默认值

function(a,b=10){
console.log(a,b);//b不传值就是10,传值10被覆盖
}
如果a有默认值,不想改变,可以实参传undefined

…运算符

  1. 将多个形参整合成一个数组:
	let fn = (...arr)=>{
		console.log(arr);
	}
	fn(10,20,30);
  1. 将数组拆分成多个值
let fn = (a,b,c)=>a+b+c;
let arr =[1,2,3];
const res = fn(...arr);
console.log(res);
  1. 可以将对象拆分成多个键值对
var ch ={naem:"翠花",age:12}
var zz = {name="李四",age:14,wife:{...ch}}
这里注意加载顺序

总结:实参分解形参合并,对象直接拆

对象

  1. 键与值相同可以只写一个:
var name="张三";
var age = 12;
var obj = {name,age}
  1. 方法也可以简写:
	var ff ={eat:function(){console.log("eat");}};
	改写:	
	var ff = {eat(){console.log("eat")}}
	调用:
	obj.eat();
	
  1. 解构赋值
    快速将对象或者数组中的值赋给多个变量
var name="张三";
var age = 12;
var zs ={
	name,
	age,
	eat(){console.log("吃");},
	sport(){console.log("运动");},
	wife:{name:"翠花",age:12}
}
var {name.age,eat,sport}=zs;
console.log(name,age,eat,sport);

注意变量名和键名需要保持一致

取别名:
var {name:n,age:a,eat:e,sports:s}=zs;
console.log(n,a,e,s);
套娃操作:

var {wife}=zs;
var name={wife};
简化套娃操作:var {wife:{name:n}} = zs;

数组结构:

	var arr = [1,2,3,4];
	var[a,b,c] =arr;
	var [a] =arr;
	//只想获取c
	var [_,_,c]=arr;
	//数组的多重解构(套娃)
	var arr =[
    "马蓉",
    "王宝强",
    [
        "贾乃亮",
        "PGOne",
        "李小璐"
    ]
]
var [_,_,[a]] = arr;

字符串

字符串是不支持多行定义的,使用模板字符串就可以了(反引号)

var name="张三";
var str=`
姓名:${name}
`;
name+str;

字符串方法

返回值是boolean型:
startsWidth:字符串是否以某个文字开头;
字符串是否以某个文字结尾;
includes:判断字符串是否有某个字符(split炸要是成三段就是含有这个字符)

具体查看数据类型:

Object.portotype.toString.call(对象名);



伪数组

是对象,像数组能遍历,但是不能用数组方法

之前getElementByTagNames等获取到的就是。

特点:

  1. 键是数字,有一个键为length,值为元素个数
  2. 数组的length属性颜色淡,但是可以调用
  3. 对象没有length,但是伪数组有
  4. 伪数组的键其实是字符串,也有引号
    arr[“0”];

自创伪数组:

	var weishuzu={
		0:"第一个",
		1:"第二个",
		2:"假设这是极限",
		length:3
  	}
  	for(let  i = 0;i<wieshuzu.length;i++{
		console.log(weishuzu[i]);
	}

伪数组转为数组

var arrv = Array.prototype.slice.call(obj);

伪数组的遍历

for(var i = 0 ; i <obj.length;i++){
console.log(obj[i});
}

函数中的关键字:arguments

function fn(){
console.log(arguments);
}
fn(1,2,3);arguments是存放实参的伪数组





this关键字代表什么

所在范围代表
全局,普通函数window
定时器中window
自调用函数window
对象方法中当前对象
箭头函数自己所处作用域的this
用对象调用的方法this代表这个对象
事件代表事件源

所有用对象调用的方法,this代表这个对象
函数定义不知道this是什么,只有调用的时候才知道。

点击调用函数的时候,相当于调用了document的onclick方法

	for(var i=0;i<imgs.length;i++){
    imgs[i].onclick = function(){
        var path = this.src;		//利用this获取变化的i值
        document.body.style.backgroundImage = 'url('+path+')';
        document.body.style.backgroundRepeat = 'no-repeat';
        document.body.style.backgroundSize = '100% 100%';
        box.style.height = 0;
    }
}

点击跳转至推荐文章




如何改变this

将fn中的this改为arr

1. call方法:被函数调用的方法

fn.call(arr)//相当于函数的调用

本质:调用函数被改成函数.call()
调用call之后函数就被调用了
var obj = {
	fn(a,b){console.log(a,b);}
}
var arr =[1,2,3];
obj.fn.call(arr,1,2);
相当于arr调用了obj里面的fn方法,第一个参数后面的都是obj.fn需要的参数

感觉讲的非常详细,可以点这个链接去看看
undefined+undefined = NaN

apply:

也是调用函数,和call差不多,也能改变this

函数的实参会组成数组传入

    var arr =[1,2,3];
	var obj ={
	    name:"张三",
	    fn(a,b,c){
	        console.log(c)
	    }
	}
	obj.fn.apply(arr,[1,2,3]);

bind:

复制函数,参数相当于复制出函数里面的this
点击跳转至推荐文章

  var obj = {
            name: "张三",
            fn(a,b){
                console.log(this);
                console.log(a+b);
            }
        }
        var arr = [1,2,3]
			//下面都是实现相同功能的不同写法,bind返回的是复制的函数
			
        // obj.fn(1,2)
        // obj.fn.call(arr,1,2)
        // obj.fn.apply(arr,arr)
        //obj.fn.bind(arr,...arr)();

下一篇:DOM高级-运动

注:全篇为个人笔记,仅供参考,如有错误请指出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值