JS
JS
JS的组成:
ECMAScript 基本语法、DOM文档对象模型、BOM浏览器对象模型
JS有三种书写位置:行内(body元素内)、内嵌式(head中)、外部式
行内:例:
<body>
<input type="button" value="唐伯虎" onclick="alert('秋香')">
</body>
外部:引入<script src='my.js'></script>
html中推荐使用双引号,js中使用单引号
JS注释
//单行注释 CTRL+/
/多行注释/ shift+alt+a 也可使用CTRL+/
JS输入输出语句
alert(“返回结果”);浏览器弹出警示框 输出的
输入框prompt(“请输入”);
console.log(“我是程序员能看见的”)控制台输出 给程序员测试用的
变量
变量的本质是在内存中申请的一块用来存储数据的空间
变量的使用
声明变量+赋值
- 声明变量var age; var关键字声明 后加变量名
- 赋值 age=10;
变量的初始化:var age =10;
var myname=prompt(‘请输入你的名字’);
alert(myname)
更新变量 重新赋值
一次声明多个变量:var age=18,name=‘zhangsan’,sex=‘nan’; 用英文逗号隔开
特殊情况
只声明不赋值,为undefined
不声明不赋值直接使用,报错,not defined
不声明直接赋值使用qq=110;不报错,可以使用,和python类似
数据类型
变量的数据类型是可以变化的
数据类型分类
简单数据类型:Number Boolean String Undefined Null
Number.MAX_VALUE MIN_VALUE最大最小值
三个特殊值:Infinity(无穷大) NaN非数值
isNaN()用来判断是否为数字 是数字返回false
字符串型String引号外单内双
获取长度:str.length
字符串拼接:字符串+任意类型=新字符串 数值相加,字符相连
变量是不能加引号的
Boolean true和false 布尔型和数字型相加时,true为1 ,false为0
变量为赋值,为undefined型 var a= undefined; 可以这样定义 和数值型相加为NaN
null 可以定义 var a null;和数字型相加为另一个数字
typeof 变量;检测数据类型 typeof a;
prompt()获得的是字符型的数据类型
字面量一个固定值的表示法
数据类型的转换
转为字符型三种方法:
- toString() num.toString();
- String() String(num);
- +号拼接 num+’ ';
转为数字型:
- parseInt(string) 取整数,去小数点,去单位
- parseFloat(string) 也可以去单位
- Number(string) 强制转换
- 利用计算隐式转换(- * / ) ‘string’-0; ‘123’-‘120’;
转为布尔型
Boolean()函数
0、NaN、null、undefined、’ '转为false 其他全转为true
编译和解释语言的区别
编译完才执行
边解释边执行
运算符
算数运算符
表达式和返回值
递增运算符(和变量配合)
++num;(前置递增)(age=age+1)先+1后返回值
num++;(后置递增(age=age+1) 先返回原值再+1
比较运算符(关系运算符)
<
>=
>
<=
== “18”==18 true 默认转换数据类型再比较 只要求值
=== ‘18’===18 要求两侧值数据类型完全一致才可以true
!==
逻辑运算符(布尔运算符)
与&&
或||
非!
短路运算 (逻辑中断):
当有多个表达式值时,左边表达式值可以确定结果时,就不再运算右边表达式值。
逻辑与:若表达式1为真,则返回表达式二;若表达式1为假,返回表达式1
若有空或否定为假,其他为真
逻辑或:若表达式1结果为真,返回表达式1,若表达式1结果为假,则返回表达式2
赋值运算符
+=;-=;*=;/=;%=;
运算符优先级
小括号>一元运算符(++,–,!)>算数运算符>关系》相等》逻辑(先与后或)》赋值》逗号
流程控制
分支结构
if语句
语法:if(条件表达式){执行语句}
if else语句
语法:
if(条件表达式){
执行语句1
} else{
执行语句2
}
if else if 语句
语法:
if(条件表达式){
语句1
}else if(条件表达式){
语句2
}else if(条件表达式){
语句3
}else{
语句四
}
三元表达式
?:
语法 条件表达式?表达式1:表达式2
若条件表达式结果为真返回表达式1结果,否则返回表达式2 的值
switch语句
语法结构
switch(表达式){
case value1:
执行语句1;
break;
case value2:
执行语句2;
break;
default:
最后语句;
}
switch和if else区别
固定值用switch 范围用if
循环结构
for 循环
语法结构:
for(初始化变量;条件表达式;操作表达式){
循环体
}
调试;sources 前面可以设置断点
while循环
语法
while(条件表达式){
循环体
}
do while循环
语法结构
do{
循环体
}while(条件表达式)
条件不满足时退出循环
continue关键字
跳出本次循环,其他循环继续
break关键字
跳出整个循环
数组
数组;一组数据的集合,存储在单个变量下
创建数组
- 利用new关键字创建
var 数组名=new Array(); - 利用数组字面量创建数组
var 数组名=[2,‘pink’]; 可以放任意数据类型,用逗号分隔
获取数组元素
索引(下标):从0开始
语法: 数组名[2]
var y=myCars.indexOf(“Volvo”) // “Volvo” 值的索引值
遍历数组
for循环 数组长度 arr.length
for(var i=0;i<arr.length;i++)
数组新增元素
- 通过修改length长度
arr.length=5;手动修改数组长度 扩充的元素为undefined - 索引号赋值
arr[3]=‘pink’; - 修改数组元素
arr[2]=0;
不要直接给数组名赋值,否则之前的元素都没有了
删除数组元素
删除指定元素 for循环加if语句
反转数组
for(var i=arr.length-1;i>=0;i--){
newarr[newarr.length]=arr[i];
}
数组排序——冒泡排序
//外层循环管趟数
for(var i=0;i<=元素数-1;i++){
//内层循环 每一趟交换次数 arr.length-i-1
for(var j=0;j<=arr.length-i-1;j++){
//内部交换变量对的值
if(arr[j]>arr[j+1]){
var temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
函数
函数的使用
声明函数+调用函数m
function 函数名(){
函数体
}
调用:函数名();
函数参数
声明:function(形参1,形参2……){
函数体
}
调用:函数名(实参1,实参2……);
实参是传递,形参是接收(相当于变量)
函数形参与实参的匹配问题
若实参个数多于形参个数,取形参个数
若实参个数小于形参个数 形参看作未申明的变量 多的形参为undefined
函数的返回值
return语句:return 返回的结果;只能返回一个值,返回的结果是最后一个值;
return终止函数:return之后语句不会执行
函数没有return返回undefined
return也可退出循环
arguments的使用
arguements是当前函数的一个内置对象 存储传递过来的实参 可以不定义形参
伪数组:
- 具有数组的length属性
- 按照索引方式进行存储
- 没有真正数组的方法
可以按数组方式进行遍历arguments
应用:利用函数求任意个数的最大值
函数的两种声明方式
- 函数关键字声明(命名函数)
function 函数名(){表达式} - 函数表达式声明 (匿名函数)
var 变量名=function(){表达式}
调用 变量名();
JS作用域
作用域:代码名在某个范围内起效果
js的作用域(es6):全局作用域、局部作用域
全局作用域:整个script标签 或是单独的js文件
局部作用域(函数作用域):在函数内部就是局部作用域
变量的作用域
全局变量:全局作用域下的变量
var num=10; num为一个全局变量
如果在函数内部没有声明,直接赋值的变量也属于全局变量
局部变量:函数内部的变量,函数形参也为局部变量
全局变量只有浏览器关闭时才会销毁,比较占内存
局部变量当程序关闭就会销毁
js没有块级作用域:{},es6新增块级作用域
作用域链
函数内部有一个函数:内部函数可以访问外部函数的变量,
作用域链:链式查找,找上一级(就近原则)
两个重要的 JavaScript 关键字
let 和 const。
使用 var 关键字声明的变量不具备块级作用域的特性,它在 {} 外依然能被访问到。
let 声明的变量只在 let 命令所在的代码块 {} 内有效,在 {} 之外不能访问。let 声明的变量不会在作用域中被提升
const 声明一个只读的常量,一旦声明,常量的值就不能改变。
预解析
js引擎运行js分为两步:预解析和代码执行
预解析:js引擎会把js里面所有的var和function提升到当前作用域最前面
预解析分为变量预解析(变量提升)和函数预解析(函数提升)
变量提升:把所有变量声明提升到当前作用域最前面,不提升赋值操作
例1:
console.log(num);
var num=10;
相当于以下代码:
var num;
console.log(num);
num=10;
例2:
fun();
var fun=function(){
console.log(22);
}
相当于以下代码:
var fun();
fun();
fun=function(){}
函数关键字声明可以提升到最前面
JS类
类声明:
语法:
class ClassName {
constructor() { … }
method_1() { … }
method_2() { … }
method_3() { … }
}
例:
class Rectangle {
// constructor
constructor(height, width) {
this.height = height;
this.width = width;
}
// Getter
get area() {
return this.calcArea()
}
// Method
calcArea() {
return this.height * this.width;
}
}
类声明不会提升
匿名类和命名类
/ 未命名/匿名类
let Rectangle = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
console.log(Rectangle.name);
// output: "Rectangle"
// 命名类
let Rectangle = class Rectangle2 {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
console.log(Rectangle.name);
JS 对象
对象是一组无序的相关属性和方法的集合,所有事物都是对象,字符串、数值、数组(万物皆对象)
对象由属性和方法组成
属性:特征
方法:行为
创建对象(object)
- 用字面量创建对象{}
var obj={};创建了一个空对象
创建方法属性对象:键值对形式 键:属性名,值:属性值 多个属性方法之间用逗号隔开,最后一个可以不用逗号,方法冒号跟的是一个匿名函数
var obj={
uname:"jane",
age:18,
sex:'male',
sayHi:function(){}
}
- 利用new Object创建
var obj=new Object();
增加属性和方法—等号赋值方法
obj.uname=‘jane’;
obj.age=18;
obj.sayHi=function(){} - 构造函数创建对象
将对象里面一些相同的属性和方法抽象出来封装
语法:
function 构造函数名(){
this.属性=值;
this.方法=function(){}
}
new 构造函数名(); 创建一个对象
例:
// 构造函数名首字母要大写
function Star(uname,age,sex){
this.name=uname;
this.age=age;
this.sex=sex;
this.sing=function(song){}
}
//构造函数不需要return就可以返回结果
var ldh=new Star('刘德华',18,'male');
new 关键字执行过程
new创建一个空对象
this指向创建的空对象
执行构造函数中的代码,添加属性和方法
返回这个新对象
构造函数类似于python中的类,构造函数创建对象也称为对象实例化
调用对象属性
- 采取对象名.属性名;
- 对象名[‘属性名’]
调用对象方法
对象名.方法名();记得添加小括号
区别
变量:单独声明并赋值,单独存在
属性:在对象里面,不需要声明
函数:单独声明 调用:函数名(); 单独存在
方法:对象里面,调用时:对象.方法
遍历对象
新的for循环 for in
语法:for(变量 in 对象){}
for (var k in obj){} k 输出属性名 obj[k] 输出属性值
内置对象
js对象有三种:自定义对象、内置对象、浏览器对象
内置对象:js自带的一些对象,提供一些常用的属性和方法
查阅文档mdn
Math对象
Math不是一个构造器,所以无需new,直接使用属性方法就可以
Math.max()
Math.min()
Math.abs(‘-1’) 会把数据类型转为数字型
Math.abs(‘pink’) 返回NaN
三个取整方法:
Math.floor()向下取整 往小了的取 小数点去掉
Math.ceil() 往大取,进一
Math.round()四舍五入 1.5 -2 五舍六入负数
Math.round(-1.5) 结果为-1 (.5往大的取)
Math.random() 返回一个随机小数【0,1)里面不跟参数
返回两个数之间随机整数,并且两端包含
function getRandom(min,max){
return Math.floor(Math.random()*(max-min+1))+min;
}
Date 对象
Date是一个构造函数需要new来创建对象
var date=new Date();
没有参数,返回系统当前时间
参数常用写法:数字型2019,10,01 字符串型‘2019-10-01 8:8:8’
日期格式化
var date=new Date();
date.getFullYear()返回年份
date.getMonth() 返回的月份小1月(0-11)
date.getDate() 返回几号
date.getDay() (周日为0,周一 1周六6)
2019年5月1日星期一
var year=date.getFullYear();
var month=date.getMonth() +1;
var date=date.getDate();
var arr=[‘星期日,‘星期一’];
var day=date.getDay();
console.log(‘今天是’+‘year’+‘年’+month+‘月’+date+‘日’+arr[day]);
格式化日期时分秒
date.getHours();
date.getMinutes();
date.getSeconds();
返回当前时分秒函数
function getTime(){
var time=new Date();
var h=date.getHours();
h=h<10?‘0’+h:h;
var m=date.getMinutes();
m=m<10?‘0’+m:m;
var s=date.getSeconds();
s=s<10?‘0’+s:s;
return h+“:”+m+’:'+s;
}
获取总的毫秒数(时间戳)
Date对象基于1970年1月1日
date.valueOf();
date.getTime();新增时间距离基准时间总毫秒数
var date1=+new Date();返回的也是总的毫秒数
H5新增的方法Date.now();
倒计时
输入时间-现在时间,不能那时分秒直接相减;用时间戳做;把时间戳毫秒数转换为时分秒
d=秒数/60/60/24;天数
h=秒数/60/60%24;小时
m=秒数/60%60;分数
s=秒数%60;秒数
function countDown(time){
var nowtime=+new Date();
var inputtime=+new Date(time);
var times=(inputtimes-nowtime)/1000;
var d=parseInt(times/60/60/24);
var h=parseInt(times/60/60%24);
var m=parseInt(times/60%60);
var s=parseInt(times%60):
return d+'天'+h+'时'+m+'分'+s+'秒';
}
数组对象
var arr=new Array(2); 长度为2 的数组
var arr=new Array(2,3);等价于[2,3]
检查是否为数组:
- instanceof 运算符 用来检测是否为数组 arr instanceof Array;
- Array.isArray(arr);
添加删除数组元素
添加
push() 添加到末尾
arr.push(4,‘pink’);
返回值为添加后新数组长度,原数组发生变化
unshift()在开头添加一个或多个
arr.unshift(‘pink’,1);
返回值为新数组的长度,原数组发生变化,
删除
pop() 删除数组最后一个元素,一次只能删一个,无参数
arr.pop();返回值为删除的元素,原数组发生变化
shift()删除第一个元素,一次只能删一个,无参数,返回删除的那个元素,原数组发生变化
数组排序
翻转数组:arr.reverse();
排序:arr.sort(); 按照各个字符的Unicode位点排序
arr.sort(function(a,b){return a-b;}) 降序;return b-a; 正常排序
数组索引
获取指定数组元素索引:arr.indexOf(‘blue’); 如果有多个,返回第一个满足条件的索引号;找不到,返回-1;
arr.lastIndexOf(‘lan’);从后面开始查找,索引仍为正常
数组去重
数组转换为字符串
arr.toString();逗号分割
join(分割符)arr.join(‘-’); 默认逗号分割 返回一个新数组
concat() 连接两个或多个数组 不影响原数组
slice(begin,end);数组截取 返回被截取的新数组
splice(第几个开始,要删除几个) 返回被删除的新数组,影响原数组
字符串对象
基本包装类型:把简单数据类型包装为复杂数据类型
字符串是不可变的:里面的值是不可变的,但地址
字符串本身是不可变的,会开辟一个新空间存放新的字符串
返回索引:str.indexOf(‘春’); indexOf(‘要查找的字符’,‘起始位置’)后一个参数可选lastIndexOf()
根据位置返回字符:str.charAt(3);
str.charCodeAt(index) 返回对应字符的ascll码
str[index]
字符串拼接截取方法
str.concat(str1);
str.substr(start,length);相当于数组中的splice
slice(start,end);
substring(strat,end);
替换
str.replace(x,y);x替换前,y替换后 只替换第一个字符
转换为数组
str.split(‘分隔符’);
toUpperCase();转换大写
toLowerCase();转换小写
简单数据类型和复杂数据类型
数据类型内存分配
值类型(简单数据类型)null返回的是空对象
引用类型(复杂数据类型)
内存分配:堆(复杂)和栈(简单,存放的是值)
复杂数据类型:首先在栈里存放地址16进制,这个地址指向的数据值存在堆中
简单类型传参:值传递——不影响实参
复杂数据类型传参:地址传递——影响实参 堆地址复制
WebAPIs和API
webAPI学的是DOM和BOM 页面交互
API:应用程序编程接口 是一些预先定义的函数,目的是提供应用程序
webAPI:浏览器提供的操作浏览器功能和页面元素的API(BOM和DOM)
DOM
获取元素
文档页面从上往下加载,所以先有标签,script写在标签下面
- document. getElementById
id 是大小写敏感的
var timer = document.getElementById(‘time’);
返回的是对象
console.dir(timer);打印返回的元素对象,更好的查看属性和方法 - document. getElementsByTagName(‘li’) 通过标签名
返回的是元素对象的集合,以伪数组形式存储
打印里面元素,采取for循环遍历
得到的元素是动态的(随之变化)
若页面只有一个元素,返回的也是一个伪数组,若页面没有这个元素,返回的是一个空的伪数组
可以根据父元素获取子元素
document.getElementsByTagName(‘ol’);
父元素要指定是哪个对象
例:
ol[0].getElementsByTagName(‘li’); - document.getElementsByClassName根据类名获取
也是伪数组形式存储 - document.querySelctor(‘选择器’)返回指定选择器第一个元素对象,选择器需要加符号
document.querySelctor(‘.box’);类选择
document.querySelctor(‘#nav’);id选择
document.querySelctor(‘li’);标签选择 - document.querySelctorAll()返回指定选择器所有的元素对象
获取body和html标签
获取body:document.body;返回body元素对象
获取html:document.document.Element;
事件三要素
事件由三部分组成:事件源、事件类型、事件处理程序
事件源(事件被触发的对象)
事件类型(如何触发,比如鼠标点击onclick)
事件处理程序(通过函数赋值方式完成)
例:
var btn=document.getElementById('btn');
btn.onclick=function(){
alert('点秋香');
}
执行事件的步骤:
- 获取事件源
- 绑定事件
- 添加事件处理程序
改变元素内容:
element.innerText 从起始位置到终止位置,去除html标签,同时空格和换行也会去掉 不识别html标签
element.innerHTML 从起始位置到终止位置,包括html标签,同时保留空格和换行
div.innerHTML=‘今天是: 2019’;
这两个属性是可读写的,可以获取标签里的内容
改变元素属性
//1. 修改元素
var ldh=document.getElementById('ldh');
var zxy=document.getElementById('zxy');
var img=document.querySelector('img');
//2. 注册事件,处理程序
zxy.onclick=function(){
img.src='url';
img.title='张学友';
}
ldh.onclick=function(){
img.src='url1';
img.title='刘德华';
}
修改表单属性
innerHTML是普通标签的
表单是通过value修改的
input.value=“被点击了”;
按钮被禁用:btn.disabled=true;
this 指向事件函数的调用者 this.disabled=true;
案例:密码框隐藏与显示
修改样式:
this.style.backgroundColor=‘purple’; 驼峰命名法
js写的是行内样式
案例:叉号显示隐藏
循环精灵图
显示隐藏文本框内容 获得焦点onfocus onblur失去焦点
text.οnfοcus=function(){}
text.οnblur=function(){}
使用className修改样式属性
在css中定义类,在js中将this.className=‘change’; 将当前类名改为change,会覆盖之前类名
若要保留之前类名:this.className=‘first change’;
排他思想
所有按钮绑定事件,for循环
先所有元素清楚样式,再设置自己
for(var i=0;i<lis.length;i++){
lis\[i].onclick=function(){
for (var i=0;i<lis.length;i++){
lis\[i].className=' ';
}
this.className='current';
}
}
案例:表单隔行变色
鼠标经过:onmouseover 离开 onmouseout
表单全选
checked=‘checked’;
tbs[i].checked=this.checked; true or false;
获取属性:
element.属性; 获取内置属性(class,id)
element.getAttribute(‘属性’); 获取自定义属性(自己添加的属性)
设置属性:
element.属性=value;div.className=‘navs’;
element.setAttribute(‘属性’,‘值’);div.setAttribute(‘class’,‘navs’);
移除属性
element.removeAttribute(‘属性’);
tab栏切换:
for (var i=0;i< items.length;i++){
items[i].style.display=‘none’;
}
intems[index].style.display=‘block’;
自定义属性命名以data-(index)开头
新增获取属性方法:element.dataset.index; div.dataset[‘index’];(有兼容性,ie11以上)
dataset是一个集合,里面存放所有以data开头的自定义属性
data-list-name dataset[‘listName’];
若自定义属性命名有多个-链接单词,获取时采用驼峰命名法
节点操作-获取元素
节点node所有内容都是节点 nodename 、nametype、nodevalue
元素节点type1 、属性节点type2 、文本节点type3
节点层级:父子兄层级关系
父级节点 node.parentNode; 最近的父亲(亲爸爸) 不能得到爷爷,找不到返回空
子节点 node.childNodes; 得到所有子节点,包含元素节点和文本节点
检查节点类型:node.childNodes[0].nodeType
node.children; 获取所有子元素节点
节点操作第一个和最后一个元素
node.firstChild;返回第一个子节点
node.lastChild;最后一个子节点
node.firstElementChild;返回第一个子元素节点;ie9以上才支持
node.lastElementChild;返回最后一个子元素节点
实际上可以使用node.children[0] node.children[node.children.length-1];
节点操作:兄弟节点
node.nextSibling;下一个兄弟节点;(包含文本节点)
node.previousSibling;上一个兄弟节点
node.nextElementSibling;下一个兄弟元素节点
node.previousElementSibling;上一个兄弟元素节点
创建节点document.creatElement(‘li’);
添加节点node.appendChild(child);在后面添加
在指定元素前面添加node.insertBefore(child,指定元素);
案例:评论:
btn.onclick=function(){
if (text.value==''){
alert('您没有输入内容!');
return false;
}else{
var li =document.createElement('li');
li.innerHTML=text.value;
// ul.appendChild(li);
ul.insertBefore(li,ul.children[0]);
}
}
删除节点:
node.removeChild(child);
点击页面阻止页面跳转:<a href=‘javascript:;’>
案例:评论删除
复制节点
node.cloneNode();括号参数为空或false,只复制标签,不复制内容,括号内容为true,深拷贝,复制里面内容
ul.appendChild(li);
案例:动态生成表格
填充数据:td.innerHTML=datas[i][k];
三种动态创建元素方式
document.write(‘元素’);直接将内容写入页面,担当文档流执行完毕,会导致页面全部重绘
element.innerHTML=‘元素’;
采取数组形式效率更高(个位数):
var arr=[ ];
arr.push(‘元素’);
document.body.innerHTML=arr.join(’ ');
document.createElement(‘元素’);效率更高
element.appendChild();
DOM核心总结:
创建、增删改查、属性、事件操作
事件高级
传统注册事件:利用on开头的onclick 注册事件唯一性 后添加的会覆盖
方法监听注册方式:eventtaget.addEventListener(type,listener,useCapture)
type:事件类型,加引号,不用加on,listener为处理函数function(){} 同一个元素可以添加多个侦听器
eventtaget.attachEvent(‘onclick’,function(){}) ie9以前的支持
删除事件(解绑事件)
传统方法:
ventTarget.οnclick=function(){
alert(11);
eventTarget.οnclick=null;
}
侦听器方法
eventTarget.addEventListener(‘click’,fn)
function fn(){
alert(22);
eventTarget.removeEventListener(‘click’,fn);
}
ie9以前
divs[2].attachEvent(‘onclick’,fn1);
function fn1(){
alert(33);
divs[2].detachEvent(‘onclick’,fn1);
}
DOM事件流
三个阶段:捕获阶段(从父亲开始)、当前目标阶段、冒泡阶段(从子代开始)
js代码只能执行捕获或者冒泡中的一个阶段
onclick、attachEvent只能得到冒泡阶段,addEventListener第三个参数为true,则处于捕获阶段
例:
var son=document.querySelector('.son');
son.addEventListener('click',function(){
alert('son');
},true);
冒泡阶段:
addEventListener第三个参数为false或省略,则处于冒泡阶段
var son=document.querySelector('.son');
son.addEventListener('click',function(){
alert('son');
});
一般更关注事件冒泡
事件对象
div.οnclick=function(event){}
event就是一个事件对象,写到处理函数的小括号里,当形参看,系统自动创建,不需要传递参数,事件对象可以自己命名,e
事件对象是我们事件一系列相关数据的集合,跟事件相关的
ie678 window.event
兼容写法:e=e||window.event;
e.target 返回触发事件元素
this 返回的是绑定事件的对象
e.type 返回事件类型
阻止默认行为,让链接不跳转,或提交按钮不提交
e.preventDefault();
例:
var a=document.querySelector('a');
a.addEventListener('click',function(e){e.preventDefault();})
传统注册方式:
a.onclick=function(e){
e.preventDefault();
}
阻止冒泡:
事件冒泡:具体元素接受,逐级向上
e.stopPropagation();
var son=document.querySelector('.son');
son.addEventListener('click',function(e){
alert('son');
e.stopPropagation();
});
ie678:
var son=document.querySelector('.son');
son.addEventListener('click',function(e){
alert('son');
e.stopPropagation();
window.event.cancelBubble=true;//属性
});
father 也需要添加
事件委托
事件委托的原理:不是单独给每个子节点添加侦听器,而是设置在父结点上,利用冒泡原理影响每个子节点
var ul=document.querySelector('ul');
ul.addEventListener('click',function(){
alert('茅坡!');
e.target.style.backgroundColor='pink';
})
禁止选中文字和禁止右键
contextmenu 禁用右键
document.addEventListener('contextmenu',function(e){
e.preventDefault();
})
禁止选中selcetstart
document.addEventListener('selctstart',function(e){
e.preventDefault();
})
鼠标事件对象MouseEvent
document.addEventListener('click',function(e){
console.log(e.clientX);
console.log(e.clientY);
})
clientX当前页面下x,y坐标
document.addEventListener('click',function(e){
console.log(e.pageX);
console.log(e.pageY);
})
pageX页面文档的x,y坐标
跟随鼠标
mousemove
绝对定位
每次鼠标移动,获得最新鼠标坐标,把这个x和y坐标作为图片的top和left值
document.addEventListener('mousemove',function(e){
var x=e.pageX;
var y=e.pageY;
pic.style.top=y+'px';
pic.style.left=x+'px';
})
键盘事件
onkeyup 松开时
document.onkeyup=function(){
})
document.addEventListener('keyup',function(){
})
onkeydown 按下时
onkeypress 按下时触发 不识别功能键ctr shift 箭头 alt不识别
键盘事件对象KeyBoardEvent
keyCode返回该键的ascll码值
keyup和keydown 不区分字母大小写,按大写A;keypress区分字母大小写
document.addEventListener('keyup',function(e){
console.log(e.keyCode);
})
按s键,把光标定位到搜索框中
获取焦点:element.focus();
var search=document.querySelector('input');
document.addEventListener('keyup',function(e){
if(e.keyCode==83){
search.focus();
}
})
注意:keydown两个事件触发时文字还未进入文本框中,而keyup弹起时,文字已经落入文本框了。
BOM
浏览器对象模型
核心(顶级)对象时window DOM中顶级对象为document
全局变量是window对象的一个属性
函数是window对象的一个方法,调用时省略window
name是window对象的一个特殊属性
页面加载事件
传统方式:后面的会覆盖前面的
<script>
window.οnlοad=function(){
里面填写script代码
}
</script>
推荐方式:没有限制
window.addEventListener(‘load’,function(){});
第三种:
document.addEventListener(‘DOMContentLoaded’,function(){});
load是页面所有元素全部加载完毕,包含dom元素,图片等等,
DOMContentLoaded 是DOM加载完毕,不包含图片等等,加载速度比load快
调整窗口大小事件
window.onsreize=function(){}
window.addEventListener(‘resize’,function(){});
window.innerWidth屏幕宽度的属性
定时器
window.setTimeout(调用函数,延迟时间);时间单位时毫秒 延迟调用函数,只调用一次
window调用时可以省略
调用函数可以直接写写函数,也可以写函数名,或者写为’函数名()'加引号
页面中有很多定时器,经常给他们加标识符(名字)
var timer=setTimeout(function(){},2000);
回调函数:一件事做完,再回头调用那个函数
案例:5秒后自动关闭广告
停止定时器:点击某个按钮停止定时器:btn.addEventListener(‘click’,function(){clearTimeout(timer);})
var setInterval(function(){},1000)定时器 每隔一秒调用一次 重复调用
开始定时器
var timer=null;(定义全局变量,赋值null)
begin.addEventListener(‘click’,function(){timer=setInterval(function(){},1000);})
清除定时器:stop.addEventListener(‘click’,function(){clearInterval(timer);})
案例:倒计时 setInterval()
button改值是通过innerHTML修改
案例:发送短信
this指向问题
一般情况下this指向那个调用它的对象
全局作用下this指向全局对象window
谁调用就指向谁
同步和异步
js是单线程
同步任务:主线程执行线
异步任务:通过回调函数实现,一般有三种类型:
- 普通事件,如:click、resize
- 资源加载,如:load、error
- 定时器,如:setInterval、setTimeout
异步任务回调函数添加到任务队列中
location对象
url:互联网上标准资源地址
语法格式:protocol://host[:port]/path/[?query]#fragment
protocol:通信协议
host:主机(域名)
port:端口号
path:路径
query:参数
fragment:片段
location.href:获取或设置整个url
location.host:返回主机(域名)
location.port:返回端口号
location.pathname:返回路径
location.search:返回参数&分开
location.hash 返回片段#后面的内容锚点
案例:点击之后跳转页面
location.href=“新url”
案例:5秒之后自动跳转
案例:获取url参数
跳转页面:location.assign(‘新的url’);记录浏览历史,可以实现后退效果
location.replace(‘url’)不记录浏览历史,不能实现后退功能
location.reload()重新加载页面相当于刷新,参数为true相当于强制刷新
navigator对象
useragent:返回一些值
if((navigator.userAgent.match(/phone)))
移动端或pc端
history对象
history.forward();
history.back();历史页面
history.go(1);前进一步
PC端网页特效
元素偏移量:offset
offset 得到元素的偏移位置,返回不带单位的数值
div.offsetTop 返回该元素相对带有定位父级元素上方的偏移
div.offsetLeft
element.offsetWidth offsetHeight返回元素的大小、宽度和高度包含padding、width
offsetParent 返回带有定位的父亲,否则返回body
parentNode 最近一级父亲,不管有无定位
offset和style区别:
style.width只能得到行内样式表的样式值,得不到内嵌样式表的值,并且style返回的带单位
offset是只读属性,不能改变,style是可以更改的
案例:模态框拖拽
client系列
element.clientTop 上边框大小
element.clientWidth 包含padding、width、不包含边框,offset包含边框
立即执行函数:不需要调用,可以立即执行的函数
语法:(function(a,b){})(1,2)或(function(){}()) 也可以传递参数 第二个小括号相当于调用函数 也可以加函数名
立即函数独立创建了一个作用域,里面所有变量为局部变量
淘宝flexible核心代码分析
load事件和pageshow事件
scroll系列
element.scrollWidth 返回自身实际宽度,不含边框,返回数值不带单位
element.scrollWidth 返回自身实际高度(包括超出的),不含边框,返回数值不带单位
element.scrollTop 返回被卷去的上侧距离,返回数值不带单位
window.pageYOffset获得页面被卷去的头部高度
scroll是元素被卷去的
mouseenter事件和mouseover事件
mouseover经过自身和子盒子都会触发(冒泡),mouseenter经过子盒子不会触发,mouseleave同样不会冒泡,搭配鼠标离开
动画原理
核心原理:通过setInterval()函数不断移动盒子距离
此元素要添加定位
例:
var timer=setInterval(function(){
if(div.offsetLeft>=400){
// 停止定时器
clearInterval(timer);
}
div.style.left=div.offsetLeft+5+'px';
},30)
简单动画函数封装
function animation(obj,target){}
function animation(obj,target){
clearInterval(obj.timer);//让对象只有一个定时器执行
obj.timer=setInterval(function(){//给不同元素添加不同定时器
if(obj.offsetLeft>=target){
// 停止定时器
clearInterval(obj.timer);
}
obj.style.left=obj.offsetLeft+5+'px';
},30)
}
缓动动画原理
让速度慢慢停下来
算法:(目标值-现在位置)/10
function animation(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);
}
obj.style.left=obj.offsetLeft+step+'px';
},15)
}
动画函数添加回调函数
function animation(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);
if (callback){
callback();//相当于 callback && callback();
}
}
obj.style.left=obj.offsetLeft+step+'px';
},15)
}
animation(span,800,function(){
alert(11);
});//调用函数
动画函数分装到单独js文件中
<script src='js/animate.js'></script>
网页轮播图
节流阀
当上一个函数动画执行完毕,再执行下一个函数动画
利用回调函数,添加一个变量来控制
flag =false;
animate(ul,300,function(){
flag=true;
})
案例:返回顶部
window.scroll(x,y);返回到指定的坐标位置 里面x,y不跟单位
animate(window,0);