Javascript 笔记(下)

525 阅读55分钟

node属性

v1.node

描述:node是DOM中的最小单位,可以认为DOM概念下页面中所有的内容都是节点。

V2.node属性

描述:node属性如非特殊说明,则对所有的节点都生效。

3.nodeName \ nodeType

描述:返回节点的名称和节点的类型(节点类型采用常数表示)

语法:

node.nodeName
node.nodeType

v注意:对于元素节点,nodeName会返回大写的元素名

例子:

var span = document.querySelector('span');
console.log(span.nodeName);   //SPAN

4.ownerDocument属性

描述:返回当前节点所在的文档的document节点

语法:

node.ownerDocument

注意:document节点的ownerDocument属性返回null

例子:

console.log(div1.ownerDocument);
console.log(div2.ownerDocument);
console.log(span.ownerDocument);
console.log(document.ownerDocument);

v5.nextSibling属性

描述:返回紧跟在当前节点后的第一个同级节点

语法:

node.nextSibling

注意:文本也是节点!!!!

例子:

console.log(div2.nextSibling);
console.log(div1.nextSibling.nextSibling);

// 查看div1中所有子节点
var el = div1.firstChild;
var i = 1;

while (el) {
  console.log(i + '. ' + el.nodeName);
  el = el.nextSibling;
  i++;
}

V6.previousSibling属性

描述:所有注意事项和内容均和nextSibling完全相同,唯一区别在于返回前一个兄弟节点。

V7.parentNode属性

描述:返回当前节点的父节点,如果没有父节点则返回null。

例子:

console.log(div2.parentNode.parentNode.parentNode.parentNode.parentNode);

8.parentElement属性

描述:返回当前节点的父元素节点,如果没有父节点或者父节点不是元素节点,都返回null。

例子:

console.log(div2.parentNode.parentNode.parentNode.parentNode);       
console.log(div2.parentElement.parentElement.parentElement.parentElement);

v9.childNodes属性

描述:返回一个由当前节点的所有子节点构成的节点集合(nodeList)

例子:

var childList = div1.childNodes;
console.log(childList);       
console.log(childList instanceof Array);       
console.log(childList instanceof Object);       
console.log(childList.length);       
console.log(childList[0]);

10.firstChild \ lastChild属性

描述:返回当前节点的第一个 \ 最后一个子节点,如果不存在则返回null

例子:

console.log(div1.firstChild);   
console.log(div1.lastChild);

11.textContent属性

描述:属性返回当前节点,及其所有后代节点的内容

例子:

console.log(document.body.textContent)

12.nodeValue

描述:本属性用来读写节点的内容(仅对文本节点有效,其他类型节点使用均无效果)

例子:

console.log(span.firstChild.nodeValue);       
span.nodeValue = '这是一个从新设置的span';

node节点的方法

v1. appendChild()方法

描述:本方法接收一个【节点对象】做参数,并将这个节点作为最后一个子节点插入当前节点。

语法:

node.appendChild(subNode);

例子:

var div = document.querySelector('div');       
var h2 = document.createElement('h2');  
h2.innerHTML = '这是h2';       
div.appendChild(h2);
console.log(div.childNodes);

v2. hasChildNodes()方法

描述:本方法用来判断一个节点是否存在子节点。如果有则返回true,否则false

语法:

node.hasChildNodes();

例子:

var div = document.querySelector('div');       
var h2 = document.querySelector('h2');       
console.log(div.hasChildNodes());       
console.log(h2.hasChildNodes());

v3. cloneNode()方法

描述:本方法表示拷贝一个节点。接收一个布尔值做参数表示是否同时拷贝该节点的所有子节点。

默认或不写参数都表示false(不拷贝)。

语法:

var newNode = node.cloneNode(boolean);

注意:

(1) 节点拷贝:复制一个节点,包括复制节点的内容,属性。

(2)  深拷贝(deep copy): 不光拷贝当前节点,还拷贝所有子节点

浅拷贝:  只拷贝当前节点,不拷贝子节点

(3) 拷贝的节点拥有和原节点一模一样的属性,但会丧失绑定在原节点上的事件。

例子:

var btn = document.querySelector('button');       
btn.onclick = function () {           
  var newBtn = btn.cloneNode(true);           
  document.body.appendChild(newBtn);       
};

V4. insertBefore()方法

描述:本方法用于将一个节点插入到当前节点的指定位置

语法:

var newNode = node.insertBefore(newNode, subNode);

说明:

(1) 第一个参数表示想要插入的新节点

(2) 第二个参数表示当前节点的某一个子节点

(3) 本方法在执行结束后,会将新节点作为执行结果返回。根据实际情况不是必须保存。

例子:

var h2 = document.createElement('h2');       
h2.innerHTML = '这是h2';   
    
//把h2标签插入到div2节点的前面       
var result = div1.insertBefore(h2, div2);       
console.log(div1.childNodes);       
console.log(result);

v5. removeChild()方法

描述:表示从当前节点中删除某个节点

语法:

var deleteNode = node.removeChild(deleteNode);

说明:本方法会返回删除的节点,根据实际情况可以不保存。

例子:

btn.onclick = function () {           
  if(div1.hasChildNodes()){           
    div1.removeChild(div1.firstChild);           
  }else{           
    alert('已经没有子节点了!');           
  }       
};

V6. replaceChild()

描述:表示将原节点中的某个旧节点,替换为新节点

语法:

var oldNode = node.replaceChild(newNode, oldNode);

注意:本方法会返回替换走的旧节点,根据实际情况可以不保存

例子:

btn.onclick = function () {           
  var textNode = document.createTextNode('已赞');           
  btn.replaceChild(textNode, btn.firstChild);           
  btn.setAttribute('disabled', 'disabled');       
};

7. contains()方法

描述:用来判断当前节点是否包含参数节点,包含返回true,否则返回false

语法:

node.contains(anotherNode);

说明:新创建的节点是被保存在内存中,只要没放到页面上就不被包含在页面内。

例子:

console.log(document.body.contains(div2));       
console.log(document.body.contains(div1));

8. isEqualNode()方法

描述:用来判断两个节点是否相等(属性相同,类型相同,子节点相同)

语法:nodeA.isEqualNode(nodeB);

例子:

console.log(div2.isEqualNode(div22));       
console.log(div2.isEqualNode(div1));       
console.log(span.isEqualNode(span2));

尺寸和位置

1.屏幕的尺寸和位置,通过screen对象获取;

screen === window.screen; //true;

//screen.width 屏幕的像素宽度 
console.log('屏幕的宽度---' + screen.width);

//screen.height 屏幕的像素高度  
console.log('屏幕的高度---' + screen.height);

//screen.availWidth 屏幕的可用宽度,Windows系统下,通常是去除任务栏宽度值  
console.log('屏幕的可用宽度---' + screen.availWidth);

//screen.availHeight 屏幕的可用高度,Windows系统下,通常是去除任务栏的高度值  
console.log('屏幕的可用高度---' + screen.availHeight);

//screen.availLeft 屏幕的最左边相对于主屏幕最左边的偏移值
console.log('距离左边的偏移值---' + screen.availLeft);

//screen.availTop 屏幕的最顶边相对于主屏幕最顶边的偏移值
console.log('距离顶边的偏移值---' + screen.availTop);

2.元素的尺寸和位置

页面中所有的元素都有基本的属性,其中有些基本属性与元素的位置和尺寸相关。元素位置相关的属性,都是相对位置,即元素相对于其偏移容器(offsetParent)的偏移量

var ele = document.getElementById("element"); //获取某一个元素

对于 offsetLeft 和 offsetTop 这两个值,是相对于偏移容器的。

1. 元素是通过 position 定位的: offsetLeft 和 offsetTop的值,是 left 值和 top 值。

2. 元素是通过 float 或者 margin 定位的:  offsetLeft 和 offsetTop 的值,是 margin-left 和margin-top 的值。

3.  如果同时存在,获取的是 left + margin-left 的值

// ele.offsetParent 获取偏移容器
console.log('偏移容器---', ele.offsetParent);

// ele.offsetLeft  元素相对与偏移容器的左边的偏移量
console.log('左边的偏移量---', ele.offsetLeft);

// ele.offsetTop  元素相对于偏移容器的顶边的偏移量
console.log('顶边的偏移量---', ele.offsetTop);

clientLeft 和 clienTop

获取元素边框,以像素表示。如果元素的文本内容方向是从右向左,并且元素内容有溢出,比如,<div dir="rtl">hello</div>,这样会在左边产生一个滚动条, 会包含滚动条的宽度,即是滚动条和边框的宽度之和

// ele.clientLeft  通常情况下是元素盒子的左边框的宽度
console.log('元素盒子的左边框宽度---', ele.clientLeft);

// ele.clientTop  通常情况下是元素盒子的顶边框的宽度
console.log('元素盒子的顶边框的宽度---', ele.clientTop);

scrollLeft 和 scrollTop

scrollLeft: 表示滚动条到元素左边(横向)的距离,可以用来设置内容区域滚动到某一位置,也可以获取当前滚动条的位置

scrollTop: 表示滚动条到顶边(纵向)的距离,可以用来设置内容区域滚动到某一位置,也可以获取当前滚动条的位置。

// ele.scrollTop  获取滚动条的高度
console.log('获取整个文档滚动条的高度---', ele.scrollTop);
console.log('获取整个文档滚动条的高度---', document.documentElement.scrollTop);

// ele.scrollLeft  获取滚动条的宽度
console.log('获取整个文档滚动条的宽度---', document.documentElement.scrollLeft);

// ele.scrollTop = 50  设置内容区域滚动到50的位置
document.documentElement.scrollTop = 50

window.outerWidth \ outerHeight
描述:返回浏览器大小,和页面窗口没有关系
例子:

console.log('outerWidth:' + window.outerWidth);
console.log('outerHeight:' + window.outerHeight);
window.innerWidth \ innerHeight
描述:返回浏览器中视口的大小,包括滚动条的大小
例子:

console.log('innerWidth:' + window.innerWidth);
console.log('innerHeight:' + window.innerHeight);
window.document.documentElement.clientWidth \ clientHeight
描述:返回浏览器中视口的大小,不包括滚动条
例子:

console.log('clientWidth:'+document.documentElement.clientWidth);
console.log('clientHeight:'+document.documentElement.clientHeight);
window.pageXOffset \ pageYOffset
描述:表示获取页面的滚动距离,是window的一个属性(只读,设置不会让页面受影响)
例子:

console.log('pageXOffset:'+window.pageXOffset);
console.log('pageYOffset:'+window.pageYOffset);
window.screenX / screenY
描述:表示页面左上角距离屏幕左上角的横纵坐标
例子:

console.log(window.screenX);
console.log(window.screenY);
window.navigator.userAgent属性
描述:表示返回浏览器内核相关信息,如果没有mobile则意味着pc端,如果有意味着移动端
例子:

console.log(window.navigator.userAgent);

querySelector系列方法与getElementsBy系列方法对比有什么不同?

(i) 两者的W3C标准不同

querySelector 系列属于W3C中的Selectors API(JS)规范

getElementsBy 系列则属于 W3C的DOM 规范。

(ii) 两者浏览器的兼容不同
querySelector 系列基本能被所有浏览器支持。
getElementsBy 系列则通常只有在考虑兼容性的时候才被提起(尽管两者功能近似)

(iii) 接受参数不同

querySelector 系列接收的参数是一个css选择器名。

getElementsBy 系列接收的参数只能是单一的 className、tagName 和 name。

(iv) 返回值不同
querySelectorAll() 返回的是一个静态节点列表(Static NodeList)

getElementsBy 系列的返回的是一个动态节点列表(Live NodeList)。

经典例子:

querySelector系列方法:

// 在循环内,尽管对ul产生了影响,但不会影响到变量list的值。

// 以为list在获取的那一刻值被保存起来,不受影响因此,有多少个li,就循环多少次

// 而通过querySelectorAll得到的这个列表,因为不受影响,因此称为静态节点列表

var ul = document.querySelectorAll('ul')[0];   
var list = ul.querySelectorAll('li');   
for(var i = 0; i < list.length ; i++){       
  ul.appendChild(document.createElement('li'));
}

getElementsBy系列方法:

// 在循环内,对ul产生了影响,并立即反映到了list之内。

// 通过getElementsBy系列方法的到的列表,会随着内容的变化而立即产生变化,不用重新赋值

// 那么这种不需要重新赋值,在内容变化后就会立即改变的列表,称为动态节点列表

var ul = document.querySelectorAll('ul')[0];   
var list = ul.getElementsByTagName('li');   
for(var i = 3; i < list.length ; i++){       
  ul.appendChild(document.createElement('li'));
}

扩展:框架集(被遗弃了)

框架及布局使用标签为frameset标签,本标签和body标签同级,二者同时只能存在一个!

(1) frameset 标签表示声明一个框架集(页面集合)

rows、cols 属性代表框架集中框架所占的宽高,单位可以是像素或百分比

(2) frame标签表示声明一个框架(页面)

src 属性代表框架要加载的页面的url地址

name 属性表示框架名称

(3) noframes 标签表示不支持框架集布局的页面显示提示信息用

例子:

<frameset rows="20%,*">   
  <noframes>对不起,您的浏览器不支持本页面布局方式,请更换更厉害的浏览器!</noframes>   
  <frame src="http://www.baidu.com"/>   
  <frameset cols="20%,*">       
    <frame src="leftSide.html"/>       
    <frame src="" name="rightSide"/>   
  </frameset>
</frameset>

iframe:内联框架

能够写在body里,和正常的元素一样显示的框架。

通过width,height设置宽高,

通过frameborder设置属性,

通过src设置显示内容

例子:

<a href="http://bbs.bjsxt.com" target="iframeMe">去论坛</a>
<iframe name="iframeMe" frameborder="1" width="500" height="400"></iframe>

事件概述

1.事件

描述:事件本质上是一种交互操作,经常配合函数使用。当事件发生时函数同时执行。

2.事件传递

描述:事件不仅能够和触发者进行交互,还能够在特定的情况下沿着domTree逐级传递,

和domTree中的各个节点进行交互。事件的这种特性称为【事件传递机制】

名词:

(1) (事件真正的)触发者:事件第一次在哪个节点上发生,这个节点就称为是触发者。

(2) 特定情况:domTree中其他节点也绑定了这个事件的情况

类型:

(1) 事件冒泡:事件从最具体的元素开始触发,沿domTree逐级向上传递,直到最不具体的节点停止

(2) 事件捕获:事件从最不具体的节点开始触发,沿domTree逐级向下传递,直到最具体的元素为止。

注意:

如非特殊强调,所有的事件传递都采用事件冒泡!

例子:

btn.onclick = function () {
  console.log('事件触发:按钮被点击!');
};       
div.onclick = function () {
  console.log('事件触发:div被点击!');
};       
document.body.onclick = function () {
  console.log('事件触发:body被点击!');
};       
document.documentElement.onclick = function () {
  console.log('事件触发:html被点击!');
};       
document.onclick = function () {
  console.log('事件触发:document被点击!'); 
};

事件绑定

1.html事件(html级事件)

描述:绑定操作发生在html代码中的事件,称为 html 事件

语法:

绑定:
on+事件名 = '函数1(); 函数2();...'

移除:
on+事件名 = null

注意:

(1) 所有html事件都采用冒泡传递

(2) 函数执行顺序按照绑定顺序为准

(3) 绑定多个函数的时候,函数应当采用分号隔开,而不是以分号结尾。

弊端:

(1) 耦合性太强

(2) 如果绑定函数未能正确加载,则会在触发事件的时候报错。

例子:

function func1(){  console.log('这是第1个函数');  }    
function func2(){  console.log('这是第2个函数');  }    
function func3(){  console.log('这是第3个函数');  }

<div onclick="func1(), func2(), func3()"></div>

document.querySelector('div').setAttribute('onclick', null);

2.DOM0事件(DOM0级事件)

描述:在脚本中通过 on+事件名 方式绑定的事件,称为 dom0 事件

语法:

添加:
元素节点.on+事件名 = function(){}

移除:
on+事件名 = null;

注意:

(1) dom0方式绑定的事件均为冒泡事件

(2) dom0方式只能给一个元素节点,一个事件绑定一个执行函数。

如果给一个事件绑定多个执行函数,则取最后绑定的函数为准

弊端:一次只能给一个事件绑定一个函数。

例子:

div2.onclick = function () { 
  console.log('div2被点击');
};       
div2.onclick = function () { 
  console.log('div2又被点击');
;       
div2.onclick = function () {  
  console.log('div2咋总被点击');  // 只有它生效
};

div2.onclick = null; // 移除点击事件,不是移除这个绑定函数。

3.DOM2事件(dom2级事件)

描述:在脚本中通过 addEventListener 函数绑定的事件,称为 dom2 事件

语法:

元素节点.addEventListener(type, listenFunc, useCapture);

参数:

(1) 第一个参数表示绑定事件的类型,没有on!是个字符串!

(2) 第二个参数表示监听函数,就是事件发生的时候执行的那个函数

(3) 第三个参数表示是否采用捕获机制,默认不写 和 false 都代表冒泡机制,true 代表捕获。

注意:dom2 事件允许绑定多个执行函数,并且执行顺序按照绑定顺序执行。

btn.addEventListener('click', function() {  console.log('1');});btn.addEventListener('click', function() {  console.log('2');});

移除:

通过 removeEventListener 函数移除绑定事件

node.removeEventListener('type', 外部函数名, useCapture);

注意:匿名函数无法移除,如果dom2事件想要移除,则必须通过外部函数名进行绑定事件。

例子:

function func(){       
    console.log('div2 的dom2事件函数');       
    div2.removeEventListener('click',func);       
};
div2.addEventListener('click', func);

鼠标事件

描述:通过鼠标操作触发的事件,称为鼠标事件

原则:

(1) 所有鼠标事件如非特殊说明,均为冒泡事件

(2) 可以给一个元素添加多个不同的鼠标事件,多个事件之间互不影响

(3) mouseenter 和 mouseleave 两个事件不冒泡,仅在当前节点触发。

类型:

(1) click 单击事件、dblclick 双击事件

div2.onclick = function () {
  console.log('这是div2上的单击事件');
};       

div2.ondblclick = function () {
  console.log('这是div2上的双击事件');
};

(2) mousedown 按下事件、mouseup 抬起事件、mousemove 移动事件

div2.onmousedown = function () {
  div2.style.backgroundColor = 'red';
};       

div2.onmouseup = function () {
  div2.style.backgroundColor = 'skyblue';
};       

div2.onmousemove = function () {
  console.log('鼠标移动事件触发');
};

(3) mouseenter 鼠标进入事件、mouseleave 鼠标离开事件 (常用)

div.onmouseenter = function () {
  console.log('鼠标进入!');
};

div.onmouseleave = function () {
  console.log('鼠标移出!');
};

(4) mouseover 鼠标进入事件(冒泡)、mouseout 鼠标离开事件(冒泡)

div2.onmouseover = function () {
  console.log('鼠标进入div2');
};

div2.onmouseout = function () {
  console.log('鼠标离开div2');
};       

(5) clientX 、clientY

获取鼠标的坐标!并设置div定位属性为鼠标坐标即可。

event.clientX   // 鼠标横坐标 
event.clientY   // 鼠标纵坐标

这两个属性在事件绑定的函数内容可以直接使用,但在外部无效,没有单位!!!!!

div.onmouseenter = function (e) {  console.log(e.clientX);}

文档事件

1. load、error 事件

描述:节点加载成功、节点加载失败之后自动调用的事件。

例子:

在 HTML 中:<body onload="fun1()">
<body onerror="fun1()">

在 JavaScript 中:window.onload=function(){  };
window.onerror=function(){  };

2.DOMContentLoaded

描述:页面 DomTree 构建完毕时自动触发

DomTree构建完毕:可以理解为除了外部图片、视频等文件没有加载之外,页面已经加载完毕

3.readystatechange

描述:当页面的readyState加载状态发生改变时,自动触发

4.文档加载顺序

解析HTML结构。

加载外部脚本和样式表文件。

解析并执行脚本代码。

DOM树构建完成。// DOMContentLoaded执行

加载图片等外部文件。

页面加载完毕。 // load执行

例子:

// 页面处于刚开始加载的状态
console.log(document.readyState);

// 给页面添加readyStateChange事件,当文档状态改变时自动触发
document.addEventListener('readystatechange', function () {
  console.log('文档加载状态发生改变:当前状态为:' + document.readyState);
});

//给页面添加DOMContentLoaded事件,当文档domTree构建完毕时自动触发
document.addEventListener('DOMContentLoaded', function () {
  console.log('文档DOM已经构建完毕');
});

//页面彻底加载完成时触发
window.onload = function () {   
  console.log('文档彻底加载完毕');
};

//图片资源加载完毕后,自动触发
document.querySelector('img').onload = function () {
  console.log('图片加载完毕!');
};

焦点事件

描述:焦点事件分为获得焦点事件 focus 和 失去焦点事件 blur

分别会在元素节点获得焦点和失去焦点时自动触发

语法:

获得焦点事件:
元素节点.onfocus = function(){}

失去焦点事件:
元素节点.onblur = function(){}

注意:

(1) 焦点事件可以使用dom0绑定也能使用dom2绑定。

(2) 焦点事件不支持冒泡传递。

例子:

var input = document.querySelector('input');    
   
input.onfocus = function () {
  console.log('获得了焦点');
};       
input.onblur = function () {
  console.log('失去了焦点');
};

滚动事件scroll

描述:滚动事件是指当页面 或 元素发生滚动时,自动调用的事件

(1) 页面滚动事件

内容:scrollTop、scrollLeft 表示页面的滚动距离(没有单位)

语法:

document.documentElement.scrollTop \ scrollLeft

注意:页面滚动距离不仅能够读取,还能够设置。

例子:

// 点击按钮,滚动到1000的距离document.querySelector('button').onclick = function () {  document.documentElement.scrollTop = 1000;};// 给文档添加滚动事件,当文档滚动时本事件自动发生。window.onscroll = function () {  // 滚动事件调用一次,就输出一次滚动距离  console.log(document.documentElement.scrollTop);};

(2)元素滚动事件

描述:元素发生滚动时,自动调用的事件

内容:获取元素的滚动距离

元素节点.scrollTop \ scrollLeft

注意:元素滚动如果想要发生,那么元素至少应该存在滚动条

例子:

button.onclick = function () {       
  // 让div回到顶部       
  div.scrollTop = 0;   
};

键盘事件

描述:由用户操作键盘触发的事件称为键盘事件

注意:键盘事件采用冒泡传递。

说明:一般情况下键盘事件会绑定给 input 或者 textarea 元素,但是因为键盘事件支持冒泡机制,因此直接绑定给 body 也是可以的。

类型:

(1 ) keydown:键盘按键在按下时触发的事件。如果按住不放则连续触发。

(2) keyup:键盘按键在抬起时触发的事件。

(3) keypress:键盘在按下(可显示的)按键时触发的事件,如果按住不放则连续触发, 能够识别大小写

(4) keyCode : 在键盘事件中获取按下按键的编码值

例子:

document.body.onkeydown = function () {       
  console.log('keydown:' + event.keyCode);       
};       

document.body.onkeyup = function () {
  console.log('键盘已抬起!')
}

document.body.onkeypress = function () {       
  console.log('keypress:' + event.keyCode);       
};

触摸事件

描述:在移动端设备中由触摸操作触发的事件,称为触摸事件

注意:触摸事件在PC端不生效

类型:

(1) touchstart  当手指触摸屏幕时触发;即使已经有一个手指放在了屏幕上也会触发。

(2) touchmove  当手指在屏幕上滑动时连续的触发。

(3) touchend  当手指从屏幕上移开时触发。

(4) touchcancel  当系统停止跟踪触摸时触发,如电话接入或者弹出信息,一般在这个操作中来做一些暂停游戏类的操作

强调:

(1) 如非特殊说明,事件均为冒泡事件

(2) 手机触摸事件必须使用dom2来进行绑定

(3) 可以给一个元素添加多个触摸事件

例子:

document.body.addEventListener('touchstart', function () {
  console.log('touchstart----触摸到一个 DOM 元素时触发');
});

document.body.addEventListener('touchmove', function () {
  console.log('touchmove-----滑动时触发');
});

document.body.addEventListener('touchend', function() {
  console.log('touchend从一个 DOM 元素上移开时触发');
});

2.获取触摸点的坐标

这三个事件又分别对应三个相同的触摸列表:

touches:正在触摸屏幕的所有手指的一个列表

targetTouches:正在触摸当前 DOM 元素上的手指的一个列表

changedTouches:涉及当前事件的手指的一个列表。

document.body.addEventListener('touchstart', function () {  console.log(event.touches);  console.log(event.targetTouches);  console.log(event.changedTouches);});

事件返回的 TouchList 列表。它对应的就是前面提到的三种事件(touchstart、touchmove、touchend)中的一种,在触发时生成的一个对象列表。列表里最有用的就是 Touch 对象了,Touch 对象里存放着对应事件的一些相关的信息,我们就是通过这种个事件里这些属性的有机结合来实现各种效果,都是只读属性!

TouchList {0: Touch, length: 1}
length:1
0:Touch
    clientX:65 // 触摸点在浏览器窗口中的横(x)坐标
    clientY:18 // 触摸点在浏览器窗口中的纵(y)坐标
    force:1 // 触摸点压力大小
    identifier:0 // 触摸点唯一标识(ID),可以根据它来判断跟踪的是否是同一次触摸过程
    pageX:65 // 触摸点在页面中的横坐标
    pageY:18 // 触摸点在页面中的纵坐标
    radiusX:11.5 // 触摸点椭圆的水平半径
    radiusY:11.5 // 触摸点椭圆的垂直半径
    rotationAngle:0 // 旋转角度
    screenX:560 // 触摸点在屏幕中的横坐标
    screenY:175 // 触摸点在屏幕中的纵坐标
target:div#touchLog 触摸目标
__proto__:Touch
__proto__:TouchList

通过上面的 radiusX,radiusY,rotationAngle 这三个属性就可以计算出你的手指触摸手机屏幕时的一个接触面,只不过这个接触面是用一个近似的椭圆来表示,也就是说它不是一个真正意义上的接触面,而是一个大概的接触面。相信心细的朋友应该会看到 TouchList 对象里有一个 length 属性,并且它的值为 1 ,这说明当前只有一个手指触发了事件(比如:touchstart 事件),换句话说,此时你只有一个手指放到了手机屏幕上,这个手指对应的一些信息存放在 Touch 对象里。因为只有一个手指放在了屏幕上,所以这个 TouchList 里只有一个 Touch 对象,并且是第一个下标为 0 。TouchList 列表里还有一个 target 属性,这个应该很好理解,就是触摸的目标。

this对象

(1) 对于直接调用来说,不管函数被放在了什么地方, this 一定是 window对于

(2) 对象中的函数来说,谁调用了函数,谁就是 this 

(3) 对于 new 的方式来说, this 被永远绑定在了对应 new 上面,不会被任何方式改变 this

(4) this在闭包中:闭包中的 this 指向window

(5) 延时器和定时器调用中的 this 指向window

(6) 事件中的this:

HTML:this 指向 window

DOM0:this 指向绑定该事件的元素

DOM2级:this 指向绑定该事件的元素

(7) 自执行函数: this 指向 window

(8) call 和 apply 和 bind 函数:第一个参数是谁,this指向谁

(9) 箭头函数里面的 this 在它申明时确定,跟他当前作用域的 this 一样

(10) 严格模式下,函数里面的 this 指向 undefined,函数外面(全局作用域)的this还是指向window

1. fn()
this => window

2. obj.fn()
this => obj

3. fn.call(xxx)
this => xxx

4. fn.bind(xxx)
this => xxx

5. fn.apply(xxx)
this => xxx

6. new Fn()
this => 新的对象

7. fn=()=>{}
this => 外面的this

event对象

描述:当 domTree 中某个事件发生时,

同时【自动产生】的一个用来描述【事件发生时所有信息】的对象,称为事件对象。

获取:

(1) 在脚本中直接通过关键词event来获取

btn.onclick = function () {
  console.log(event); // MouseEvent {....}
  console.log(typeof event); // object
};

(2) 在添加事件监听时,通过绑定函数传参形式获取。一般形参为e或者eve.

注意:event 对象实际上是 window 浏览器对象的一个属性,因此在外部也能直接使用。

只不过在事件之外访问的时候没有内容,是空值没意义,因此习惯上还是在事件函数内部使用。

btn.onclick = function (e) {
  console.log(e); // MouseEvent {isTrusted: true, screenX: 21, screenY: 113, clientX: 21, clientY: 19, …}altKey: falsebubbles: truebutton: 0buttons: 0cancelBubble: falsecancelable: trueclientX: 21clientY: 19composed: truectrlKey: falsecurrentTarget: nulldefaultPrevented: falsedetail: 1eventPhase: 0fromElement: nullisTrusted: truelayerX: 21layerY: 19metaKey: falsemovementX: 0movementY: 0offsetX: 11offsetY: 7pageX: 21pageY: 19path: (5) [button, body, html, document, Window]relatedTarget: nullreturnValue: truescreenX: 21screenY: 113shiftKey: falsesourceCapabilities: InputDeviceCapabilities {firesTouchEvents: false}srcElement: buttontarget: buttontimeStamp: 603.3699996769428toElement: buttontype: "click"view: Window {parent: Window, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …}which: 1x: 21y: 19__proto__: MouseEvent
  console.log(event); // MouseEvent {isTrusted: true, screenX: 21, screenY: 113, clientX: 21, clientY: 19, …}altKey: falsebubbles: truebutton: 0buttons: 0cancelBubble: falsecancelable: trueclientX: 21clientY: 19composed: truectrlKey: falsecurrentTarget: nulldefaultPrevented: falsedetail: 1eventPhase: 0fromElement: nullisTrusted: truelayerX: 21layerY: 19metaKey: falsemovementX: 0movementY: 0offsetX: 11offsetY: 7pageX: 21pageY: 19path: (5) [button, body, html, document, Window]relatedTarget: nullreturnValue: truescreenX: 21screenY: 113shiftKey: falsesourceCapabilities: InputDeviceCapabilities {firesTouchEvents: false}srcElement: buttontarget: buttontimeStamp: 603.3699996769428toElement: buttontype: "click"view: Window {parent: Window, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …}which: 1x: 21y: 19__proto__: MouseEvent
};

event对象的常用属性和方法

(1) type 属性

描述:表示发生的事件类型,本属性只读

语法:

event.type

(2) bubbles 属性

描述:用来获取当前触发的事件是否支持冒泡,支持返回true,不支持返回false。

语法:

event.bubbles

例子:

btn.onclick = function (e) {
  console.log(e.bubbles); // true
  e.stopPropagation();  //阻止事件传播
};

(3) eventPhase 属性

描述:获取事件传导至当前节点时,所处于的状态

说明:本属性为只读属性,有三个可能值

返回 1 表示事件在当前节点处于捕获状态

返回 2 表示当前节点是事件的真正触发者

返回 3 表示事件在当前节点处于冒泡状态

例子:

// 冒泡状态
btn.onclick = function (e) {
  console.log('冒泡状态btn:' + e.eventPhase);
};
document.body.onclick = function (e) {
  console.log('冒泡状态body:' + e.eventPhase);
};
document.onclick = function (e) {
  console.log('冒泡状态document:' + e.eventPhase);
};

// 捕获状态
btn.addEventListener('click', function (e) {
  console.log('捕获状态btn:' + e.eventPhase);
}, true);
document.body.addEventListener('click', function (e) {
  console.log('捕获状态body:' + e.eventPhase);
}, true);
document.addEventListener('click', function (e) {
  console.log('捕获状态document:' + e.eventPhase);
}, true);

v(4) target 属性

描述:获取事件的真正触发者。

语法:eve.target

注意:在现在阶段,事件内部可以认为 eve.target 等同于 this 的作用。

例子:

btn.onclick = function (e) {
  console.log(e.target) // 返回 btn
}

v(5) currentTarget 属性

描述:获取事件的监听者(当前触发者)

语法:eve.currentTarget

注意:事件在哪个节点触发,currentTarget 属性就是谁

例子:

btn.onclick = function (e) {
  console.log(e.currentTarget) // 返回 btn
}

v(6) stopPropagation() 方法

描述:能够阻断事件从当前节点传播到下一个节点。

语法:

eve.stopPropagation();

例子:

document.body.onclick = function (e) {
  e.stopPropagation();
}; 

v(7) preventDefault ()

描述:能够阻断(取消)当前节点的默认行为

语法:

eve.preventDefault();

例子:

var anchor = document.querySelector('a');       
anchor.onclick = function (e) {       
 e.preventDefault();       
};

v(8) cancelable 属性

描述:用来判断当前节点能否取消默认行为,true表示能够取消

语法:

eve.cancelable

例子:

div2.onclick = function (e) {           
  if( e.cancelable ){           
    e.preventDefault();           
  }else{           
    console.log('当前节点不存在默认行为,无需取消!');           
  }       
};

BOM概述

描述:bom是浏览器对象模型(browser Object model),是由一组对象构成的规则。

注意:bom的核心对象是window对象,window对象相当于浏览器窗口

说明:

(1) BOM包括了DOM

(2) BOM处理页面之间的交互,而DOM处理页面之内的交互。

(3) BOM没有统一的规则

window对象

1.window对象

描述:window对象可以理解为浏览器窗口

注意:所有定义在全局作用域中的变量、函数都会变成window对象的属性和方法,

在调用的时候可以省略window。

2.window的常见属性和方法

(1) window.name

描述:是一个在页面切换之后,甚至域名变更之后仍然会存在的容器。

说明:借助window.name可以实现页面与页面之间的数据传递,称为【跨域传输】

例子:

//如果想要获取一个页面内的信息,那么这个页面必须加载。
var btn = document.querySelector('button');

btn.onclick = function () {
  var iframe = document.createElement('iframe');
  iframe.src = '(3)anotherPage.html';//加载保存了信息的页面
  iframe.style.display = 'none';
  document.body.appendChild(iframe);

  //当iframe加载完毕,意味着window.name的内容已经被赋值完毕了
  iframe.onload = function (eve) {
    var iframeWindowName = eve.target.contentWindow.name;
    eval(iframeWindowName);
    console.log(num);
  }
};

浏览器中的警示框

1. alert() 方法

描述:alert() 是window提供的一个,用来提示用户信息的方法。

语法:

alert(string);

注意:

(1) 本方法没有返回值(返回值是undefined)

(2) alert() 方法弹出的对话框是模态对话框,在对话框关闭之前程序暂停,直到关闭后才继续执行

例子:

alert('提示信息!');

2. prompt() 方法

描述:prompt() 也是 window 提供的一个,用来提示并收集用户信息的方法

语法:

prompt(text, defaultText);

// text 可选, 要在对话框中显示的纯文本// defaultText 可选, 默认要输入文本

(1) 如果直接点击取消按钮,则返回null注意:

(2) 如果有默认参数并直接点确定,则返回默认参数。如果输入内容则返回输入的内容。

(3) 如果没有默认参数并直接点确定,则返回空字符串。如果输入内容则返回输入内容。

(4) prompt() 方法弹出的对话框是模态对话框,在对话框关闭之前程序暂停,直到关闭后才继续执行

例子:

btn.onclick = function () {
  let result = prompt('你是who?');
  console.log(result);
}

3. confirm() 方法(最常见)

描述:window 提供的一个用来提示用户信息的方法

语法:

confirm(text);// text 可选,要在对话框中显示的纯文本

注意:

(1) 点击确认按钮返回true,取消按钮返回false

(2) confirm() 方法弹出的对话框是模态对话框

例子:

btn.onclick = function () {
  let result = confirm('是否要删除?');
  console.log(result);
}

定时器 / 延迟器

1. 间隔调用 (定时器)

描述:本方法的特征是能够自动每间隔一定时间,调用一次指定函数。

语法:

var timer = null;   
timer = setInterval(间隔调用的函数,执行函数的间隔ms);

移除:
clearInterval()

例子:

var timer = null;

timer = setInterval(function(){
  console.log('hi,nimabi');
},2000);

// es6 箭头函数写法(推荐)
timer = setInterval(() => {
  console.log('hi,nimabi');
}, 1000)

// clearInterval(timer); 

扩展:

(1)setInterval 方法放回的是一个数字队列,创建定时器的序号。

清除定时器的时候可以直接通过数字队列来清除定时器。

例子1:

setInterval(function(){ console.log('hi,1'); }, 2000);           
setInterval(function(){ console.log('hi,2'); }, 2000);           
setInterval(function(){ console.log('hi,3'); },2000);   
// 清除第一个和第二个        
clearInterval(1);           
clearInterval(2);

(2)如果使用间隔调用的函数是一个带参函数,则声明部分需要采用下列的方式。

例子:

var timer = null;           
function showWord(abc){
  console.log(abc);           
};           
timer = setInterval('showWord("你好")',2000);

(3) 在定时器内部,函数的真正调用者是 window

使用箭头函数,它的 this 继承上级的 this

var timer = null;       
setInterval(function(){              
  console.log(this);  // window     
},2000);

setInterval(() => {
  console.log(this);  // 继承上级的 this
},2000);

(4) 定时器在创建完毕后不会立刻开始执行,而是会等待【任务队列中任务执行完毕】之后在开始执行。

var timer1 = null;       
timer1 = setInterval(function(){
  console.log('hi1');
},2000);   //后       
console.log(timer1);   //先

2. 延迟调用 (延迟器)

描述:表示函数等待一定时间后在执行

说明:除了语法结构和表示的含义不同之外,其余注意事项全和定时器一样

语法:

var timer = null;   
timer = setTimeout(间隔调用的函数,执行函数的间隔ms);

例子:

var timer = null;   
timer = setTimeout(function(){
  console.log('这是一个延迟调用');
} , 2000); 

移除:
clearTimeout (延迟器表示);

页面加载顺序

1.defer

让这个外部脚本在dom加载完毕后,在加载

避免了因外部引入文件过大或网络卡顿造成的【文件阻塞】

<script src="js/myJs.js" defer></script>

2.async

让外部脚本和dom同时加载,异步执行

弊端:不能确定谁先加载完成。

<script src="js/myJs.js" async></script> 

3.以上两个script的属性,仅对外部脚本生效。

回流和重绘

1.重绘(repaint) 和 回流(reflow)

描述:

重绘:页面中元素发生可见性的变化,导致页面重新渲染的现象称为重绘

回流:页面中元素发生位置或尺寸的变化,导致部分页面或整个页面重新加载的现象称为回流

说明:

(1) 回流必将引起重绘,但重绘不一定引发回流

(2) 这两个现象都是浏览器加载页面时可能导致加载变慢的问题,要尽可能的避免

2.减少回流和重绘的途径

描述:因为页面中各种操作基本都会引发回流和重绘,因此完全避免是不可能的。

所以为了提高浏览器性能,我们要尽可能的减少引发他们的状况。

途径:

(1) 不要一项一项的去改变样式,尽可能一口气写完。(可以写在一起,不要被打断就行)

最好使用 .style 或者 .style.cssText

(2) 读写dom操作尽量放在一起

(3) 当大量读写dom操作无法避免的时候,可以使用文档碎片节点doucmentFragment来解决问题。

(4) 使用fixed和absolute能够减少回流和重绘

window.history对象

描述:表示页面栈对象

说明:栈区特征为【后进先出】,堆区特征为【先进先出】。

内容:

(1) window.history.back() 跳转到栈中的上一个页面

(2) window.history.forward() 跳转到栈中的下一个页面

(3) window.history.go(num) 跳转到栈中的指定页面

(4) window.history.length 栈中页面的数量

注意:

通过window.history对象中提供的方法进行的页面跳转并不会向栈中添加新的页面。

而通过window.location.href或者通过a标签进行的跳转,则会向栈中添加新的页面。

补充:

栈区特征是【后进先出】,不仅仅意味着后添加的内容先被移除栈,

还意味着栈中的内容如果想要添加到指定位置,必须先将其之前的内容先退栈才行!

call 、bind 、 apply 更改 this 指向

call 、bind 、 apply 是为了改变this的指向而存在的,第一个参数为必要参数,剩余参数为可选参数

apply 第一个为this指向,后面的都是所带的参数(参数都必须放在一个数组里)

.apply(this指向, ['参数'...])

call 第一个为this指向,后面的都是所带的参数

.call(this指向, '参数'...)
bind 第一个为this指向,它的参数和 call 一样,但是最后还要一个小括号调用它

.bind(this指向, '参数'...)()

例子:

let name = '王子成';
let age = 20;
var A = '我是外面的哈哈哈';  // 用 let 定义对象里面无法获取

const obj = {
  name: 'obj-wzc',
  age: 10,
  A: '我是obj的哈哈哈',
  B: this.A,
  myFun1 (b) {
    console.log(`${this.name}的年龄是${this.age}, A:${this.B}, 用的方法${b}`)
  },
  myFun2 (a, b) {
    console.log(`${this.name}的年龄是${this.age},他来自${a}, 用的方法${b}`)
  }
};

const db = {
  name: '狗子',
  age: 20
};

obj.myFun1('直接调用'); // obj-wzc的年龄是10,他来自中国, 用的方法直接调用
obj.myFun2.call(db, '中国', 'call()'); // 狗子的年龄是10,他来自中国, 用的方法call()
obj.myFun2.bind(db, '中国', 'bind()')(); // 狗子的年龄是10,他来自中国, 用的方法bind()
obj.myFun2.apply(db, ['中国', 'apply()']); // 狗子的年龄是10,他来自中国, 用的方法apply()

闭包

描述:本质上是一种将【函数内部】和【函数外部】连接起来的手段

作用:

(1) 允许在函数外部,访问函数内部的局部变量。

(2) 将局部变量的生存周期延长至全局作用域,避免被垃圾回收机制杀死。

注意:

(1) 不要滥用闭包,因为可能导致变量内存不释放从而导致内存泄露

(2) 闭包的实际调用者都是window,所以闭包中的this均指向了window

例子:

function func() {
  var num = 999;
  return function () {
    console.log(num);
  };
}
var result = func();
result(); // 999

类和对象

描述:

(1) 类是一种抽象的,并不实际存在的,表示一种事物共有特征的描述。

(2) 对象是一种具体的,实际存在的,类中的某一个个体。

JS中通过构造函数的帮助制定类。通过【new命令调用构造函数】创建类中的对象

语法:

function 类名 (对象属性值1,对象属性值2,...){
  this.对象属性1 = 对象属性值1;
  this.对象属性2 = 对象属性值2;
  ...
}

var 对象 = new 类名(实际属性1,实际属性2,...);

作用:

快速构建对象,不必每次创建对象都重新编写对象结构。

例子:

function People(pname, page, pheight, pabilibty){
  this.userName = pname;
  this.userAge = page;
  this.userHeight = pheight;
  this.userAbility = pabilibty;
}

var frank = new People('张先森', '18', '180', function () {console.log('变得帅');});
console.log(frank);  // People {userName: "张先森", userAge: "18", userHeight: "180", userAbility: ƒ}

面向过程思想与面向对象思想

1.面向过程思想

描述:解决问题围绕【如何解决】来开展编程,核心是找到解决问题的方法(函数)

2.面向对象思想

描述:解决问题围绕【谁能解决】来开展变成,核心是找到解决问题的对象

说明:JS本身是面向过程的语言,只不过为了解决面向对象的问题,提出了各种手段来模拟面向对象

3.面向对象中,对象的特征:“公有、私有”

公有:对象中的属性和方法,在对象外部能够直接访问,这样的属性和方法就称为公有属性和公有方法

私有:对象中的属性和方法,仅能在对象内部访问,在对象外不不能直接访问,需要通过特权函数才能访问,这样的属性和方法称为私有属性和私有方法

特权函数:在JS中对象能够用来访问内部局部变量的函数,使用特权函数来模拟私有的赋值调用过程

例子:

function People(pname, pability){
  //JS用局部变量来模拟私有属性和私有方法
  var secret = '梦';
  this.getSecret = function () {
    console.log(secret);
  };

  //公有属性
  this.pname = pname;
  this.pability = pability;
}

var frank = new People('张先森', function () {
  console.log('吃了睡睡了吃');
});

//公有属性和公有方法能够在对象之外直接访问
console.log(frank.pname); // 张先森
frank.pability();  // 吃了睡睡了吃

//私有属性不能在对象之外直接访问,私有方法可以
console.log(frank.secret)  // undefined
frank.getSecret();  // 梦

原型

描述:原型 prototype 是 JS 为函数提供的一个对象类型的属性。

说明:向原型中添加的属性和方法,能够被【由类创建的对象】共同拥有。

注意:本属性不需要手动添加,prototype 属性自动被所有的函数拥有,直接使用就可以。

本质:本质上原型的存在就是为了给类的对象添加公有属性

补充:

JS中提供了一种属性访问机制

(1) 如果是通过类创建的对象,在访问属性的时候会先去对象本身内查找。

(2) 如果没有找到,则会去【创建这个对象的类】的原型中查找。

如果在原型内找到了这个属性,也相当于这个对象拥有这个属性。

语法:

function 类名(公有属性值1,公有属性值2,...){
  var 私有属性名1:'私有属性值1',
  var 私有方法1:function (){},
  this.公有属性名1:公有属性值1,
  this.公有属性名2:公有属性值2,
  ...
}
类名.prototype.公有属性3 = 公有属性值3;

例子:

function People(pname, page, pability) {

  //私有属性
  var secret = '梦';

  //公有属性(大家都有的,但是内容不相同的公有属性)
  this.pname = pname;
  this.page = page;
  this.pability = pability;

  //特权函数(特权函数实际上也是公有的,只不过特殊之处在于能够读写私有属性)
  this.getSecret = function () {
    return secret;
  };
  this.setSecret = function (newSecret) {
    secret = newSecret;
  };

}

//公有属性(大家都有的,而且内容都一样的公有属性)
var frank = new People('张先森', 18, function () {
  console.log('我能白话!');
});

console.log(frank.pname); // 张先森
console.log(frank.page); // 18
frank.pability(); // 我能白话!

frank.setSecret('成为刘诗诗的老公!');
console.log(frank.getSecret());  // 成为刘诗诗的老公!

People.prototype.eyesNum = 2;
console.log(frank.eyesNum); // 2

2.原型相关的知识

结构:JS为原型提供了两个默认的属性

(1) constructor 构造器:指向这个类本身(指明了原型归哪个类所有)

(2) __proto__ 原型指向:指向这个原型本身,提供给【类创建的对象】使用。

弊端:原型中不能保存数组这类引用类型的数据,

因为地址传递的问题会导致出现修改的连锁变化

例子:

function fun1 () {};

// 构造器
console.log(fun1.prototype.constructor); // f ()

// 原型指向
console.log(fun1.__proto__); // ƒ () { [native code] }
console.log(fun1.__proto__ === Function.prototype); // true

原型链

描述:【对象的__proto__属性】和【对象的构造函数的原型的__proto__属性】

构成的链式结构称为原型链

白话:对象的原型,跟他父类的原型绑在一起,拧成一根链子。那么这根链子就称为原型链

注意:

(1) 原型链的顶端是Object

(2) Object类的原型(Object.prototype)没有__proto__属性。

作用:

访问对象的属性的时候,先在对象本身中查找;

如果在对象中没能找到这个属性,则会沿着原型链逐级向上查找,

在原型链的任何一级如果找到这个属性,都视同对象拥有这个属性。

-------被称为是【继承】

构建:设置子类的prototype属性是父类的实例,即可构建原型链

例子:

// 构建原型链的代码
// 创建一个类,添加一个公有属性叫money
function Father() { }
Father.prototype.money = '数不清';

var mayun = new Father();

//创建一个类,并将prototype属性赋值为Father类的一个对象
function Son() { }
Son.prototype = mayun;

//创建一个Son类的对象
var frank = new Son();

console.log(frank.money);  // 数不清

设计模式

1.工厂模式

弊端:创建的对象无法确定归属于哪一个类

例子:

function Car(lun1, lun2, lun3, lun4, ability) {
  var car = {};
  car.lun1 = lun1;
  car.lun2 = lun2;
  car.lun3 = lun3;
  car.lun4 = lun4;
  car.ability = ability;

  return car;
}

var car1 = Car('左前轮1', '右前轮1', '左后轮1', '右后轮1', '会跑1');

console.log(car1 instanceof Car); // false
console.log(car1); // {lun1: "左前轮1", lun2: "右前轮1", lun3: "左后轮1", lun4: "右后轮1", ability: "会跑1"}

2.构造函数模式

弊端:面对共有的,属性相同的公有属性,没办法一次写清,必须每次都为这个属性分配内存。

例子:

function Car(lun1, lun2, lun3, lun4, ability) {
  this.lun1 = lun1;
  this.lun2 = lun2;
  this.lun3 = lun3;
  this.lun4 = lun4;
  this.ability = ability;
}

var car1 = new Car('前左轮1', '前右轮1', '后左轮1', '后右轮1', '能开1');
console.log(car1 instanceof Car); // true

3.原型模式

弊端:省内存到极致的问题就是,面对不同属性值的公有属性时,反而增加了内存的负担

例子:

// 构造函数
function Person() { };
Person.prototype.name = '张三';
Person.prototype.sayName = function () {
  console.log(this.name);
};

let person1 = new Person();
person1.sayName(); //张三

let person2 = new Person();
person2.sayName(); // 张三

console.log(person1.sayName == person2.sayName); //true

4.混合模式

弊端:没办法在每一个领域做到完美

例子:

function Car(lun1, lun2, lun3, lun4) {
  this.lun1 = lun1;
  this.lun2 = lun2;
  this.lun3 = lun3;
  this.lun4 = lun4;
}

Car.prototype.ability = function () {
  console.log('爷会飞');
};

var car1 = new Car('左前轮1', '右前轮1', '左后轮1', '右后轮1');
var car2 = new Car('左前轮2', '右前轮2', '左后轮2', '右后轮2');

car1.ability(); // 爷会飞
car2.ability(); // 爷会飞

5.动态原型模式

// 懒加载:使用的时候才加载并占有内存,不使用的时候就相当于不存在。

function Car(lun1, lun2, lun3, lun4) {
  this.lun1 = lun1;
  this.lun2 = lun2;
  this.lun3 = lun3;
  this.lun4 = lun4;

  // Car中没有_initialized时
  if (typeof Car._initialized == 'undefined') {

    // 原型中的内存仅会在调用函数的时候才被占用,如果函数一直不被使用,则原型就一直不会占有内存。
    Car.prototype.ability = function () {
      console.log('爷会飞');
    };
    Car._initialized = true;

  }

}

var car1 = new Car(['左前轮1', '右前轮1', '左后轮1', '右后轮1']);
var car2 = new Car(['左前轮2', '右前轮2', '左后轮2', '右后轮2']);

car1.ability() // 调用时它才会占用

正则表达式

描述:正则表达式是一种检索字符串的规则,经常表现为字符串的样子

语法:

/正则表达式主体/修饰符(可选)

本质:正则表达式本质上是对象类型,只不过表现为字符串的样子

例子:

// 规则:检索frank字符串
var reg1 = /frank/;
//规则:忽略大小写的,检索frank字符串
var reg2 = /frank/i;

console.log(typeof reg1); // object
console.log(typeof reg2);  // object

修饰符

描述:修饰符是检索字符串时规则的制定者之一,修饰符表示应当按照何种规则进行检索。

类型:常见的修饰符有三种 i g m

说明:

(1) i 修饰符:代表了【忽略大小写】的规则

(2) g 修饰符:代表了【全局匹配】的规则

(3) m 修饰符:代表了【换行匹配】的规则,对^$字符有影响。

正则表达式的用法

(1) search() 方法

描述:正则表达式在 search 中表示制定规则,让 search 在字符串中检索【符合正则制定的规则】的字符串

a. 如果找到返回第一次出现的下标

b. 如果查找失败,返回-1

例子:

var str = 'hello World! goodbye world!';
var index = str.search(/world/i);
console.log(index); // 6

(2) replace() 方法

描述:让 replace 根据参数一的规则进行查找,并将【满足规则一的所有内容】替换为参数二

强调:replace 方法本身不会改变原字符串,而是会生成一个新的字符串

例子:

var str = 'hello World! goodbye world!';           
var newStr = str.replace(/world/gi, '(frank)');   
        
console.log(newStr); // hello (frank)! goodbye (frank)!
console.log(str); // hello World! goodbye world!

(3) match() 方法

描述:

(a.) match 能够匹配,符合参数规则的字符串第一次出现的信息

var str = 'hello World! goodbye world!';

var info = str.match(/world/i);
console.log(info); // ["World", index: 6, input: "hello World! goodbye world!", groups: undefined]

(b.) match 能够匹配【所有符合参数规则的子字符串】,并构成集合返回

var str = 'hello World! goodbye world!';//只有存在修饰符g的时候,match才会返回集合var info = str.match(/world/gi);console.log(info); // (2) ["World", "world"]

检索模式

描述:检索模式是指【正则表达式主体】可以采用何种方式编写,也是规则的制定者之一

类型:表达式模式、元字符模式、量词模式

注意:

a.检索模式中的几种模式可以混合使用,来达到精确制定规则的效果

b.在正则主体当中一个[]中括号代表一个字符,一个()小括号代表一个词组

(1) 表达式模式

描述:表达式模式是指【通过表达式书写来制定检索规则】的方式

类型:[abc]、[0-9]、(m|n)

(a.) [abc]模式

描述:本模式代表的规则是【存在于方括号中,即满足】

注意:本模式是针对于正则主体使用的,因此中括号必须写在正则主体中才生效

例子:

// 规则为:全局中忽略大小写检索单个字符,单个字符只要是 (a 或者 b) 之一即满足
var str = '12abc12ABC';
var newStr = str.replace(/[ab]/gi,'(frank)');
console.log(newStr);  // 12(frank)(frank)c12(frank)(frank)C

// 规则为:全局中忽略大小写检索两个挨在一起的字符
// 第一个必须是 (1 或者 2),第二个必须是 (a 或者 b)
var str = '12abc12ABC';
var newStr = str.replace(/[12][ab]/gi,'(frank)');
console.log(newStr); // 1(frank)bc1(frank)BC

(b.) [0-9]模式

描述:本模式代表的规则是【存在于范围内,即满足】

注意:范围前面的必须小于后面的,否则会报错!

例子:

// 规则为:全局中忽略大小写检索两个挨在一起的字符
// 第一个必须是 (1 或者 2),第二个必须是 0-9 的数字var str = '137abc125abc';         
var newStr = str.replace(/[135][0-9]/gi,'(frank)');         
console.log(newStr); // (frank)7abc(frank)5abc

(c.) (m|n)模式

描述:本模式代表的规则是【符合以|分隔的选项之一,即满足】

注意:本模式可以匹配的不仅仅是字符,还可以是词组

例子:

// 规则为:全局中忽略大小写检索挨在一起的字符或者词组
// ab 或者 ABC
var str = '12abc12abABC';         
var newStr = str.replace(/(ab|ABC)/g,'(frank)');         
console.log(newStr);  // 12(frank)c12(frank)(frank)

(2)元字符模式

描述:元字符模式是指通过元字符进行字符串检索的模式

类型:\d、\s、\b、\w、\W、...

注意:一个元字符代表一个字符

(a.) \d元字符

描述:\d代表的规则是【是数字,即满足】

例子:

var str = '12abc12abABC';         
var newStr = str.replace(/\d/g,'(frank)');         
console.log(newStr); // (frank)(frank)abc(frank)(frank)abABC

(b.) \s元字符

描述:\s代表的规则是【是空格,即满足】

例子:

var str = ' 12abc 12ab ABC ';         
var newStr = str.replace(/\s/g,'(frank)');         
console.log(newStr);//(frank)12abc(frank)12ab(frank)ABC(frank)

(c.) \b元字符

描述:\b代表的规则是【是词语边界,即满足】

例子:

var str = '12abc 12ab ABC';         
var newStr = str.replace(/\b/g,'(frank)');         
console.log(newStr);  // (frank)12abc(frank) (frank)12ab(frank) (frank)ABC(frank)

(d.) 其他:

. 匹配任何单个字符,除了换行

\D 非数字

\S 非空白

\w 数字 字母 下划线 \W 非 [0-9a-zA-Z_]

\n 换行

\t 制表符

(3)量词模式

描述:通过设置量词进行内容检索的模式称为量词模式

量词:能够描述内容出现次数的词语(+\*\?)

注意:量词通常不单独作为正则主体,而是会配合其他模式一起使用。

强调:量词只对其前面第一个字符生效!!!!!!!!!!!!!!!!!!!!!

类型:n+、n*、n?

(a.) n+量词模式

描述:n+代表的规则是【存在一个或多个n,即满足】

规律:n+量词在匹配的时候实际上是,能匹配多少就匹配多少,直到不满足才停止。

例子:

var str = 'a1abb2ab3baab';         
var newStr = str.match(/a+/g);         
console.log(newStr);  // ["a", "a", "a", "aa"]

var str = '1234abc';
var list = str.match(/\d+/g);
console.log(list); // 1234

(b.) n*量词模式

描述:n*代表的规则是【存在零个或多个n,即满足】

规律:n*量词在匹配的时候实际上是,能匹配多少就匹配多少,直到不满足才停止。

例子:

var str = 'a1abb2ab3baab';         var newStr = str.match(/b*/g);         console.log(newStr); // (13) ["", "", "", "bb", "", "", "b", "", "b", "", "", "b", ""]

(c.) n?量词模式

描述:n?代表的规则是【存在零个或一个n,即满足】

规律:n?量词在匹配的时候实际上是,能匹配多点就匹配多点,只要一满足就立即结束。

例子:

var str = 'a1abb2ab3baab';         
var newStr = str.match(/b?/g);         
console.log(newStr);  // (14) ["", "", "", "b", "b", "", "", "b", "", "b", "", "", "b", ""]

正则RegExp对象

描述:JS为正则表达式提供了一个正则类(正则的构造函数)RegExp。

通过构造函数创建的对象称为正则对象

语法:

var 名字 = new RegExp('正则主体','修饰符');

注意:

a.通过构造函数创建正则对象,参数必须为字符串格式

b.构造函数创建的正则表达式,和字面量创建的具有相同的作用,只不过长得不一样。

例子:

var str = '123abc12abABC';    
var reg = new RegExp('\\d[a-z]+','gi');    
var newStr = str.replace(reg,'(frank)');    
console.log(newStr);  // 12(frank)1(frank)

(1) test()

描述:本方法是 RegExp 对象中提供的一个方法,

用来判断在【指定字符串中】是否存在【满足正则表达式规则】的子字符串。

存在就返回 true,反之返回 false

语法:

正则表达式.test(指定字符串)

例子:

var regExp = new RegExp('abcd','g');    
console.log(regExp.test('12abc12abABC'));//false     
var regExp = new RegExp('abc','g');    
console.log(regExp.test('12abc12abABC'));//true

补充:

RegExp 类中提供的方法对于正则表达式都是通用的,无论是字面量创建的正则,还是构造函数创建的正则。

console.log(/abc/g.test('12abc12abABC'));  // true 

正则表达式高级

1. ^ 初位字符和 $ 末位字符

描述:

^初位字符:以某个内容开头

$末位字符:以某个内容结尾

语法:

var reg = new RegExp('^temp', '');
var reg = new RegExp('temp$', '');

例子:

var reg = new RegExp('^abc','gi');
var str = '12abc12abABC';

if( reg.test(str) ){
  console.log('以abc开头的字符串');
} else {
  console.log('不是以abc开头的字符串');
}

注意:

如果一个子字符串被包裹在 ^ 和 $ 之间,那么匹配结果只能是这个字符串本身。

其余都不能匹配成功

例子:

var reg = new RegExp('^abc$','gi');
var str = 'abc';

if( reg.test(str) ){
  console.log('以abc开头并结尾的字符串');
} else {
  console.log('不是');
}

2.重复类

描述:重复类是指在正则表达式中通过 {} 大括号检索的一种模式的称谓。

{} 用来表示所匹配的内容连续出现的次数。一般重复类会配合表达式模式一起使用。

语法:

var reg = new RegExp('正则表达式主体{重复类}', '修饰符');

类型:

subStr{n} 表示检索内容恰好出现n次

subStr{n,} 表示检索内容至少出现n次

subStr{n, m} 表示检索内容至少出现n次,至多出现m次。

注意:

对于重复类,有些是能匹配多少就匹配多少【{n,},{n,m}】

有些是匹配到就立即结束【{n}】

例子:

var reg = new RegExp('[a-z]{6}', 'gi');
var str = '12abc12abABCDEFGHIJKLMNOPQRSTUVWXYZ';

var result = str.match(reg);
console.log(result);  // (4) ["abABCD", "EFGHIJ", "KLMNOP", "QRSTUV"]

强调:

对于重复类而言,如果不存在组匹配符号(),那么重复类仅对其前面的第一个字符生效

例子:

var reg = new RegExp('abc{2}','gi');
var str = '12abcabc12abccab';

var result = str.match(reg);
console.log(result);  //  ["abcc"]

3.贪婪模式 和 懒惰模式

描述:

贪婪模式:只要符合正则要求就一直向下匹配,直到不满足条件为止

懒惰模式:只要匹配到最低符合正则要求的内容,就立即结束。

说明:

greed 和 lazy 都是固化在正则内部的两种检索模式,不会主动表现出来。

而是会配合其他的检索模式一同生效。

语法:

n+、n*、{n,}、{n,m} 都是使用贪婪模式的表现符号

n?、{n}、{n,}?、n*?、... 都是懒惰模式的表现符号

例子:

// 贪婪
var str = 'a1abb2ab3baab';
var info = str.match(/b[a-z]*/gi);
console.log(info); // (3) ["bb", "b", "baab"]

// 懒惰
var str = 'a1abb2ab3baab';
var info = str.match(/b[a-z]?/gi);
console.log(info); // (4) ["bb", "b", "ba", "b"]

4.脱字符

描述:当且仅当^符号出现在中括号的首位的时候,表示【不是...即成立】的规则。

语法:

var reg = /[^匹配内容]/修饰符

注意:

(1) 如果^出现在正则首位,但没有写在中括号首位,表示初位字符

如果^出现在正则主体当中,但没写在中括号首位,表示普通字符

(2) [^]表示匹配任意字符

例子:

var pageStr = '<img width="200" /> <img> <img width="300" /> <img width="400" />';

// 以 <img 开头,后面不是 > ,以 /> 结束的文本
var reg = /<img[^>]*\/>/gi;
var list = pageStr.match(reg);
console.log(list);  // (3) ["<img width="200" /><img width="300" /><img width="400 "/>"]

数组去重

1.indexOf数组去重

注意:本数组去重方法存在一个重大的弊端,就是非常耗费时间(当数组元素过多时)

昵称:牺牲时间换空间

例子:

var arr = ['a','b','a','c','a'];
var newArr = [];

for(var i=0; i<arr.length; i++) {
  if(newArr.indexOf(arr[i]) == -1) {
    newArr.push(arr[i]);
  }
}

console.log(newArr); //(3) ["a", "b", "c"]

2.hash表数组去重

解释:哈希表(hash):散列值表,无序的键值对集合。

注意:本数组去重方法存在一个重大的弊端,就是非常耗费内存(当数组元素过多时)

昵称:牺牲空间换时间

例子:

var arr = ['a','b','a','c','a'];
var resultArr = [];
var hash = {};
for(var i=0; arr[i]!=undefined; i++){
  if(!hash[arr[i]]){
    resultArr.push(arr[i]);
    hash[arr[i]] = 100;
  }
}

console.log(resultArr); // (3) ["a", "b", "c"]
console.log(hash);  // {a: 100, b: 100, c: 100}

3. ES6去重

利用 ES6 的 set 方法。

Set() 数据结构,它类似于数组,其成员的值都是唯一的  

let arr = [1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4];

function unique(arr) {
  // 利用Array.from() 将Set结构转换成数组
  return Array.from(new Set(arr))
}
console.log(unique(arr)); // (7) [1, 2, 3, 5, 6, 7, 4]

冒泡排序

基本思想:

依次比较两个相邻的数,如果不符合规则则互换位置。

那么一轮比较下来就能够将最大或最小的值放在数组最后一位。

继续对除【最后一位】之外的所有元素重复上述过程

例子:

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

// 一轮比较,一轮比较能够得到一个最大值
for (var i=1; i<arr.length; i++) {

  // 一轮比较中,要比较多少次
  for (var j=0; j<arr.length -i; j++) {

    // 如果前面的一个值大于后面的值,则将大的值放后面
    if (arr[j] > arr[j + 1]) {
      var temp = arr[j];
      arr[j] = arr[j + 1];
      arr[j + 1] = temp;
    }

  }

  console.log(arr);
  /*
    (5) [4, 3, 2, 1, 5]
    (5) [3, 2, 1, 4, 5]
    (5) [2, 1, 3, 4, 5]
    (5) [1, 2, 3, 4, 5]
  */

}

递归函数

描述:自己能够调用自己的函数,称为递归函数

注意:

(1) 在递归之外,递归变量赋初值

(2) 在递归之内,设置递归能够执行下去的条件

(3) 递归执行结束后,要让递归变量向着递归能够结束的方向发生变化

例子:

// 递归变量赋初值
var times = 1;

function tellStory() {

  // 设置递归的终止条件
  if (times > 5) return;

  console.log('从前有座山');
  console.log('山里有座庙');
  console.log('庙里有个老和尚');
  console.log('老和尚在讲故事');
  console.log('讲的什么故事呢');
  console.log('-----times:' + times + '--------');

  // 递归变量向着递归结束的方向发生改变
  times++;

  // 递归能够循环执行的保证
  tellStory();

}

tellStory();

快速排序

依托:递归函数

原理:

(1) 在已知数据集合当中随便取一个基准值(pivot)

(2) 将其余数据以基准值为中心,大于的放右面,小于的放左面

(3) 对左右两个子集重复步骤(1)(2)

例子:

var arr = [1, 4, 7, 2, 5, 8, 3, 6, 9];

//创建快速排序函数
function quickSort(tempArr) {

  //递归终止条件
  if (tempArr.length <= 1) return tempArr;

  //取基准
  var pivotIndex = Math.floor(tempArr.length / 2);
  var pivot = tempArr.splice(pivotIndex, 1);

  //分左右
  var leftArr = [];
  var rightArr = [];

  for (var i = 0; i < tempArr.length; i++) {
    if (tempArr[i] > pivot) {
      rightArr.push(tempArr[i]);
    } else {
      leftArr.push(tempArr[i]);
    }
  }

  return quickSort(leftArr).concat(pivot, quickSort(rightArr));

}

var finalArr = quickSort(arr);
console.log(finalArr);  // (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]

JSON

什么是 JSON?

JSON 英文全称 JavaScript Object Notation
JSON 是一种轻量级的数据交换格式
JSON 是独立的语言
JSON 易于理解
JSON 是用于存储和传输数据的格式
JSON 通常用于服务端向网页传递数据
JSON 使用 JavaScript 语法,但是 JSON 格式仅仅是一个文本, 文本可以被任何编程语言读取及作为数据格式传递

JSON格式:

  • 数据为 键/值 对。
  • 数据由逗号分隔。
  • 大括号保存对象
  • 方括号保存数组

(1)JSON 数据: 一个名称 对应 一个值

JSON 数据格式为 键/值 对,就像 JavaScript 对象属性。

键/值对包括字段名称(在双引号中),后面一个冒号,然后是值:

"name":"Runoob"

(2)JSON 对象

JSON 对象保存在大括号内,就像在 JavaScript 中, 对象可以保存多个 键/值 对:

{"name":"Runoob", "url":"www.runoob.com"}

(3)JSON 数组

JSON 数组保存在中括号内,就像在 JavaScript 中, 数组可以包含对象:

"sites":[
    {"name":"Runoob", "url":"www.runoob.com"}, 
    {"name":"Google", "url":"www.google.com"},
    {"name":"Taobao", "url":"www.taobao.com"}
]

(4)JSON 值可以是:数字(整数或浮点数)、字符串(在双引号中)、逻辑值(true 或 false)、数组(在方括号中)、对象(在花括号中)、null

例子:

{
  "code": "1",
  "data": [
    {
      "title": "NBA进攻R级别防守SSS级别的球员在CBA会是什么水平",
      "typeid": 3
    },
    {
      "title": "NBA那么多肌肉男,为何只有詹姆斯被赞是“人类身体标本”?",
      "typeid": 3
    }
  ],
  "msg": "",
  "total": 25919
}

JSON解析(Javascript Object Notation)

描述:对象的字符串表现形式,本质上是一种轻量级的数据交换格式

(1) JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串。

语法:

JSON.stringify(value, replacer, space)

参数说明:

value:  必需, 要转换的 JavaScript 值(通常为对象或数组)。

replacer:   可选。用于转换结果的函数或数组。

(1)如果 replacer 为函数,则 JSON.stringify 将调用该函数,并传入每个成员的键和值。使用返回值而不是原始值。如果此函数返回 undefined,则排除成员。根对象的键是一个空字符串:""。

(2)如果 replacer 是一个数组,则仅转换该数组中具有键值的成员。成员的转换顺序与键在数组中的顺序一样。

space:  可选,文本添加缩进、空格和换行符,如果 space 是一个数字,则返回值文本在每个级别缩进指定数目的空格,如果 space 大于 10,则文本缩进 10 个空格。space 也可以使用非数字,如:\t。

注意:

(1)JSON字符串统一采用单引号定义,而JSON字符串内容中如果出现引号则使用双引号。

(2)JSON封装过程:把js对象转换成JSON字符串。因为后台只认识JSON字符串

(3)JSON解析过程,把JSON字符串转换成js对象。因为字符串没办法直接提取有用信息

返回值:返回包含 JSON 文本的字符串。

例子:

var str = {"name":"wzc", "age":"18"}
jsonStr = JSON.stringify(str, null, 2) //使用两个空格缩进
console.log(jsonStr);
/*
  {
    "name": "wzc",
    "age": "18"
  }
*/

(2)JSON.parse() 方法用于将一个 JSON 字符串转换为对象。

语法:

JSON.parse(text, reviver)

参数说明:

text:  必需, 一个有效的 JSON 字符串。

reviver:  可选,一个转换结果的函数, 将为对象的每个成员调用此函数。

返回值:返回给定 JSON 字符串转换后的对象。

例子:

var Json = `
  {
    "code": "1",
    "data": [
      {
        "title": "NBA进攻R级别防守SSS级别的球员在CBA会是什么水平",
        "typeid": 3
      },
      {
        "title": "NBA那么多肌肉男,为何只有詹姆斯被赞是“人类身体标本”?",
        "typeid": 3
      }
    ],
    "msg": "",
    "total": 25919
  }
`;
var obj = JSON.parse(Json);
console.log(obj)  // {code: "1", data: Array(2), msg: "", total: 25919}

JQuery

jQuery 安装

1.本地:可以从 http://jquery.com 中下载。

<script src="jquery-1.10.2.min.js"></script>

2.线上:如果您不希望下载并存放 jQuery,那么也可以通过 CDN(内容分发网络) 引用它。

<script src=" https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

jq对象

描述:$() 函数的执行结果(返回值),是一个 jq 对象,jq 对象是一个包含了满足选择器条件的元素节点的信息集合,可以像使用数组一样使用。本质:是一个对象

注意:$() = jQuery() // 两者方法一致

jq 可以转换成 js 对象:

var $divs = $('div');           
$divs.css('background-color','red');           
console.log($divs[0]); //获取jq中第一个js对象,通过中括号获取           
console.log($divs.get(1)); //获取jq中第二个js对象,通过.get(n)获取

jq 对象只能使用 jq 自己的属性和方法

例子:

var $divs = $('div');       
console.log($divs); // 批量选中        

$divs[0].style.backgroundColor = 'red'; // js对象调用jq方法,报错

length 属性

描述:本方法和属性为jq对象所有,表示jq对象中包含多少个js元素节点

语法:jq对象.length

例子:

var $divs = $('div');   
$divs.css('backgroundColor','red'); 
   
console.log($divs.length);   // 1

jQuery 选择器

选择器实例选取
*$("*")所有元素
#id$("#lastname")id="lastname" 的元素
.class$(".intro")所有 class="intro" 的元素
element$("p")所有 <p> 元素
.class.class$(".intro.demo")所有 class="intro" 且 class="demo" 的元素

:first$("p:first")第一个 <p> 元素
:last$("p:last")最后一个 <p> 元素
:even$("tr:even")所有偶数 <tr> 元素
:odd$("tr:odd")所有奇数 <tr> 元素
:eq(index)$("ul li:eq(3)")列表中的第四个元素(index 从 0 开始)
:gt(no)$("ul li:gt(3)")列出 index 大于 3 的元素
:lt(no)$("ul li:lt(3)")列出 index 小于 3 的元素
:not(selector)$("input:not(:empty)")所有不为空的 input 元素
:header$(":header")所有标题元素 <h1> - <h6>
:animated 所有动画元素
:contains(text)$(":contains('W3School')")包含指定字符串的所有元素
:empty$(":empty")无子(元素)节点的所有元素
:hidden$("p:hidden")所有隐藏的 <p> 元素
:visible$("table:visible")所有可见的表格
s1,s2,s3$("th,td,.intro")所有带有匹配选择的元素
[attribute]$("[href]")所有带有 href 属性的元素
[attribute=value]$("[href='#']")所有 href 属性的值等于 "#" 的元素
[attribute!=value]$("[href!='#']")所有 href 属性的值不等于 "#" 的元素
[attribute$=value]$("[href$='.jpg']")所有 href 属性的值包含以 ".jpg" 结尾的元素
:input$(":input")所有 <input> 元素
:text$(":text")所有 type="text" 的 <input> 元素
:password$(":password")所有 type="password" 的 <input> 元素
:radio$(":radio")所有 type="radio" 的 <input> 元素
:checkbox$(":checkbox")所有 type="checkbox" 的 <input> 元素
:submit$(":submit")所有 type="submit" 的 <input> 元素
:reset$(":reset")所有 type="reset" 的 <input> 元素
:button$(":button")所有 type="button" 的 <input> 元素
:image$(":image")所有 type="image" 的 <input> 元素
:file$(":file")所有 type="file" 的 <input> 元素
:enabled$(":enabled")所有激活的 input 元素
:disabled$(":disabled")所有禁用的 input 元素
:selected$(":selected")所有被选取的 input 元素
:checked$(":checked")所有被选中的 input 元素

补充:$() 函数在使用的时候内部写引号,在写选择器。但有几种特殊情况不用添加引号

$(window)

$(document)

$(this)

jq中添加事件监听

1. jq中添加事件监听

语法:

jq对象.事件名( 回调函数 );

特性:因为jq对象是批量的,因此在jq中添加事件监听的时候也是批量添加的。

例子:

var $divs = $('div');       
$divs.click(function () {       
  $(this).css('background-color','red');       
});

2. jq中事件名称

说明:jq中添加事件监听时,事件名称和js中基本保持一致。

只不过需要注意添加事件监听时一律没有on!

测试:

(1) jq可以给一个元素添加多个不同类型的事件,且互相触发不影响

(2) jq可以给一个元素添加多个相同类型的事件,且执行顺序按照添加顺序执行

例子:

var $div1 = $('.div1');      
$div1.click(function (){ 
  console.log('div1的单击事件');
});       
$div1.click(function () {
  console.log('div1的另一个单击事件');
});

注意:

在jq中添加事件监听的时候,允许链式声明的写法。

且除最后一个添加的函数末尾写分号外,其余事件监听函数末尾都不需要写分号。

例子:

var $div1 = $('.div1');       
$div1.click(function () {
  console.log('第一个点击事件');
}).click(function () {
  console.log('第二个点击事件');
}).dblclick(function () {
  console.log('双击事件');
});

3. 下面是 jQuery 中事件方法的一些例子:

.ready(function)     // 文档的就绪事件(当文档完成加载时)
.click(function)     // 点击事件
.dblclick(function)  // 双击事件
.focus(function)     // 获得焦点事件
.mouseover(function) // 鼠标悬停事件

4. jq中添加事件监听的其他方法

(1) on() \ off() 方法

描述:on()方法用于添加事件监听,off()方法用于取消事件监听

语法:

jq对象.on('事件名',回调函数);
jq对象.off('事件名');

注意:off方法在取消事件的时候,取消的是一类事件,而不是一个事件!

例子:

var $div1 = $('.div1');
var $div2 = $('.div2');
$div1.on('click', function () {
  console.log('div1通过on方法绑定的点击事件');
});
$div2.on('click', function () {
  $div1.off('click');
  console.log('div1上的事件已经被off方法取消掉了');
});

(3) one() 方法

描述:one方法添加的事件监听只能执行一次

语法:

jq对象.one('事件名', 回调函数);

例子:

var $div1 = $('.div1');       
$div1.one('click', function () {
  console.log('这是一个点击事件');
});

jq中常见方法

1. css() 方法

描述:本方法为jq对象读写css样式的方法,相当于js中的style属性。

语法:

jq对象.css('属性名', '属性值');

说明:

(1) 第一个参数是必要参数,第二个参数是可选参数。

(2) 如果只写第一个参数则代表读取属性的值,而写两个参数代表设置属性的值。

例子:

var $div1 = $('.div1');       
var $div2 = $('.div2');       
$div1.click(function () {       
  $(this).css('background-color', 'red');       
});       
$div2.click(function () {       
  console.log($div1.css('background-color'));       
});

补充:如果 css() 方法需要一次修改多个css样式,则参数可以写成JSON格式

例子:

var $div1 = $('.div1');       
$div1.click(function () {       
  $(this).css({               
    "background-color":"yellow",
    "border":"10px solid pink",
    "width":"150px",
    "height":"200px"
  });
});

2. show()、hide()方法

描述:show() 方法表示jq对象立即显示,hide() 方法表示jq对象立即隐藏

语法:

jq对象.show(动画时间ms);

说明:

(1) 方法内部的参数是可选参数,表示动画执行时间,单位是毫秒,

如果不写则默认执行时间为0。

(2) 方法的动画实际上是一个宽高渐变,透明度渐变的动画,

是从display:none到display:block之间的改变

例子:

var $div1 = $('.div1');       
$('button:eq(0)').click(function () {
  $div1.show();
});
$('button:eq(1)').click(function (){
  $div1.hide();
});       
$('button:eq(2)').click(function () {
  $div1.show(5000);
});       
$('button:eq(3)').click(function () {
  $div1.hide(5000);
});

3. hover()

描述:jq中hover() 方法规定当鼠标指针悬停在被选元素上时要运行的两个函数。方法触发 mouseentermouseleave 事件。

语法:

hover(function(){
  // 移入事件
}, function(){
  // 移出事件
});

注意: 如果只指定一个函数,则 mouseenter 和 mouseleave 都执行它。

例子:

$('tr:gt(0)').hover(function () {       
  tempColor = $(this).css('background-color');       
  $(this).css('background-color','red');   
}, function () {       
  $(this).css('background-color',tempColor);   
});

4. slideUp() 和 slideDown()方法

描述:slideUp 方法表示jq对象上拉消失,slideDown 方法表示jq对象下拉出现

语法:

jq对象.slideUp();
jq对象.slideDown();

补充:对于这两个方法即使不写参数,也会默认有一定的动画时间,只不过比较短而已。

例子:

var $div1 = $('.div1');       
$('button:eq(0)').click(function () {  $div1.slideUp();  });       
$('button:eq(1)').click(function () {  $div1.slideDown();  });       
$('button:eq(2)').click(function () {  $div1.slideUp(5000);  });       
$('button:eq(3)').click(function () {  $div1.slideDown(5000);  });

注意:

对于这两个方法存在一个隐藏的属性,称为“边界”。默认边界为上边界。

边界可以手动设置,设置方法为给jq对象添加定位属性。

强调:

slideUp 和slideDown 方法执行的起始点和结束点分别是

display:none 和 display:block

5. fadeIn() 和 fadeOut() 方法

描述:fadeIn() 表示淡入,fadeOut() 表示淡出

语法:

jq对象.fadeIn();
jq对象.fadeOut();

说明:淡入和淡出的起始点和终止点分别为 display:none 和 display:block。

而不是 opacity:0 和 opacity:1

例子:

var $div1 = $('.div1');   
$('button:eq(0)').click(function () {  $div1.fadeIn();  });   
$('button:eq(1)').click(function () {  $div1.fadeOut();  });   
$('button:eq(2)').click(function () {  $div1.fadeIn(5000);  });   
$('button:eq(3)').click(function () {  $div1.fadeOut(5000);  });

6. addClass() 和 removeClass()

描述:addClass方法为追加类,在原有的基础上添加一个类名

removeClass方法为移除类,在已知的属性值列表中删除一个类名

语法:

jq对象.addClass('类名');
jq对象.removeClass('类名');

注意:对于这两个方法,参数是【类名】,不是选择器!!!

例子:

var $div1 = $('.div1');       
$('button:eq(0)').click(function () {  $div1.addClass('bgRed');  });       
$('button:eq(1)').click(function () {  $div1.removeClass('bgRed');  });

7. attr() 方法

描述:用于修改jq对象的属性,本方法会覆盖原有的属性值

语法:

jq对象.attr('属性名','属性值');

例子:把原来的class替换成abc

$('.div1').attr(‘class’ , ‘abc’);

补充:如果attr方法只有一个参数,则代表读取这个属性的属性值。

8. text() 方法

描述:设置或返回所选元素的文本内容

语法:

jq对象.text('文本内容');

例子:

$('div').text();
$('div').text('文本已修改!');

9. html()

描述:用来读写和设置jq对象的文本内容,相当于原生 js 中的 innerHTML属性,如果方法没有参数,代表读取内容。如果写了参数,代表设置内容。

语法:

jq对象.html('文本内容');

例子:

$div1.html();
$div1.html('文本已修改');       

10. val() 方法

描述:设置或返回表单字段的值

语法:

jq对象.val();

例子:

$('div').val();$('div').val('我是新的输入框的值!');

11. animate()

描述:表示设置jq对象的自定义动画

语法:

jq对象.animate(JSON格式的参数,动画执行时间ms);

说明:

第一个参数是JSON格式,表示动画结束时jq对象的状态,哪怕只有一个属性发生改变,也要写成JSON格式

例子:

$('.div1').click(function () {       
  $(this).animate({
    'left':800,
    'width':'200px',
    'height':'350px'
   }, 2000);       
});

(1)动画顺序:jq动画执行时遵守以下两个原则

(2)同步原则:同一个元素如果存在多个animate命令,则按照添加顺序执行。

$('.div1').click(function () {           
  $(this).animate({'left':800}, 2000)
    .animate({'width':'200px'}, 2000)
    .animate({'height':'350px'}, 2000);       
});

(3)异步原则:不同元素如果存在多个animate命令,则他们同时执行。

$('.div1').animate({'left':800}, 2000);       
$('.div2').animate({'left':800}, 2000);

注意:对于一个jq对象而言,一个animate完成所有动画,和多个animate分别完成所有动画效果完全不等价

(4)局限性:只能够修改一些可以被量化的属性,而对于没有量化的属性则无法进行动画。

例子:

$('.div1').click(function () {       
  //一次执行完毕       
  $(this).animate({'left':800, 'width':'200px', 'height':'350px'}, 2000);  

  //按照出现的顺序分次执行       
  $(this).animate({'left':800},2000)           
    .animate({'width':'200px'},2000)           
    .animate({'height':'350px'},2000);   
});

(5)匀速运动(可选参数)

描述:animate 动画实际上是一个 ease-inout 的动画,linear 属性能够让动画匀速运动

语法:

jq对象.animate(JSON格式参数, 时间, 'linear');

说明:linear属性是animate方法的第三个参数

例子:

$('.div1').animate({'left':800}, 5000, 'linear', function (){       
  $(this).css('background-color','red');       
});       
$('.div2').animate({'left':800}, 5000, function (){       
  $(this).css('background-color','red');       
});

(6)回调函数(可选参数)

描述:回调函数表示 animate 动画执行完毕后,要做什么

说明:回调函数是 animate 方法的第四个参数

例子:

$('.div1').click(function () {           
  $(this).animate({'left':800},2000, function () {           
    $('.div1').css('background-color','red');           
  });
});

12. stop() 方法

描述:stop方法用于结束jq对象的动画

语法:

jq对象.stop(clearAllAnimation, gotoEnd);

(1) 两个参数都是布尔值,默认都是false,可以不写

(2) 第一个参数代表是否清除所有动画序列中的动画,false表示只清除当前动画。

(3) 第二个参数代表是否立即完成当前动画(达到动画结束状态),false表示不完成。

13. delay() 方法

描述:delay() 方法对队列中的下一项的执行设置延迟。

例子:

$('.container img').each(function (i) {       
  $(this).delay(i*500).fadeIn(100).fadeOut(100).fadeIn(100).fadeOut(100).fadeIn(100);   
});

Jq节点关系

1. children() 方法

描述:本方法用于获取一个jq对象的所有【直接子节点】

语法:

jq对象.children('选择器名');

说明:

(1) 参数为可选参数,如果不写代表选中jq对象中所有直接子节点

(2) 如果写参数,则代表选中jq对象中所有直接子节点中【满足选择器】的节点

例子:

$('div').click(function () {
  $(this).children().css('background-color','red');
  $(this).children('.teshu').css('background-color','red');
});

2. find() 方法

描述:本方法用于查找一个jq对象中【符合选择器要求】的后代节点

语法:

jq对象.find('选择器名');

说明:find() 方法并不是只能查找直接子节点,而是对所有后代节点都能有效

例子:

$('div').click(function () {
  $(this).find('span').css('background-color','red');
});

3. parent() 方法

描述:本方法用来获取当前jq对象的直接父节点

语法:

jq对象.parent();

说明:本方法不需要参数,且仅能获取直接父节点,对祖先节点无效。

例子:

$('span').click(function () {
  $(this).parent().css('border','10px solid red');
});

4. parents() 方法

描述:本方法用来获取当前jq对象的所有祖先节点,直到html节点为止。

语法:

jq对象.parents('选择器名');

说明:

(1) 本方法参数为可选参数,如果不写表示获取所有祖先节点

(2) 如果写参数,则代表选中祖先节点中,满足选择器的节点

例子:

$('span').click(function () {
  $(this).parents().css('border','10px solid red');
  $(this).parents('.div1').css('border','10px solid red');
});

5. siblings()方法

描述:本方法用来获取当前jq对象的所有兄弟节点,除本身外

语法:

jq对象.siblings('选择器名');

说明:

(1) 本方法参数为可选参数,如果不写则选中当前jq对象的所有兄弟节点

(2) 如果写参数,则代表选中兄弟节点中,满足选择器的节点。

例子:

$('p').click(function () {
  $(this).siblings().css('background-color','red');  $(this).siblings('.teshu').css('background-color','red');});

6. next()、prev()、nextAll()、prevAll()方法

描述:以上四个方法都是用来访问jq对象的指定兄弟节点,如果写参数,则代表选中节点中,满足选择器的节点。

语法:

jq对象.next();
jq对象.prev();
jq对象.nextAll();
jq对象.prevAll();

说明:

(1) next() 方法用来访问当前jq对象的后一个兄弟节点

(2) prev() 方法用来访问当前jq对象的前一个兄弟节点

(3) nextAll() 方法用来访问当前jq对象的后面所有的兄弟节点

(4) prevAll() 方法用来访问当前jq对象的前面所有的兄弟节点

例子:

$('p').click(function () {
  $(this).prevAll('.teshu').css('background-color','red');
})

jq节点顺序

1. index()

描述:本方法用于返回当前jq对象在兄弟节点中的排名,序号从0开始

语法:

jq对象.index();

例子:

$('p').click(function () {
  console.log($(this).index());
});

2.对应

说明:jq中的对应实际上指的是eq()函数,作用是从集合中筛选出指定序号的节点

语法:

jq对象.eq(n);

说明:序号从0开始

例子:

var $div1_p = $('.div1 p');
var $div2_p = $('.div2 p');
$div1_p.click(function () {
  //点击div1中p标签的时候,让div2中对应序号的p跟随改变
  $div2_p.eq($(this).index()).css('background-color','red');
});

jq节点遍历

1. each()方法

描述:遍历jq对象的每一个js节点,并让每一个js节点分别执行参数中的回调函数

语法:

jq对象.each(回调函数);

注意:在each()方法的回调函数中,$(this)指代当前循环的这个js对象,而不是jq对象本身。

例子:

$('div').each(function () {
  $(this).children().eq(1).css('background-color','red');
});

jq节点操作

1. append()、appendTo()、prepend()、prependTo()方法

描述:以上四个方法都用来给某个jq对象内部添加内容,只不过语法略有不同

语法:

(1) a.append(b): 给jq对象a中的内容之后,追加jq对象b

(2) b.appendTo(a): 把jq对象b,追加到jq对象a中的内容之后。

例子:

var $div = $('div');
$div.click(function () {
  $(this).append($('<h2>这是一个h2</h2>'));
  $('<h2>这是一个h2</h2>').appendTo($(this));
});

(3) a.prepend(b): 给jq对象a中的内容之前,添加jq对象b

(4) b.prependTo(a): 把jq对象b,添加到jq对象a中的内容之前。

例子:

var $div = $('div');
$div.click(function () {
  $(this).prepend($('<h2>这是一个h2</h2>'));
  $('<h2>这是一个h2</h2>').prependTo($(this));
});

2. after()、insertAfter()、before、insertBefore()方法

描述:以上四个方法都用来给某个jq对象外部添加内容,只不过语法略有不同

语法:

(1) a.after(b): 给jq对象a的后面,添加一个同级jq对象b

(2) b.insertAfter(a): 把jq对象b,添加到jq对象a的后面

例子:

var $div = $('div');
$div.click(function () {
  $(this).after($('<h2>这是一个h2</h2>'));
  $('<h2>这是一个h2</h2>').insertAfter($(this));
});

(3) a.before(b): 给jq对象a前面,添加一个同级jq对象b

(4) b.insertBefore(a): 把jq对象b,添加到jq对象a的前面

例子:

var $div = $('div');
$div.click(function () {
  $(this).before($('<h2>这是一个h2</h2>'));        
  $('<h2>这是一个h2</h2>').insertBefore($(this));
});

3.节点守恒定律

描述:通过搜索获得的节点,在页面中同一时刻,只能出现在唯一的一个位置。

例子:

var $div1 = $('.div1');
var $div2 = $('.div2');
var $p = $('.teshu');
$div1.click(function () {
  //点击div1,将p标签添加到div1中
  $(this).append($p);
});
$div2.click(function () {
  //点击div2,将p标签添加到div2中
  $(this).append($p);
});

4. wrap()

描述:表示给当前jq对象添加一个父级元素节点

语法:

a.wrap(b);

说明:给a添加一个父级元素节点b

例子:

var $div2 = $('.div2');
$div2.click(function () {
  $(this).wrap($('<div></div>'));
});

5. empty() \ remove()

描述:

empty() 方法表示清空jq对象的内容

remove() 方法表示将自身删除

语法:

jq对象.empty();
jq对象.remove();

例子:

$('.teshu').click(function () {
  $(this).empty();
  $(this).remove();
});

6. clone()

描述:相当于原生js中的 cloneNode() 方法

语法:

jq对象.clone();

例子:

var $div1 = $('.div1');
var $div2 = $('.div2');
var $p = $('.teshu');

$div2.click(function () {
  //点击div1,将【p标签的克隆】添加到div1中
  $(this).append($p.clone());
});

jquery方式创建标签及添加属性

var $td = $("<td>");     // 创建td标签
$td.attr(class,'box');   // 设置标签属性class=‘box’
$td.html('哈哈哈哈');     // 设置td标签文本值为'哈哈哈哈'
$("#tr_id1").append($td); // 将新创建的td标签插到id为tr_id1的标签中

AJAX

Ajax(Asynchronous JavaScript And XML)概念:
通过XMLHttpRequest对象向服务器提出请求并处理响应,进行页面的局部更新。

1. AJAX都有哪些优点和缺点?

ajax的优点:
1、最大的一点是页面无刷新,用户的体验非常好。
2、使用异步方式与服务器通信,具有更加迅速的响应能力。
3、“按需取数据”,可以最大程度的减少冗余请求,和响应对服务器和带宽的负担,节约空间和宽带租用成本。
4、基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。

ajax的缺点:
1、ajax不支持浏览器back按钮。
2、安全问题 AJAX暴露了与服务器交互的细节。
3、对搜索引擎的支持比较弱。
4、破坏了程序的异常机制。
5、不容易调试。

2. 创建 XMLHttpRequest 对象的语法:

let xhr = new XMLHttpRequest();

3. 向服务器发送请求

如需将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open() 和 send() 方法:

// 规定请求的类型、URL 以及是否异步处理请求
// method:请求的类型;GET 或 POST
// url:文件在服务器上的位置
// async:true(异步)或 false(同步)
xmlhttp.open(method, url, async);

//将请求发送到服务器
// 参数仅用于 POST 请求
xmlhttp.send();

4. GET 还是 POST?

与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用。

然而,在以下情况中,请使用 POST 请求:

  • 无法使用缓存文件(更新服务器上的文件或数据库)
  • 向服务器发送大量数据(POST 没有数据量限制)
  • 发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠

5. 请求方式

  • GET

get方法在Rest中主要用于获取资源,能够发送参数,不过有限制,且参数都会以?开头的形 式附加在URL尾部。规范的get方法处理器应该是幂等的,也就是说对一个资源不论发送多少次get请求都不会更改数据或造成破坏。

特点: 可被缓存,保留在浏览器历史记录中,可被收藏为书签,不应在处理敏感数据时使用,有长度限制,只应当用于取回数据

  • POST

post方法在Rest请求中主要用于添加资源,参数信息存放在请求报文的消息体中相对安全,且可发送较大信息

特点: 不会被缓存,不会保留在浏览器历史记录中,不能被收藏为书签,对数据长度没有要求

  • PUT

put方法在Rest中主要用于更新资源,因为大多数浏览器不支持put和delete,会自动将put和delete请求转化为get和post. 因此为了使用put和delete方法, 需要以post发送请求,在表单中使用隐藏域发送真正的请求。put方法的参数是同post一样是存放在消息中的,同样具有安全性,可发送较大信息。put方法是幂等的,对同一URL资源做出的同一数据的任意次put请求其对数据的改变都是一致的。
  • DELETE

Delete在Rest请求中主要用于删除资源,因为大多数浏览器不支持put和delete,会自动将put和delete请求转化为get和post。因此为了使用put和delete方法,需要以post发送请求,在表单中使用隐藏域发送真正的请求。Delete方法的参数同post一样存放在消息体中,具有安全性,可发送较大信息 Delete方法是幂等的,不论对同一个资源进行多少次delete请求都不会破坏数据


6. ajax的同步和异步区别:

同步:阻塞的:同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返 回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;

异步:非阻塞的:异步是指进程不需要一直等下去, 而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。 

7. onreadystatechange 事件

当请求被发送到服务器时,我们需要执行一些基于响应的任务。

每当 readyState 改变时,就会触发 onreadystatechange 事件。

readyState 属性存有 XMLHttpRequest 的状态信息。

在 onreadystatechange 事件中,我们规定当服务器响应已做好被处理的准备时所执行的任务。

当 readyState 为 4 , status 为 200 时,表示响应已就绪!

onreadystatechange存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。
readyState

存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。

  • 0: 请求未初始化
  • 1: 服务器连接已建立
  • 2: 请求已接收
  • 3: 请求处理中
  • 4: 请求已完成,且响应已就绪
status

200: "OK"

404: 未找到页面

8. 服务器响应

获取服务器数据: responseText  // 获得字符串形式的响应数据。

9.简述 ajax 的过程:

1. 创建 XMLHttpRequest 对象,也就是创建一个异步调用对象

2. 创建一个新的 HTTP 请求,并指定该 HTTP 请求的方法、URL 及验证信息 

3. 设置响应 HTTP 请求状态变化的函数 

4. 发送 HTTP 请求 

5. 获取异步调用返回的数据 

6. 使用 JavaScript 和 DOM 实现局部刷新

10. 原生 ajax 请求完整实例

let xhr;
if (window.XMLHttpRequest) {
  // IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
  xhr = new XMLHttpRequest();
} else {
  // IE6, IE5 浏览器执行代码
  xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.onreadystatechange = () => {
  // 判断是否请求成功
  if (xhr.readyState === 4 && xhr.status === 200) {
    //返回数据
    console.log(xhr.responseText);
  }};
xhr.open("GET", url, true);
xhr.send();

jQuery - AJAX

1. jq封装好的 ajax 请求

$.ajax({
  url: "https://www.jsanai.com/api/selfnews/newslist",
  dataType: "json",
  type: "GET",
  async: "true",
  data: { id: 1 },
  success (res) {
    console.log(res.data);
  },
  error () {
    console.error('请求错误!');
  }
});
  • url 发送请求的地址
  • dataType 服务器返回数据的类型:
  xml:返回XML文档,可用JQuery处理。
  html:返回纯文本HTML信息。
  script:返回纯文本JavaScript代码。
  json:返回json数据。
  jsonp:(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)      那获取资料,即跨域读取数据。
  text:返回纯文本字符串。
  •  type 请求方式:默认为get
  GET 获取资源
  POST 添加资源
  DELETE 删除资源
  PUT 更新资源
  • async 异步方式,默认为 true,即异步方式。当设置为 false 时,为同步方式。
  • data 请求参数
  •  success 请求成功时执行
  •  error 请求失败时执行

2. jQuery.getJSON() 是 jQuery.ajax() 函数的简写形式.

语法:jQuery.getJSON( url [, data ] [, success ] )

$.getJSON(url , "", function(data) {
  console.log(data)
});