目录
2.js是单线程的语言,但是我们可以通过超时调用来调度代码。
一、面向对象的程序设计
1.对象的创建
(1)工厂模式
1.定义:由于使用普通的字面量创建多个对象时,会产生大量的重复代码,为了解决这个问题,我们引入工厂模式。
2.优点: 通过将创建对象的方法封装起来,避免重复代码产生。
3.缺点:创建的所有对象类型都是Object类型,没有办法知道对象到底是Person还是Dog。
例子:
当分别检测创建的两个类时,这两个类都是对象,人和狗是不能区分的。
function newPerson(name,age,gender){
var p=new Object();
p.name=name;
p.age=age;
p.gender=gender;
p.sayName=function(){
console.log(this.name);
};
return p;
}
var p1=newPerson('zhangsan','12','男');
var p2=newPerson('lisa','18','女');
console.log(p1);
console.log(p2);
p1.sayName();
p2.sayName();
function newDog(name,age,gender){
var d=new Object();
d.name=name;
d.age=age;
d.gender=gender;
d.sayName=function(){
console.log("汪汪的名字是"+this.name);
};
return d;
}
var d1=newDog('鼠标','2','母');
var d2=newDog('六斤','3','公');
console.log(d1);
d1.sayName();
console.log(typeof p1);
console.log(typeof d1);
(2)构造函数模式
1.可以区分每个类,Person是Person类,Dog是Dog类。
2.每个方法都要在每个实例上重新创建一遍,没有必要。
3.虽然可以将这个方法提取出来,提取到全局范围内,将引用传递给对象中的函数属性,但是全局函数太多的话,体现不了类的封装性。
(3)原型模式
function Person(){};
特点:
1.对于一些共享的属性,共享函数使用这种方式创建是非常合适的。
2.但是包含引用数据类型的值就不太好。
(4)构造函数模式+原型模式
2.继承
1.原型链继承
当我们调用对象的某个方法或属性时,我们该怎么寻找方法呢?
每个构造函数都有一个原型对象,原型对象中都包含一个指向构造函数的指针,而实例都把含一个指向原型对象的内部指针。当原型对象等于另一个类型的实例即继承。调用某个方法或属性的步骤。
a.搜索实例
b.搜索原型
c.搜索父类原型
(1)默认原型
所有函数默认原型都是Object的实例,默认原型中都会包含一个内部指针,指向Object.isPrototype
例子:
//定义父类类型
function Animal(){
this.name="animal";
}
Animal.prototype.sayName=function(){
console.log(this.name);
}
//定义子类
function Dog(){
this.color="black";
}
// 将子构造函数的原型,指向父类对象的实例
Dog.prototype=new Animal();
Dog.prototype.sayColor=function(){
console.log(this.color);
}
var dog=new Dog();
console.log(dog);
dog.sayName();
dog.sayColor();
(2)确定原型和实例的关系
1.通过使用instanceof
2.通过使用isPrototype()
只要是原型链中出现过的原型,都可以说是该原型链所派生的实例的原型。
例子:
function Animal(name,age){
this.name=name;
this.age=age;
}
Animal.prototype.sayName=function(){
console.log(this.name);
}
Animal.prototype={
constructor:Animal,
sayHello:function(){
console.log(this.name+"say hello!");
}
}
function Dog(name,age,color){
this.name=name;
this.age=age;
this.color=color;
}
//原型链继承
//console.log(Dog.prototype);
Dog.prototype=new Animal();
console.log(Dog.prototype);
Dog.prototype.constructor=Dog;
Dog.prototype.sayColor=function(){
console.log(this.color);
}
var dog=new Dog('金毛',1,'yellow');
console.log(dog);
dog.sayHello(); //Animal.prototype
dog.sayColor(); //Dog.prototype
console.log(dog.toString());//Object.prototype超类
console.log(typeof dog);
console.log(dog instanceof Dog);
console.log(dog instanceof Animal);
console.log(dog instanceof Object);
//检测是否是该原型派生出来的对象
console.log(Object.prototype.isPrototypeOf(dog));
console.log(Animal.prototype.isPrototypeOf(dog));
(3)谨慎定义方法
子类型覆盖超类型中的某个方法,或者是需要添加超类中不存在的方法,都需要将给原型添加方法的代码放在继承只会(即替换原型的语句之后)
(4)原型链问题
1.通过原型来实现继承时,原型实际上变成另一个类型的实例,原来的实例属性也就变成了现在的原型属性。
2.在创建子类型的实例时,不能向超类型的构造函数传递参数。
因此实践中很少会单独使用原型链
2.经典继承(不仅可以继承方法,也可以继承属性)
又叫借用构造函数,也叫伪造对象。
定义:在子类型构造函数的内部调用超类型构造函数。函数不过是在特定环境中执行代码的对象,因此通过apply(),call()方法可以在(将来)新建对象上执行构造函数,即在子类型对象上执行父类型函数中定义的所有对象初始化的代码。结构每个子类实例中都具有父类型中的属性以及方法。
例子:
function Animal(name,age){
this.name=name;
this.age=age;
this.sayName=function(){
console.log(this.name);
}
}
Animal.prototype.sayAge=function(){
console.log(this.age);
}
function Dog(name,age,color,type){
//this.name=name;
//借用构造函数
//找到父类
Animal.call(this,name,age);
this.color=color;
this.type=type;
}
var dog=new Dog('铃铛',1,'yellow','金毛');
console.log(dog);
dog.sayName();
//dog.sayAge();//报错,因为是父类原型中的方法,不能继承原型中的方法
3.组合继承
定义:组合继承就是原型链继承+经典继承,可以继承属性和方法,以及原型中的属性和方法。也称为“伪经典继承”,将原型链和借用构造函数的技术组合在一起。
原理:使用原型链实现对原型属性和方法的继承,而通过借用构造函数实现对实例数中的继承。
例子:
function Animal(name,age){
this.name=name;
this.age=age;
this.sayAge=function(){
console.log(this.age);
}
}
Animal.prototype={
constructor:Animal,
sayName:function(){
console.log("hello,my name is"+this.name);
}
}
function Dog(name,age,type){
//经典继承
Animal.call(this,name,age);
this.type=type;
}
//原型链继承
Dog.prototype=new Animal();
Dog.prototype.constructor=Dog;
Dog.prototype.sayType=function(){
console.log(this.type);
}
var dog=new Dog('花花',1,"哈士奇");
console.log(dog);
dog.sayName();
dog.sayType();
dog.sayAge();
二、文档对象模型——DOM
1.定义
DOM使js操作html、xml文档的api,1998年10月出来的。在IE中的DOM对象事宜COM对象的形式实现的。
2.实例化
(1)通过dom拿到我们想要的节点
var myDiv=document.getElementById("myDiv");
console.log(myDiv);
(2)通过dom创建节点。
<script>
var myDiv=document.getElementById("myDiv");
console.log(myDiv);
//创建一个li结点
var node =document.createElement("LI");
//创建一个text结点
var textNode=document.createTextNode("Hello");
//将text结点追加到li节点上
node.appendChild(textNode);
//找到id为myDiv
var myDiv=document.getElementById("myDiv");
//将刚刚创建的node结点追加为myDiv的子节点。
myDiv.appendChild(node);
</script>
3.Document类型
1.属性
body | 直接指向body元素 |
head | 获取html头部内容 |
title | 获取文档标题 |
docType | 获取<!DOCTYPE> 兼容性不好 很少用 |
URL | 获取文档的标题 |
domain | 获取域名 |
referrer | 获取链接到当前页面的那个页面的url |
images | 获取页面所有的img对象 返回值:HTMLCollection |
forms | 获取所有form表单对象 返回值:HTMLCollection |
links | 获取文档中带有href属性的a元素 |
2.方法
方法 | 作用 | 调用者 | 参数 | 返回值 |
getElementById() | 通过元素的id获取元素节点 | document | 想要获取的元素id | 返回找到的第一个元素怒,如果没有则返回null |
getElementsByClassName() | 通过元素的类名获取元素节点 | document | 元素的类名 | HTMLCollection list 包含一个或多个元素,可以使用数组的操作方式处理结果。 |
getElementByTagName() | 通过元素名或标签名找到元素 | document | 元素名或标签名 | HTMLCollection list 包含一个或多个元素,可以使用数组的操作方式处理结果。 |
getElementByName() | 通过元素name属性找到原素 | document | 元素的name属性名 | NodeList list 包含一个或多个元素。 可以使用数组的操作方式处理结果。 |
4.Element类型
1.属性
id | 元素在文档中的唯一标识符 |
className | 与元素的class特性相对应 可以重复 可以有多个 用空格分割 |
title | 与元素相关的附加说明信息 |
src、alt | 与图片相关 |
2.方法
(1)设置属性
node.setAttribute();
作用:给获取到的元素设置属性
调用者:要设置属性的元素
参数:两个参数 属性名 对应的值
【注意:要设置的值存在的话,修改原来的值,不存在的话 添加】
node.className="two";//s设置类名第一种方式
node.setAttribute("class","three");//设置类名的第二种方式
方法 | 作用 | 调用者 | 参数 | 返回值 |
node.getAttribute(); | 给获取的相应元素的某个属性 | 元素 | 属性名 | 对象的属性值 |
myDiv.removeAttribute(); | 移除相应元素的某个属性 | 元素 | 属性名 | 不考虑返回值 |
firstElementChild | 第一个孩子元素节点 | |||
lastElementChild | 最后一个孩子元素节点 | |||
nextElementSibling | 下一个兄弟元素节点 | |||
previousElementSibling | 上一个兄弟元素节点 | |||
childElementCount | 子元素的数量,返回值和children.length值相 | |||
createElement(); | 创建一个dom元素节点 | document | 一个参数,要创建元素的标签名,在html中不区分大小写,而在xml中区分大小写。 | 无 |
5.Text类型
1.获取文本内容
(1)innerHTML 返回元素内容
(2)textContent 该元素内部的text
(3)innerText 获取文本内容
console.log(div.innerHTML);
console.log(div.innerText);
2.获取文本节点
firstChild
var textNode=div.firatChild;
console.log(textNode);
console.log(textNode.innerText)
3.属性
length 文本长度
4.方法:
方法 | 作用 | 调用者 | 参数 | 返回值 |
appendData() | 给文本节点追加文本 | 文本节点 | 要追加的文本内容 | 无 |
deletData(beginIndex,count) | 删除文本 | 文本节点 | 开始的位置[1开始],要删除的数量 | 无 |
insertData(beginIndex,count) | 插入文本 | 文本节点 | 开始的位置[1开始],要插入的文本 | 无 |
replaceData(beginIndex,count,text) | 替换文本 | 文本节点 | 开始的位置,数量,要替换的文本 | 无 |
splitText(beginIndex) | 从开始位置将当前文本节点分割 | 文本节点 | 开始位置 | 分割好的后面的文本节点 |
document.createTextNode() | 创建文本节点 | document | 文本内容 | textNode |
substringData(beginIndex,count) | 提取文档中的字符串 | 文本节点 | 开始的位置,数量 | 提取出来的字符串【注意:不改变原来的文本】 |
6.Comment类型
定义:代表注释
方法:createComment();
作用:创建注释节点
var cNode=document.createComment("这是一个注释");
7.DOM节点操作的方法
(1)创建节点
var myDiv=document.createElement("tagName");
(2)给节点添加文本内容
myDiv.innerText="这是新创建的div";
(3)在页面上的一个节点
(4)将myDiv追加到rootDiv上
rootDiv.appendChild(myDiv);
函数方法 | 作用 | 调用者 | 参数 | |
appendChild() | 将节点作为子节点追加到调用它的节点的后面 | 父节点 | 要追加的新节点 | 【注意:任何dom节点不能同时出现在文档的多个位置,如果追加的节点是原本存在的,那只会】 |
insertBefore(myDiv,childNode); | 将新的节点插入到之前某个节点的前面 | 父节点 | 要插入的 | |
removeChild(childNode); | 删除某个子节点 | 父节点 | 要删除的子节点 | |
cloneNode(); | 复制节点 | 要复制的节点自身 | 个可选参数,默认为false浅克隆 只复制标签。如果为true,那么就是深克隆,会复制标签以及内容。 |
三、事件
1.事件三要素
事件目标
事件处理程序
事件对象
2.事件流(页面接收事件的顺序)
(1)事件冒泡
1.定义:事件由一个具体的元素接受,然后又逐步传递到具体的节点。
2.特点:从内往外传递
【注意:元素需要嵌套,每层元素都绑定事件】
3.组织事件冒泡:
event.stopPropagation();
(2)事件捕获
1.事件由不太具体的节点接收到,然后传到具体的节点上。
2.特点:从外往内传递
3.函数方法:
(1)addEventListener();
作用:绑定事件监听器
参数:
1.事件类型(click mouseover等)
2.事件处理函数,当绑定的事件被触发时,要执行的操作
3.boolean 可选参数 用来决定事件流类型(false是事件冒泡,true是事件捕获)
(2)removeEventListener()
作用:移除事件
参数:
1.事件名
2.事件处理函数
3.boolean(false是事件冒泡,true是事件捕获)
(3)on+事件名 【它是一个属性】
作用:绑定事件 比如:onclick onmouseover
调用者: 节点 可以是div 也可以是button
(4)IE事件处理程序
attachEvent();
作用:事件绑定
参数:
1.事件处理名称
2.事件处理函数
detachEvent()
作用:事件移除
3.事件对象event
(1)在触发DOM的某个事件时 会产生一个事件对象 event
(2)这个包含所有与事件相关的信息
(3)浏览器默认会把event传入到事件处理函数中
(4)event对象的属性都是只读属性
(5)常用属性:
属性名 | 类型 | 说明 |
event.type | String | 事件类型 |
event.bubbles | Boolean | 事件是否冒泡 |
cancelable | Boolean | 是否可取消事件默认行 |
target | Element | 事件目标 |
4.事件类型
(1)鼠标事件
1.click:点击鼠标的主要按钮,点击触控板
2.dblclick: 双击鼠标的主要按钮
3.mousedowm:任意鼠标按钮按下时触发
4.mouseout:在位于元素上方的鼠标光标移入到另外一个元素中。
5.mouseover:鼠标位于元素外部,将其首次移入另一个元素边界之内时触发。
6.mousemove:鼠标在元素内部移动的时候重发触发
7.mousewheel 滚轮事件
8.mouseleave 在位于元素上方的鼠标光标移动到元素范围之外时触发
(2)坐标点
1.客户区坐标位置 event.clientX,event.clientY
eg.console.log("客户区坐标位置:" + event.clientX + ',' + event.clientY);
2.页面坐标位置 event.pageX,event.pageY
eg.console.log("页面坐标位置:" + event.pageX + ',' + event.pageY);
3.屏幕位置 event.screenX,event.screenY
eg.console.log("屏幕坐标位置:" + event.screenX + ',' + event.screenY);
(3)焦点事件
1.blur 元素失去焦点
2.focus 元素获得焦点
(4)UI事件
1.load
(1)在页面完全加载后在window上触发这个事件
(2)如果是图像加载完成后,会在img元素上触发
(3)window.onload
2.unload 在页面完全卸载后会在window上触发这个事件
3.select 当用户选择文本框中的字符时会触发
4.resize 当浏览器窗口被调整宽高时会触发,会重复触发
5.acroll 滚动条滚动时会触发,会重复触发
(5)键盘事件
1.keydown 按下键盘任意键时触发,如果按住不放会一直重复触发【后面跟的是ASCII码】
2.keypress 按下键盘字符键时触发,如果按住不放会重复触发
3.keyup 释放键盘上键时触发。
5.事件代理
将事件绑定到父元素上,这时点击当前元素时,就会执行父元素上绑定的事件处理函数。
好处:父元素代理子元素的事件,子元素可以动态添加,不用频繁的去绑定事件。
可以通过event.target获得当前元素
例子:
运行下面代码:给每个子元素绑定点击事件,当点击子元素时会有弹框出来;给带有+的子元素绑定克隆事件,当点击这个+子元素时会复制出和其他子元素相同的子元素,并且克隆出来的子元素会自动绑定点击事件。而这个克隆出来的新子元素也有点击事件的这个事件叫代理事件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>事件代理</title>
<style>
//给父元素和子元素分别进行修饰
.parent{
border:1px solid blueviolet;
overflow: hidden;
}
.child{
width: 100px;
height:100px;
border:1px solid royalblue;
margin: 10px;
float: left;
}
.add{
width: 100px;
height:100px;
border:1px solid royalblue;
float: left;
margin: 10px;
text-align: center;
line-height: 100px;
}
</style>
</head>
<body>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="add" onclick="addChild()">+</div>
</div>
</body>
<script>
//事件代理:将事件代理到父元素上
var parent=document.getElementsByClassName('parent')[0];
parent.onclick=function(event){
if(event.target.className === 'child'){
alert('我是子元素')
}
}
//追加节点
function addChild(){
var parent = document.getElementsByClassName('parent')[0];
var child = document.getElementsByClassName('child')[0];
var cloneChild = child.cloneNode(true);
var lastChild = parent.lastChild.previousSibling;
parent.insertBefore(cloneChild,lastChild);
}
</script>
</html>
四、浏览器对象模型——BOM
1.BOM里的一个核心对象时window
2.js是单线程的语言,但是我们可以通过超时调用来调度代码。
(1)超时调用:
1.setTimeOut
作用:在指定的毫秒数(时间)后执行函数
参数:
1.要执行的函数(必须)
2.,以毫秒表示的时间(可选,默认0)
返回值:是一个数字,是当前setTimeout的id,可以通过这个id取消超时
2.clearTimeout()
作用:取消超时调用
参数:超时调用的id
(2)间歇调用:
setInterval
作用:在指定的毫秒数(时间)周期,重复调用函数,知道窗口关闭,或者调用clearInterval()。
参数:
1.要执行的函数(必须)
2.以毫秒表示的时间(可选) 但是最好写上毫秒数。
返回值:是一个数字,是当前setTimeout的id,可以通过这个id取消间歇调用
3.系统对话框
调用系统对话框向用户提示消息,当对话框显示的时候,代码会暂停执行,关掉后,代码继续执行
(1)alter()
作用:警告框/提示框 只有确认按钮
参数:字符串,显示给用户
返回值:无
(2)confirm()
作用:确认框 有确认按钮和取消按钮
参数:字符串,显示给用户
返回值:点击确认返回true,点击取消返回false
(3)prompt()
作用:提示用户输入文本,有确认和取消两个按钮
参数:字符串 显示给用户
返回值:点击确认返回用户输入的文本,点击取消返回null。
4.Location
BOM对象之一, 提供当前窗口加载的文档的一些信息,还导航功能。它既是window的对象,又是document的对象。
eg.console.log(window.location==document.location)
console.log(window.location)
hash: "" 服务器名称和端口号
host: "" 服务器名称
hostname: ""
href: "file:///D:/briup/...html" 当前页面的完整路径
origin: "file://"
pathname: "/D:/briup/....html"
port: "" 端口号
protocol: "file:"
方法:
1.assign()
作用:载入一个信道url,并且生成一条新的浏览记录,可以回退。
2. replace()
作用:用新的url替换当前url 、,不会生成新的记录,不可以回退
3.reload()
作用:重新加载当前页面
参数:boolean类型 如果参数为true,则会强制刷新。
5.history
(1)作用:保存着用户的上网历史记录,出于安全考虑,我们无法得到浏览器的url,但是我们可以拿到列表,实现前进后退。
(2)属性:
1.length 返回历史列表中的网址数
【注意:Firefox Chrome Safart都是从1开始,IE和Opear从0开始】
(3)方法:
1.back(): 加载history列表中的前一个url
2.forword(): 加载history列表的下一个url
3.go():加载列表的某一个具体页面
参数:数字 可以为负数
history.go(1); //forward()
history.go(-1); //back()