JS ES6 笔记

js 书写形式 1,行内式<input type="button" value="点我试试" οnclick="alert('Hello World')" /> 2,内嵌式

<script>内容</script>

3,外部文件

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

变量

变量名规范: 1,严格区分大小写 2,不能以数字开头 3,遵守驼峰名法,首字母小写,后边大写

数据类型: JS 把数据类型分为两类: 简单数据类型 (Number,String,Boolean,Undefined,Null) 复杂数据类型 :对象数据类型object。 函数数据类型function

1,数字类型 八进制前+0,十六进制前加OX isNaN(x)用来判断一个变量是否为非数字类型

2,字符串型,单引号或者双引号 用length可以获取整个字符串的长度 多个字符串拼接之间可以使用+

获取检测变量的数据类型可用用typeof

数据类型的转换 1,转换为字符串 toString()转字符串 方法。num.toString() String()强制转换 函数. String(num)

隐世转换 : num+“我是字符串” 和字符串拼接结果都是字符串

2,转换为数字型 parselnt(string) 转换整数 括号中加引号 perseFloat(string) 转换为浮点数。 得到小数 Number() 转换为数值型 js隐式转换(- * /) 利用算数式转换 没有加

3,转换为布尔型 Boolean() 其他类型转换为布尔

NaN和任何值都不相同

逻辑运算符 或与非 && || ! 短路运算:左边的表达式可以确定结果时,就不再继续右边运算

运算优先级 从大到小 () + -- ! */+- > >= < <= == != === !== && || =

三元表达式:表达式1?表达式2:表达式3;

控制结构

顺序结构 无特定语法

分支结构: if语句,三元表达式,switch语句

循环结构:for循环

数组(是特殊的对象数据类型)

1,创建数组

利用new 创建数组 Array A大写 var 数组名=new Array();

2.利用数组字面量创建数组 var 数组名= [];

获取数组元素

1.数组名的长度使用.length可以访问

2.数组的索引:从0开始

可以通过数组名[索引]的形式来获取数组中的元素

数组中增加元素

1.可以通过以下方式在数组末尾插入新元素。 数组[数组.length] = 新数据;

2.通过修改数组索引新增数组元素。 增加原有的会覆盖掉

数组[序号] = '新值'

函数概念;

函数就是封装了一段可被重复调用执行的代码块。

1,自定义函数;

function 函数名() { }

函数名();

函数名关键字必须小写。

2.函数表达式 也称匿名函数

var 变量名 = function(){};

函数名();

调用方式,函数调用必须卸载函数体下面

函数参数语法 。形参:函数定义时设置接收调用时传入 。实参:函数调用时传入小括号内的真实数据 1,调用的时候实参是传递给形参的 2,形参简单理解为:不用声明的变量 3,实参和形参的多个参数之间用逗号分隔;

当函数形参和实参不匹配时\ 实参等于形参个数 输入正确结果 实参个数多余形参个数 只取到形参的个数 实参个数小于形参个数 多的形参定义为undefined,结果为NaN 在js中,形参默认值是undefined

添加删除数组元素的方法

push(参数)。 末尾添加一个或者多个元素。 并返回新的长度

pop()。 删除最后一个元素,把数组长度减一。 返回它删除的元素的值

break ,continue ,return 的区别

  • break :结束当前的循环体(如 for、while)

  • continue :跳出本次循环,继续执行下次循环(如 for、while)

  • return :不仅可以退出循环,还能够返回 return 语句中的值,同时还可以结束当前的函数体内的代码

arguments使用

不确定多个参数传递,可以用arguments来获取。是伪数组 具有length属性 按索引方式存储数据 不具有数字的push,pop等方法。

作用域链:采取就近原则的方式来查找变量最终的值。

预解析:JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析和代码执行。 预解析:在当前作用域下, JS 代码执行之前,浏览器会默认把带有 var 和 function 声明的变量在内存中进行提前声明或者定义。 代码执行: 从上到下执行JS语句。 预解析也叫做变量、函数提升。 变量提升(变量预解析): 变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升。

对象(任何一个对象都由零到多个键值队组成。)

对象是一组无序的相关属性和方法的集合。所有事物都是对象,对象由属性方法组成。

创建对象的三种方法:

1,利用字面量创建对象 var 对象名 = {} { } 里面包含了对象的属性和方法;

调用对象的 属性:

对象.属性名 对象["属性名"] 方括号中必须加引号

调用对象的方法: 对象.方法名()

2,利用new Object 创建对象 var 数组名 = new Object();创建空对象然后追加 不需要写在{}中 数组名.uname="张嘉文"; 追加方法:数组名.sayHi=function(){ console.log("hi!");} 方法都是分号结尾,属性是逗号,追加方法都一样

3,利用构造函数(我们把对象里面一些相同的属性和方法抽象出来封装到函数里面叫构造函数)创造对象。 直接调用是普通函数,用new调用是构造函数 function 构造函数名(形参1,形参2){ this.属性 = 值; this.方法 = function {} } 调用用new new 构造函数名(实参1,实参2)

举例 function Star(uname,age,sex) { this.name=uname; this.age=age; this.sex=sex; this.sing=function(sang) { console.log(sang); } } var ldh= new Star("刘德华",18,"男");

var zxy= new Star("张学友",13,"男");

console.log(ldh.name); 使用属性 ldh.sing("冰雨"); 使用方法

1,构造函数首字母大写 2,构造函数不需要return返回结果 3,函数内的属性和方法前需要加this,表示当前的属性和方法 4,当我们创造对象时候,必须用new来调用构造函数

new关键字的作用

  1. 在内存中创建一个空对象;

  2. 修改this的指向,把this指向创建出来的空对象;

  3. 执行函数的代码,给新对象添加属性和方法

  4. 返回this指向到新对象(所以不需要return)

构造函数和对象

构造函数抽象了对象的公共部分,封装到函数里面,它泛指某一大类

创建对象,通过new关键字创建对象的过程我们也称为对象实例化

遍历对象 for (k in 对象名字) { } console.log(k); 输出是属性名 console.log (obj[k]); 输出是属性值

内置对象: js中对对象分为三种:自定义对象,内置对象,浏览器对象;

获取指定范围内的随机整数: function getRandom(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }

数据类型:简单类型与复杂类型

简单类型又叫基本数据类型或者值类型 在存储变量中存储的是值本身, string number Boolean undefined null

复杂数据类型又叫引用类型,在存储变量中仅仅是地址引用 。因此叫做引用书类型,通过new 关键字创建对象(系统对象,自定义对象) ,如object,array,data等

堆和栈: 空间分配区别: 1,栈(操作系统):由操作系统自动分配释放存放函数的参数值,局部变量。 简单数据类型存放在栈里面。 2,堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若不释放由垃圾回收机制回收,复杂数据类型存放到堆里。

2.4 简单类型传参

    函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量。

2.5 复杂数据类型传参

    函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。

有new就是复杂数据类型

堆栈底层机制

从电脑中分配一块内存执行代码(栈内存 Stack),

变量放在当前栈内存变量存储空间中。值放在当前栈内存变量存储区域中(简单基本类型这样存储)。赋值过程让变量和值相互关联

堆内存 heap。 复杂值(引用类型值)堆存储

在内存中分配一块新内存,定义几个引用类型,分配几个堆空间。用来存储引用类型值。内存中存有十六位进制地址

把对象中的键值对一次存储到堆内存中。把堆内存的地址和变量关联起来

个人总结:简单基本类型指向的是具体内容,更改不该。引用类型复杂值指向的是地址。一改内容都改

js中的数据类型检测

typeof[val]:用来检测数据类型的运算符

检测结果:1,首先是一个字符串 2,字符串中包含对应的类型

局限性 : 1 tpyeof null => 'boject'. null不是对象 2。基于typeof 无法细分当前值是普通对象还是数组对象。 对象类型返回的都是'object'

instanceof : 用来检测当前实例是否属于某个类

Constructor:基于构造函数检测数据类型(也是基于类的方式)

object.prototype.toString.call():检测数据类型的最好办法

DOM

文档:一个页面就是一个文档,DOM中使用的document表示

元素:页面中的所有标签都是元素,DOM中使用element表示

节点:网页中的所有内容都是节点(标签、属性、文本、注释),用node表示

获取元素:

1,根据id获取 document.getElementById(id)不需要通配符 2,根据标签名获取元素的对象集合document.getElementtsByTagName("标签名") 得到的是对象集合,想操作里面的元素就要遍历。得到的元素对象是动态的。

3,根据类名返回元素对象集合 document.getElementsByClassName("类名");不需要加选择器前边的点. 一类 class都是一个名字 4,根据指定选择器返回第一个元素对象 document.querySelector("选择器"); 5,根据指定选择器返回 document.querySelectorAll("选择器"); !注意4,5 两个选择器要加符号 符号具体是什么类型的选择器

操作元素:

1.操作元素内容 innnerText。 innerHTML

2.操作元素常见属性。 src href title

3.操作表单元素属性 type value

4.操作元素样式属性 element.style。和。className

1,改变元素内容 element。innerText 从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉 element。innerHTML 起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行

获取内容的区别: innertext会去除空格和换行,而innerHTML会保留空格和换行, 设置内容时的区别:innerText不会识别html,而innerHTML会识别

表单元素的属性操作 表单里面的值是通过value来修改的 this 指向函数的调用者

样式属性操作

element.style 行内样式操作 element.className 类名样式操作 先写一个类名。用js方式给标签赋值 className 会直接更改元素的类名,会覆盖原先的类名。达到修改样式的目的 .style 修改的是行内样式,权重比较高

排他思想: 如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想。 两次for循环来实现,第一次for实现绑定事件和给当前样式,第二次实现清楚所有样式。

自定义属性操作元素

1.设置元素属性值 element.属性=‘值’ 设置内置属性.\ element.setAttribute('属性',‘值’); 主要设置自定义属性。 class特殊写的就是class不是className

2.获取元素属性值 element.属性 :获取内置属性值(元素本身自带的属性) element.getAttribute('属性'); 主要获得自定义属性,程序员自定义的属性值

比如 div.id 用getAtrribute主要勇获得自定义属性

3.移除属性 element.removeAttribute('属性');

H5规定自定义属性data-开头做为属性名并且赋值。

获取节点操作:

1,用DOM提供的方法获取元素 逻辑性不强繁琐 2,利用节点层次关系获取元素。 利用父子兄弟关系获取,逻辑强

节点操作

1,节点概述:一般来说节点至少拥有nodeType节点类型,nodeName节点名称,nodeValue节点值 元素节点nodetype为1,属性节点为2,文本节点为3包含文字,空格,换行

父级节点元素获取方法:node.parentNode 返回某个节点最近的父节点,没有返回null

区分子节点元素和子元素节点

所有 子节点元素获取方法:parentNode.childNodes(标准) 返回所有节点,包括元素节点和文本节点。 子元素节点:parentNode.children(非标准)。

获取第一个子节点 parentNode.firstChild\ 获取最后一个子节点 parentNode.lastChild

获取第一个子元素节点parentNode.firstElementChild 获取最后一个子元素节点 parentNode.lastElementChild 有兼容性问题,ie9以上支持

  1. 实际开发的写法 既没有兼容性问题又返回第一个子元素 console.log(ol.children[0]); 第一个子元素节点 console.log(ol.children[ol.children.length - 1]); 最后一个子元素节点

兄弟节点: node.nextSibling 返回下一个兄弟节点,包含所有节点,找不到返回null node.previousSibling 返回当前元素上一个兄弟节点,包含所有节点吗,找不到返回null

node.nextElementSibling 返回当前元素的下一个兄弟元素节点\ node.periousElementSibling 返回当前元素的上一个兄弟元素节点。

创建节点:

动态元素创建节点 document.createElement('tagName')

添加节点 node.appendChild(child) 添加一个节点到父节点的子节点列末尾. 不加引号 node.insertBefore(child,指定位置(比如ul.children[0] 谁的第几个孩子)) 将一个节点添加到父节点的指定子节点前边。

删除节点 node.removeChild()

复制节点 node.cloneNode() 克隆以后需要复制出来。 1,如果括号内参数为空或者为false,是浅拷贝,值克隆复制节点本身,不可龙里面的子节点 2,如果括号参数为true,则是深拷贝,会负值节点本身以及里面所有的子节点。

三种动态创造元素的区别

.document.write() 不常用 直接将内容写入页面内容流,但是文档流执行完毕,会导致页面全部重绘 .element.innerHTML 将内容写入某个DOM节点,不会导致页面全部重绘; 字符串拼接效率低, .document.createElement() 效率一般

DOM核心总结 文档对象模型,是标准接口,通过dom接口可以改变网页内容,结构和样式 我们获取的dom元素都是对象,所以称为文档对象模型 我们主要针对元素进行操作。主要是增删改查,属性操作,事件操作

1,创建 document.write()。 写入页面内容流。文档执行完毕会导致页面重绘 element.innerHTML。 将内容写入某个DOM节点,不会导致页面重绘

document.createElement()。 创建多个元素效率低结构清晰

2,增加 node.appenChild(child)。 将一个节点添加到指定副节点的字节点列表末尾,类似css里的:after为元素 node.insertBefore(child,指定元素)。 将一个节点添加到父节点的指定子节点前面,类似:before

3,删 node.removeChild(child)。从DOM中删除一个子节点,返回删除的节点。

4,改 4.1修改元素属性:src、href、title等 4.2修改普通元素内容:innerHtml、innerText 4.3修改表单元素:value、type、disabled 4.4修改元素样式:style、className

5查 主要获取查询dom元素 5.1 DOM提供的API方法:getElementByid、getElementByTagName 5.2H5推荐的新方法:querySelector、querySelectorAll 5.3利用节点操作获取元素:parentNode、children

6属性操作 主要针对自定义属性 6.1 setAttribute:设置DOM的属性值 6.2 getAttribute:得到DOM的属性值 6.3 removeAttribute 移除属性

事件操作

给元素添加事件,称为 注册事件 或者绑定事件

注册事件有两种方式, 传统方式和监听注册方式 传统方式:on开头的事件, 特点:注册事件的唯一性

监听注册方式:addEventListener()它是一个方法 特点:同一个元素同一个事件可以注册多个监听器, 按注册顺序依次执行

事件监听 addEventListener(type,listener[,useCapture])事件监听 event type:事件类型字符串 事件 listener:事件处理函数,事件发生时,会调用该监听函数。 函数 useCapture:可选参数,是一个布尔值默认false

删除事件(解绑事件)

1,传统方式 eventTarget.onclick = null;

2,方法监听注册方式 eventTarget.removeEventListener(tpye, listener)

divs[1].addEventListener('click', fn) // 里面的fn 不需要调用加小括号

    function fn() {
​
        alert(22);

divs[1].removeEventListener('click', fn);

    }

DOM事件流

事件流描述的是从页面中接收事件的顺序。 事件发生时会在元素节点直接按照特定的顺序传播,这个传播过程j即DOM事件流

DOM事件流会经历三个阶段 1,捕获阶段 document -html -body-div 2,当前目标阶段 div 3,冒泡阶段 div-body-html-document

1,js代码只能执行捕获或者冒泡其中一个阶段 2,onclick 和 attachEvent 只能得到冒泡阶段 3,addEventListener(type,listener{,ture}) 如果第三个参数为true,表示事件在捕获阶段调用事件处理程序,如果是false,表示在事件冒泡阶段调用事件处理程序。 type 要写引号

事件对象

事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象 比如:谁绑定了这个事件,鼠标触发事件得到鼠标相关信息

事件对象的使用 事件触发发生(单击,鼠标经过)时就会产生事件对象,并且系统会以实参的形式传给事件处理函数。 所以在事件处理函数中声明一个形参来接收事件对象

1,event 就是一个事件对象,写到我们侦听函数的小括号里面当形参来看 2,事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数 3,事件对象 是 我们事件的一些列相关数据的集合 跟事件相关的 比如鼠标点击里面就包含鼠标的相关信息 4,这个事件对象我们可以自己命名 比如 event 、evt 、e

事件对象的属性和方法 e.target 返回触发事件对象 标准 e.srcElement 返回触发事的对象\ e.type 返回事件类型 比如click e.cancelBubble 该属性阻止冒泡\ e.preventDefault() 该方法阻止默认事件(默认行为) 标准 比如不让链接跳转 e.stopPropagation() 阻止冒泡标准

e.target和this 的区别 this是事件绑定的元素(绑定这个事件处理函数的元素) e.target 是事件触发的元素 一般情况两者是一直的,在事件冒泡时(父子元素有相同事件,单击子元素,父元素的事件处理函数也会被触发执行) 这个时候this 指向父元素,因为它是绑定事件的元素对象 target 指向子元素,因为它是触发事件的那个具体元素

阻止默认行为

百度 <script> // 2. 阻止默认行为 让链接不跳转 var a = document.querySelector('a'); a.addEventListener('click', function(e) { e.preventDefault(); // dom 标准写法 最常用的方法 }); // 3. 传统的注册方式 a.onclick = function(e) { // 普通浏览器 e.preventDefault(); 方法 e.preventDefault(); // 低版本浏览器 ie678 returnValue 属性 e.returnValue = false; // 我们可以利用return false 也能阻止默认行为 没有兼容性问题 但是return后面的代码不执行了,而且只限于传统的注册方式 return false; } </script>

阻止事件冒泡

标准写法:利用事件对象里面的stopPropagation()方法 e.stopPropagation()

事件委托

事件委托也称事件代理,在jQuery里面称为事件委派 原理:不是每个子节点单独设置监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点 e.target. 可以得到当前父元素的儿子设置样式

注:冒泡阶段往上返回执行父节点的事件。

常用鼠标事件

onclick 点击左键

onmouseover。 经过触发

onmouseout。 离开触发

onfocus。 获得焦点

onblur。 失去焦点

onmousemove。 移动触发

onmouseup。 弹起触发

Onmousedown。 按下触发

键盘事件 onkeyup 松开触发 onkeydown 摁下触发 onkeypress 摁下触发 1,如果使用addEventListener 不需要加on 2,onkeypress和另外两个的区别是,它不识别功能键,比如左箭头等 3,三个事件的执行顺序:keydown-keypress-keyup

键盘事件对象 keycode 返回该键的ASCLL值 1,onkeydown和onkeyup不区分字母大小写,onkeypress区分字母大小写 2,更多用keydown和keyup 3,keypress不识别功能键,但是keycode属性能区分大小写,返回不同的ascll值

BOM

Dom :文档对象模型,把文档当作对象来操作,顶级对象document ,主要是操作页面元素

BOM:浏览器对象模型,把浏览器当作对象来看待,顶级对象是windows,学习浏览器窗口交互

顶级对象window是js访问浏览器窗口的一个接口 它是一个全局对象,定义在全局作用域中的变量、函数都会变成window对象的属性和方法,在调用时可以省略window

window对象的常见事件 页面(窗口)加载事件

第一种: window.onload =function(){} 或者 window.addEventListener('load',function(){}); window.onlaod 是窗口加载事件,当文档内容完全加载完成会触发该事件(包括图像,脚本文件,css文件),就调用处理函数 1,window.onload传统注册方式只能写一次,如果有多个会以最后一个window.load为准。 2,如果使用addEventListener则没有限制

第二种:DOMContentLoaded

addEventListener('DOMContentLoaded',function(){}) DOMContentLoaded事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。

调整窗口大小事件 window.onresize = function (){} window.addEventListener('resize',function(){}); 只要窗口大小像素发生变化,就会触发这个事件 我们额经常利用这个事件完成响应式布局。window.innerWidth当前屏幕宽度

定时器

setTimeout() 炸弹定时器\ window.setTimeout(调用函数,【延迟毫秒】) 1,window可以省略 2,延迟毫秒数默认为0 3,定时器可以赋一个标识符

两种调用方式:

setTimeout(function(){函数},2000);

第二种

Function 函数名(){

内容}

var time = setTimeout(函数名,3000)。

停止定时器 window.clearTimeout(timeoutID) 1,window可以省略 2,里面的参数就是定时器的标识符

setInterval() 闹钟定时器 开启定时器:window.setInterval(回调函数,【间隔的毫秒数】) setInterval()方法重复调用一个函数,每隔这个时间,就回去调用一次

停止定时器 window.clearInterval(intervalID); 注意赋值对象的作用域

this的指向问题

this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,一般情况下this的最终指向的是那个调用它的对象。

  1. 全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this指向window)

  2. 方法调用中谁调用this指向谁

  3. 构造函数中this指向构造函数的实例

事件代理

由于事件会在冒泡阶段向上传播,因此可以把子节点的监听函数定义在父节点上,由父节点函数监听函数统一处理多个子元素的事件。这种方法叫做事件代理。

js执行机制

同步:一个任务做完了在做下一个 异步:一个任务执行时间长可以先执行下一个任务

同步任务在主线程上执行,形成一个执行栈 异步任务通过回调函数实现,一般有三种类型

1,普通事件 click、resize

2,资源加载 load error、

3,定时器 异步任务相关的回调函数添加到任务队列中(任务队列也称为消息队列)。

js执行机制(事件循环)

1,先执行执行栈同步任务, 2,异步任务放入任务队列 3,一旦执行栈中所有同步任务都执行完,系统会一次读取任务队列中的异步任务

注意事件中,不触发不到时间不满足条件就不不放入异步队列中 由于主线程不断重复获取任务,执行任务,这种机制被称为事件循环

location对象

window对象给我们提供了一个location属性用于获取或者设计窗体的URL,并且可以用于解析URL。因为这个属性返回一个对象,所以我们也将这个属性称为location对象

location对象常见的方法 location.assign() 何href一样,可以跳转页面,记录历史可以后退 location.replace() 替换当前页面,不记录历史不可以后退 location.reload() 重新加载页面,相当于F5

navigator对象 包含了浏览器的相关信息,最常用的是userAgent,该属性可以返回由客户机发送服务器的user-agent头部的值

history对象。 与浏览器记录进行交互,该对象包含用户访问过的url back()后退 forward()前进 go(参数)

网页特效

元素偏移量offset系列

offset翻译就是偏移量,我们使用offset相关属性可动态的得到该属性的位置,大小等 1,获取元素距离带有定位父元素的位置 2,获得元素自身的大小 3,返回值不带单位

element.offsetParent 带有定位的父元素,父元素没有定位返回body element.offsetTop 返回元素相对带有定位父元素上方的偏移量 element.offsetLeft 返回元素相对带有定位父元素左边框的偏移 element.offsetWidth 返回自身包括padding、边框、内容区的宽度,返回值不带单位 element.offsetHeight 返回自身包括padding、边框、内容区的高度,返回值不带单位

offset 与style 区别 offset 可以得到任意样式表中的样式值 获取数值没有单位 offsetWidth包含padding+border+width offsetWidth 等属性是只读属性,只能获取不能赋值

style style只能得到行内样式表中的样式值 style.width 获得的是带有单位的字符串 style.width获得不包含padding何border的值 style.width是可读写属性,可以获取也可以赋值

元素可视区client系列。 动态获得该元素边框的大小

element.clientTop 返回元素上边框的大小 element.clientLeft 返回元素左边框的大小 element.clientWidth 返回自身包括padding,内容区的宽度,不含边框,返回数值不带单位 element.clientHeight 返回自身包括padding,内容区的高度,不含边框,返回数值不带单位

立即执行函数 1,立即执行函数不需要调用,立即执行 2,写法: (function(){})() (function(){}()) 3 ,多个立即函数,写分号结尾 4,立即函数最大的作用就是创建了一个独立的作用域,避免了命名冲突

pageshow事件: 这个事件在页面显示时触发,无论页面是否来自缓存。事件对象的persisted来判断是否是缓存中的页面触发的pageshow事件,这个事件给window触发

元素滚动scroll系列。动态得到该元素的大小滚动距离

element.scrollTop 返回被卷去的上侧距离,返回数值不带单位 element.scrollLeft 返回被卷去的左侧距离,返回数值不带单位 element.scrollWidth 返回自身实际的宽度,不含边框,返回数值不带单位 包含padding element.scrollHeight 返回自身实际的高度,不含边框,返回数值不带单位 包含padding

页面被卷去的头部:如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll事件。

元素被卷去的头部是 element.scrollTop 页面被卷去的头部是window.pageYoffset

页面被卷去的头部兼容性解决方案

  1. 声明了 DTD,使用 document.documentElement.scrollTop DTD是第一个语句<!DOCTYPE html>

  2. 未声明 DTD,使用 document.body.scrollTop

  3. 新方法 window.pageYOffset和 window.pageXOffset,IE9 开始支持

封装函数解决兼容性问题。 function getScroll() { return { left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft||0, top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0 }; } 使用的时候 getScroll().left

三大系列总结 element.offsetWidth 返回自身包括padding,边框,内容区域宽度,返回值不带单位 element.clientWidth 返回自身包括padding,内容区域宽度,返回值不带单位 element.scrollWidth 返回自身实际宽度,不含边框,返回值不带单位

1.offset系列 经常用于获得元素位置 offsetLeft offsetTop

2.client经常用于获取元素大小 clientWidth clientHeight

3.scroll 经常用于获取滚动距离 scrollTop scrollLeft

4.注意页面滚动的距离通过 window.pageXOffset 获得

mouseenter 和 mouseover区别

mouseover 鼠标经过自身盒子和子盒子回触发, mouseenter 只会经过自身盒子触发

mouseenter不会冒泡,跟mouseenter搭配鼠标离开mouseleave同样不会冒泡

动画函数 核心原理:通过定时器setinterval()不断移动盒子的位置 获得盒子当前的位置,当前的位置加一个移动距离,利用定时器不断重复操作,加一个结束定时器条件,此元素添加定位,才能使用element.style.left

缓动效果

  1. 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。

  2. 核心算法: (目标值 - 现在的位置) / 10 做为每次移动的距离步长

  3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器

  4. 注意步长值需要取整正数往大了取整负数往小取整 step = step>0?Math.ceil(step)\:Mathi.floor(step);

动函数添加回调函数 回调函数原理:函数可以作为一个参数。将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数,这个过程就叫做回调。 回调函数写的位置:定时器结束的位置

动画函数多个目标值之间移动 可以让动画函数容800移动到500 当我们点击按钮,判断步长是正值还是负值,正值步长往大了取整,负值步长往小了取整。

完成代码 function animate(obj, target, callback) { // console.log(callback); callback = function() {} 调用的时候 callback()

// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
    // 步长值写到定时器的里面
    // 把我们步长值改为整数 不要出现小数的问题
    // var step = Math.ceil((target - obj.offsetLeft) / 10);
    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();
    }
    // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
    obj.style.left = obj.offsetLeft + step + 'px';
​
}, 15);

}

防抖

对于短时间内连续触发的事件,让某个时间期限内,事件处理函数只执行一次

节流阀

目的:防止轮播图按钮连续点击造成播放过快当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发。 核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。

开始设置一个变量var flag= true;

If(flag){flag = false; do something} 关闭水龙头

利用回调函数动画执行完毕, flag = true 打开水龙头

移动端网页特效 触屏事件

移动端浏览器兼容性较好,我们不需要考虑以前 JS 的兼容性问题,可以放心的使用原生 JS 书写效果,但是移动端也有自己独特的地方。比如触屏事件 touch(也称触摸事件),Android和 IOS 都有。

触屏touch事件 touchstart 手指摸到dom元素触发 touchmove 手指在一个DOM元素上滑动触发 touchend 手指从一个DOM元素上移开触发

TouchEvent 是一类描述手指在触摸平面(触摸屏、触摸板等)的状态变化的事件 touches 正在触摸屏幕的所有手指的一个列表 targetTouches 正在触摸当前DOM元素上的手指的一个列表 changedTouches 手指状态发生了改变的列表,从无到有,从有到无的变化

平时我们都给元素注册触摸事件,重点记忆targetTocuhes

移动端拖动元素

  1. touchstart、touchmove、touchend 可以实现拖动元素

  2. 但是拖动元素需要当前手指的坐标值 我们可以使用 targetTouches[0] 里面的pageX 和 pageY

  3. 移动端拖动的原理: 手指移动中,计算出手指移动的距离。然后用盒子原来的位置 + 手指移动的距离

  4. 手指移动的距离: 手指滑动中的位置 减去 手指刚开始触摸的位置

拖动元素三步曲:

(1) 触摸元素 touchstart: 获取手指初始坐标,同时获得盒子原来的位置

(2) 移动手指 touchmove: 计算手指的滑动距离,并且移动盒子

(3) 离开手指 touchend:

注意: 手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动 e.preventDefault();

classList属性

classList属性说HTML5新增的属性,返回元素的类名。该属性用于仔元素中添加,移除切换css类。

element.classList.add('类名');

element.classList.remove(’类名‘);

element.classList.toggle('类名');

注意:以上方法里面,所有类名都不带点

click 延时解决方案

移动端 click 事件会有 300ms 的延时,原因是移动端屏幕双击会缩放(double tap to zoom) 页面。

解决方案:

1. 禁用缩放。 浏览器禁用默认的双击缩放行为并且去掉300ms 的点击延迟。
  <meta name="viewport" content="user-scalable=no">
2.利用touch事件自己封装这个事件解决300ms 延迟。
​
原理就是:
  1. 当我们手指触摸屏幕,记录当前触摸时间

  2. 当我们手指离开屏幕, 用离开的时间减去触摸的时间

  3. 如果时间小于150ms,并且没有滑动过屏幕, 那么我们就定义为点击

DOM

文档:一个页面就是一个文档,DOM中使用的document表示

元素:页面中的所有标签都是元素,DOM中使用element表示

节点:网页中的所有内容都是节点(标签、属性、文本、注释),用node表示

获取元素:

1,根据id获取 document.getElementById(id)不需要通配符 2,根据标签名获取元素的对象集合document.getElementtsByTagName("标签名") 得到的是对象集合,想操作里面的元素就要遍历。得到的元素对象是动态的。

3,根据类名返回元素对象集合 document.getElementsByClassName("类名");不需要加选择器前边的点. 一类 class都是一个名字 4,根据指定选择器返回第一个元素对象 document.querySelector("选择器"); 5,根据指定选择器返回 document.querySelectorAll("选择器"); !注意4,5 两个选择器要加符号 符号具体是什么类型的选择器

操作元素:

1.操作元素内容 innnerText。 innerHTML

2.操作元素常见属性。 src href title

3.操作表单元素属性 type value

4.操作元素样式属性 element.style。和。className

1,改变元素内容 element。innerText 从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉 element。innerHTML 起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行

获取内容的区别: innertext会去除空格和换行,而innerHTML会保留空格和换行, 设置内容时的区别:innerText不会识别html,而innerHTML会识别

表单元素的属性操作 表单里面的值是通过value来修改的 this 指向函数的调用者

样式属性操作

element.style 行内样式操作 element.className 类名样式操作 先写一个类名。用js方式给标签赋值 className 会直接更改元素的类名,会覆盖原先的类名。达到修改样式的目的 .style 修改的是行内样式,权重比较高

排他思想: 如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想。 两次for循环来实现,第一次for实现绑定事件和给当前样式,第二次实现清楚所有样式。

自定义属性操作元素

1.设置元素属性值 element.属性=‘值’ 设置内置属性.\ element.setAttribute('属性',‘值’); 主要设置自定义属性。 class特殊写的就是class不是className

2.获取元素属性值 element.属性 :获取内置属性值(元素本身自带的属性) element.getAttribute('属性'); 主要获得自定义属性,程序员自定义的属性值

比如 div.id 用getAtrribute主要勇获得自定义属性

3.移除属性 element.removeAttribute('属性');

H5规定自定义属性data-开头做为属性名并且赋值。

获取节点操作:

1,用DOM提供的方法获取元素 逻辑性不强繁琐 2,利用节点层次关系获取元素。 利用父子兄弟关系获取,逻辑强

节点操作

1,节点概述:一般来说节点至少拥有nodeType节点类型,nodeName节点名称,nodeValue节点值 元素节点nodetype为1,属性节点为2,文本节点为3包含文字,空格,换行

父级节点元素获取方法:node.parentNode 返回某个节点最近的父节点,没有返回null

区分子节点元素和子元素节点

所有 子节点元素获取方法:parentNode.childNodes(标准) 返回所有节点,包括元素节点和文本节点。 子元素节点:parentNode.children(非标准)。

获取第一个子节点 parentNode.firstChild\ 获取最后一个子节点 parentNode.lastChild

获取第一个子元素节点parentNode.firstElementChild 获取最后一个子元素节点 parentNode.lastElementChild 有兼容性问题,ie9以上支持

  1. 实际开发的写法 既没有兼容性问题又返回第一个子元素 console.log(ol.children[0]); 第一个子元素节点 console.log(ol.children[ol.children.length - 1]); 最后一个子元素节点

兄弟节点: node.nextSibling 返回下一个兄弟节点,包含所有节点,找不到返回null node.previousSibling 返回当前元素上一个兄弟节点,包含所有节点吗,找不到返回null

node.nextElementSibling 返回当前元素的下一个兄弟元素节点\ node.periousElementSibling 返回当前元素的上一个兄弟元素节点。

创建节点:

动态元素创建节点 document.createElement('tagName')

添加节点 node.appendChild(child) 添加一个节点到父节点的子节点列末尾. 不加引号 node.insertBefore(child,指定位置(比如ul.children[0] 谁的第几个孩子)) 将一个节点添加到父节点的指定子节点前边。

删除节点 node.removeChild()

复制节点 node.cloneNode() 克隆以后需要复制出来。 1,如果括号内参数为空或者为false,是浅拷贝,值克隆复制节点本身,不可龙里面的子节点 2,如果括号参数为true,则是深拷贝,会负值节点本身以及里面所有的子节点。

三种动态创造元素的区别

.document.write() 不常用 直接将内容写入页面内容流,但是文档流执行完毕,会导致页面全部重绘 .element.innerHTML 将内容写入某个DOM节点,不会导致页面全部重绘; 字符串拼接效率低, .document.createElement() 效率一般

DOM核心总结 文档对象模型,是标准接口,通过dom接口可以改变网页内容,结构和样式 我们获取的dom元素都是对象,所以称为文档对象模型 我们主要针对元素进行操作。主要是增删改查,属性操作,事件操作

1,创建 document.write()。 写入页面内容流。文档执行完毕会导致页面重绘 element.innerHTML。 将内容写入某个DOM节点,不会导致页面重绘

document.createElement()。 创建多个元素效率低结构清晰

2,增加 node.appenChild(child)。 将一个节点添加到指定副节点的字节点列表末尾,类似css里的:after为元素 node.insertBefore(child,指定元素)。 将一个节点添加到父节点的指定子节点前面,类似:before

3,删 node.removeChild(child)。从DOM中删除一个子节点,返回删除的节点。

4,改 4.1修改元素属性:src、href、title等 4.2修改普通元素内容:innerHtml、innerText 4.3修改表单元素:value、type、disabled 4.4修改元素样式:style、className

5查 主要获取查询dom元素 5.1 DOM提供的API方法:getElementByid、getElementByTagName 5.2H5推荐的新方法:querySelector、querySelectorAll 5.3利用节点操作获取元素:parentNode、children

6属性操作 主要针对自定义属性 6.1 setAttribute:设置DOM的属性值 6.2 getAttribute:得到DOM的属性值 6.3 removeAttribute 移除属性

事件操作

给元素添加事件,称为 注册事件 或者绑定事件

注册事件有两种方式, 传统方式和监听注册方式 传统方式:on开头的事件, 特点:注册事件的唯一性

监听注册方式:addEventListener()它是一个方法 特点:同一个元素同一个事件可以注册多个监听器, 按注册顺序依次执行

事件监听 addEventListener(type,listener[,useCapture])事件监听 event type:事件类型字符串 事件 listener:事件处理函数,事件发生时,会调用该监听函数。 函数 useCapture:可选参数,是一个布尔值默认false

删除事件(解绑事件)

1,传统方式 eventTarget.onclick = null;

2,方法监听注册方式 eventTarget.removeEventListener(tpye, listener)

divs[1].addEventListener('click', fn) // 里面的fn 不需要调用加小括号

    function fn() {
​
        alert(22);

divs[1].removeEventListener('click', fn);

    }

DOM事件流

事件流描述的是从页面中接收事件的顺序。 事件发生时会在元素节点直接按照特定的顺序传播,这个传播过程j即DOM事件流

DOM事件流会经历三个阶段 1,捕获阶段 document -html -body-div 2,当前目标阶段 div 3,冒泡阶段 div-body-html-document

1,js代码只能执行捕获或者冒泡其中一个阶段 2,onclick 和 attachEvent 只能得到冒泡阶段 3,addEventListener(type,listener{,ture}) 如果第三个参数为true,表示事件在捕获阶段调用事件处理程序,如果是false,表示在事件冒泡阶段调用事件处理程序。 type 要写引号

事件对象

事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象 比如:谁绑定了这个事件,鼠标触发事件得到鼠标相关信息

事件对象的使用 事件触发发生(单击,鼠标经过)时就会产生事件对象,并且系统会以实参的形式传给事件处理函数。 所以在事件处理函数中声明一个形参来接收事件对象

1,event 就是一个事件对象,写到我们侦听函数的小括号里面当形参来看 2,事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数 3,事件对象 是 我们事件的一些列相关数据的集合 跟事件相关的 比如鼠标点击里面就包含鼠标的相关信息 4,这个事件对象我们可以自己命名 比如 event 、evt 、e

事件对象的属性和方法 e.target 返回触发事件对象 标准 e.srcElement 返回触发事的对象\ e.type 返回事件类型 比如click e.cancelBubble 该属性阻止冒泡\ e.preventDefault() 该方法阻止默认事件(默认行为) 标准 比如不让链接跳转 e.stopPropagation() 阻止冒泡标准

e.target和this 的区别 this是事件绑定的元素(绑定这个事件处理函数的元素) e.target 是事件触发的元素 一般情况两者是一直的,在事件冒泡时(父子元素有相同事件,单击子元素,父元素的事件处理函数也会被触发执行) 这个时候this 指向父元素,因为它是绑定事件的元素对象 target 指向子元素,因为它是触发事件的那个具体元素

阻止默认行为

百度 <script> // 2. 阻止默认行为 让链接不跳转 var a = document.querySelector('a'); a.addEventListener('click', function(e) { e.preventDefault(); // dom 标准写法 最常用的方法 }); // 3. 传统的注册方式 a.onclick = function(e) { // 普通浏览器 e.preventDefault(); 方法 e.preventDefault(); // 低版本浏览器 ie678 returnValue 属性 e.returnValue = false; // 我们可以利用return false 也能阻止默认行为 没有兼容性问题 但是return后面的代码不执行了,而且只限于传统的注册方式 return false; } </script>

阻止事件冒泡

标准写法:利用事件对象里面的stopPropagation()方法 e.stopPropagation()

事件委托

事件委托也称事件代理,在jQuery里面称为事件委派 原理:不是每个子节点单独设置监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点 e.target. 可以得到当前父元素的儿子设置样式

注:冒泡阶段往上返回执行父节点的事件。

常用鼠标事件

onclick 点击左键

onmouseover。 经过触发

onmouseout。 离开触发

onfocus。 获得焦点

onblur。 失去焦点

onmousemove。 移动触发

onmouseup。 弹起触发

Onmousedown。 按下触发

键盘事件 onkeyup 松开触发 onkeydown 摁下触发 onkeypress 摁下触发 1,如果使用addEventListener 不需要加on 2,onkeypress和另外两个的区别是,它不识别功能键,比如左箭头等 3,三个事件的执行顺序:keydown-keypress-keyup

键盘事件对象 keycode 返回该键的ASCLL值 1,onkeydown和onkeyup不区分字母大小写,onkeypress区分字母大小写 2,更多用keydown和keyup 3,keypress不识别功能键,但是keycode属性能区分大小写,返回不同的ascll值

BOM

Dom :文档对象模型,把文档当作对象来操作,顶级对象document ,主要是操作页面元素

BOM:浏览器对象模型,把浏览器当作对象来看待,顶级对象是windows,学习浏览器窗口交互

顶级对象window是js访问浏览器窗口的一个接口 它是一个全局对象,定义在全局作用域中的变量、函数都会变成window对象的属性和方法,在调用时可以省略window

window对象的常见事件 页面(窗口)加载事件

第一种: window.onload =function(){} 或者 window.addEventListener('load',function(){}); window.onlaod 是窗口加载事件,当文档内容完全加载完成会触发该事件(包括图像,脚本文件,css文件),就调用处理函数 1,window.onload传统注册方式只能写一次,如果有多个会以最后一个window.load为准。 2,如果使用addEventListener则没有限制

第二种:DOMContentLoaded

addEventListener('DOMContentLoaded',function(){}) DOMContentLoaded事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。

调整窗口大小事件 window.onresize = function (){} window.addEventListener('resize',function(){}); 只要窗口大小像素发生变化,就会触发这个事件 我们额经常利用这个事件完成响应式布局。window.innerWidth当前屏幕宽度

定时器

setTimeout() 炸弹定时器\ window.setTimeout(调用函数,【延迟毫秒】) 1,window可以省略 2,延迟毫秒数默认为0 3,定时器可以赋一个标识符

两种调用方式:

setTimeout(function(){函数},2000);

第二种

Function 函数名(){

内容}

var time = setTimeout(函数名,3000)。

停止定时器 window.clearTimeout(timeoutID) 1,window可以省略 2,里面的参数就是定时器的标识符

setInterval() 闹钟定时器 开启定时器:window.setInterval(回调函数,【间隔的毫秒数】) setInterval()方法重复调用一个函数,每隔这个时间,就回去调用一次

停止定时器 window.clearInterval(intervalID); 注意赋值对象的作用域

this的指向问题

this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,一般情况下this的最终指向的是那个调用它的对象。

  1. 全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this指向window)

  2. 方法调用中谁调用this指向谁

  3. 构造函数中this指向构造函数的实例

js执行机制

同步:一个任务做完了在做下一个 异步:一个任务执行时间长可以先执行下一个任务

同步任务在主线程上执行,形成一个执行栈 异步任务通过回调函数实现,一般有三种类型

1,普通事件 click、resize

2,资源加载 load error、

3,定时器 异步任务相关的回调函数添加到任务队列中(任务队列也称为消息队列)。

js执行机制(事件循环)

1,先执行执行栈同步任务, 2,异步任务放入任务队列 3,一旦执行栈中所有同步任务都执行完,系统会一次读取任务队列中的异步任务

注意事件中,不触发不到时间不满足条件就不不放入异步队列中 由于主线程不断重复获取任务,执行任务,这种机制被称为事件循环

location对象

window对象给我们提供了一个location属性用于获取或者设计窗体的URL,并且可以用于解析URL。因为这个属性返回一个对象,所以我们也将这个属性称为location对象

location对象常见的方法 location.assign() 何href一样,可以跳转页面,记录历史可以后退 location.replace() 替换当前页面,不记录历史不可以后退 location.reload() 重新加载页面,相当于F5

navigator对象 包含了浏览器的相关信息,最常用的是userAgent,该属性可以返回由客户机发送服务器的user-agent头部的值

history对象。 与浏览器记录进行交互,该对象包含用户访问过的url back()后退 forward()前进 go(参数)

网页特效

元素偏移量offset系列

offset翻译就是偏移量,我们使用offset相关属性可动态的得到该属性的位置,大小等 1,获取元素距离带有定位父元素的位置 2,获得元素自身的大小 3,返回值不带单位

element.offsetParent 带有定位的父元素,父元素没有定位返回body element.offsetTop 返回元素相对带有定位父元素上方的偏移量 element.offsetLeft 返回元素相对带有定位父元素左边框的偏移 element.offsetWidth 返回自身包括padding、边框、内容区的宽度,返回值不带单位 element.offsetHeight 返回自身包括padding、边框、内容区的高度,返回值不带单位

offset 与style 区别 offset 可以得到任意样式表中的样式值 获取数值没有单位 offsetWidth包含padding+border+width offsetWidth 等属性是只读属性,只能获取不能赋值

style style只能得到行内样式表中的样式值 style.width 获得的是带有单位的字符串 style.width获得不包含padding何border的值 style.width是可读写属性,可以获取也可以赋值

元素可视区client系列。 动态获得该元素边框的大小

element.clientTop 返回元素上边框的大小 element.clientLeft 返回元素左边框的大小 element.clientWidth 返回自身包括padding,内容区的宽度,不含边框,返回数值不带单位 element.clientHeight 返回自身包括padding,内容区的高度,不含边框,返回数值不带单位

立即执行函数 1,立即执行函数不需要调用,立即执行 2,写法: (function(){})() (function(){}()) 3 ,多个立即函数,写分号结尾 4,立即函数最大的作用就是创建了一个独立的作用域,避免了命名冲突

pageshow事件: 这个事件在页面显示时触发,无论页面是否来自缓存。事件对象的persisted来判断是否是缓存中的页面触发的pageshow事件,这个事件给window触发

元素滚动scroll系列。动态得到该元素的大小滚动距离

element.scrollTop 返回被卷去的上侧距离,返回数值不带单位 element.scrollLeft 返回被卷去的左侧距离,返回数值不带单位 element.scrollWidth 返回自身实际的宽度,不含边框,返回数值不带单位 包含padding element.scrollHeight 返回自身实际的高度,不含边框,返回数值不带单位 包含padding

页面被卷去的头部:如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll事件。

元素被卷去的头部是 element.scrollTop 页面被卷去的头部是window.pageYoffset

页面被卷去的头部兼容性解决方案

  1. 声明了 DTD,使用 document.documentElement.scrollTop DTD是第一个语句<!DOCTYPE html>

  2. 未声明 DTD,使用 document.body.scrollTop

  3. 新方法 window.pageYOffset和 window.pageXOffset,IE9 开始支持

封装函数解决兼容性问题。 function getScroll() { return { left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft||0, top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0 }; } 使用的时候 getScroll().left

三大系列总结 element.offsetWidth 返回自身包括padding,边框,内容区域宽度,返回值不带单位 element.clientWidth 返回自身包括padding,内容区域宽度,返回值不带单位 element.scrollWidth 返回自身实际宽度,不含边框,返回值不带单位

1.offset系列 经常用于获得元素位置 offsetLeft offsetTop

2.client经常用于获取元素大小 clientWidth clientHeight

3.scroll 经常用于获取滚动距离 scrollTop scrollLeft

4.注意页面滚动的距离通过 window.pageXOffset 获得

mouseenter 和 mouseover区别

mouseover 鼠标经过自身盒子和子盒子回触发, mouseenter 只会经过自身盒子触发

mouseenter不会冒泡,跟mouseenter搭配鼠标离开mouseleave同样不会冒泡

动画函数 核心原理:通过定时器setinterval()不断移动盒子的位置 获得盒子当前的位置,当前的位置加一个移动距离,利用定时器不断重复操作,加一个结束定时器条件,此元素添加定位,才能使用element.style.left

缓动效果

  1. 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。

  2. 核心算法: (目标值 - 现在的位置) / 10 做为每次移动的距离步长

  3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器

  4. 注意步长值需要取整正数往大了取整负数往小取整 step = step>0?Math.ceil(step)\:Mathi.floor(step);

动函数添加回调函数 回调函数原理:函数可以作为一个参数。将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数,这个过程就叫做回调。 回调函数写的位置:定时器结束的位置

动画函数多个目标值之间移动 可以让动画函数容800移动到500 当我们点击按钮,判断步长是正值还是负值,正值步长往大了取整,负值步长往小了取整。

完成代码 function animate(obj, target, callback) { // console.log(callback); callback = function() {} 调用的时候 callback()

// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
    // 步长值写到定时器的里面
    // 把我们步长值改为整数 不要出现小数的问题
    // var step = Math.ceil((target - obj.offsetLeft) / 10);
    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();
    }
    // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
    obj.style.left = obj.offsetLeft + step + 'px';
​
}, 15);

}

节流阀

目的:防止轮播图按钮连续点击造成播放过快当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发。 核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。

开始设置一个变量var flag= true;

If(flag){flag = false; do something} 关闭水龙头

利用回调函数动画执行完毕, flag = true 打开水龙头

移动端网页特效 触屏事件

移动端浏览器兼容性较好,我们不需要考虑以前 JS 的兼容性问题,可以放心的使用原生 JS 书写效果,但是移动端也有自己独特的地方。比如触屏事件 touch(也称触摸事件),Android和 IOS 都有。

触屏touch事件 touchstart 手指摸到dom元素触发 touchmove 手指在一个DOM元素上滑动触发 touchend 手指从一个DOM元素上移开触发

TouchEvent 是一类描述手指在触摸平面(触摸屏、触摸板等)的状态变化的事件 touches 正在触摸屏幕的所有手指的一个列表 targetTouches 正在触摸当前DOM元素上的手指的一个列表 changedTouches 手指状态发生了改变的列表,从无到有,从有到无的变化

平时我们都给元素注册触摸事件,重点记忆targetTocuhes

移动端拖动元素

  1. touchstart、touchmove、touchend 可以实现拖动元素

  2. 但是拖动元素需要当前手指的坐标值 我们可以使用 targetTouches[0] 里面的pageX 和 pageY

  3. 移动端拖动的原理: 手指移动中,计算出手指移动的距离。然后用盒子原来的位置 + 手指移动的距离

  4. 手指移动的距离: 手指滑动中的位置 减去 手指刚开始触摸的位置

拖动元素三步曲:

(1) 触摸元素 touchstart: 获取手指初始坐标,同时获得盒子原来的位置

(2) 移动手指 touchmove: 计算手指的滑动距离,并且移动盒子

(3) 离开手指 touchend:

注意: 手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动 e.preventDefault();

classList属性

classList属性说HTML5新增的属性,返回元素的类名。该属性用于仔元素中添加,移除切换css类。

element.classList.add('类名');

element.classList.remove(’类名‘);

element.classList.toggle('类名');

注意:以上方法里面,所有类名都不带点

click 延时解决方案

移动端 click 事件会有 300ms 的延时,原因是移动端屏幕双击会缩放(double tap to zoom) 页面。

解决方案:

1. 禁用缩放。 浏览器禁用默认的双击缩放行为并且去掉300ms 的点击延迟。
  <meta name="viewport" content="user-scalable=no">
2.利用touch事件自己封装这个事件解决300ms 延迟。
​
原理就是:
  1. 当我们手指触摸屏幕,记录当前触摸时间

  2. 当我们手指离开屏幕, 用离开的时间减去触摸的时间

  3. 如果时间小于150ms,并且没有滑动过屏幕, 那么我们就定义为点击

防抖和节流

1,什么是防抖

防抖策略是当事件被触发后,延迟n秒后再执行回调,如果在这个n秒内事件又被触发,则重新计时。

实现输入框的防抖

//1.定义延迟器的id
var timer = null
//2.定义防抖的函数
function debounceSearch(keywords){
timer=setTimeout(function(){
 getSuggestList(keywords)
},500)
}
//3.在触发keyup事件,立即清空他imer
$('#ipt').on('keyup',function(){
clearTimeout(timer)
....执行的代码
debounceSearch(keywords)
})
 

节流

节流策略,可以减少一段时间内事件的触发频率

节流的应用场景

1.鼠标连续不断的触发某个事件(比如点击),只在单位时间内触发一次;

2.懒加载时要监听计算滚动条的位置,但不必每次滑动都触发,可以降低计算的频率,而不必去浪费cpu资源;

节流阀

节流阀为空,表示可以执行下次操作;不为空,表示不呢个执行下次操作。

当前操作执行完,必须将节流重置为空,表示可以进行下次操作

每次操作前,必须先判断节流阀是否为空

定义一个timer节流阀
当效果执行完毕以后,清空timer节流阀,方便下次开启延时器
判断节流阀是否为空,如果不为空,则证明距离上次执行间隔不足

防抖和节流的区别

防抖:如果事件被频繁的触发,防抖能保证只有最后一次触发生效,前面N多次触发都会被忽略!

节流:如果事件被频繁触发,节流能够减少事件触发的频率,因此节流是有选择性的执行一部分事件

ES6

let:

let声明的变量只在所处于的块级有效。 只在{}中有效

不存在变量提升,

不影响作用域链,

同一个作用域内不允许重复声明

暂时性死区特性: 用let声明的变量会绑定在这个块级作用域,不会受外界的影响

const

声明常量, 常量就是值(内存地址)不能变化的量。 (既然是常量不能重新进行赋值,如果是基本数据类型,不能更改值,如果是复杂数据类型,不能更改地址值)

具有块级作用域{}内有效

声明常量时必须赋值,不能以后在赋值

常量赋值后,值不能修改

标识符一般为大写

不允许重复声明

不能提升变量等级。

应用场景:声明对象用const,非对象声明用let

注意:对象属性修改和数组元素变化不会触发const错误

let 、const、var 区别

var。 函数级作用域(只在函数作用域中隔绝) 变量提升。 值可以更改

let。 块级作用域(花括号级作用域) 变量不提升(不先找let提升作用域) 值可以更改。

const 块级作用域 变量不提升。 值不可以更改

解构赋值

ES6中允许从数组中提取值,按照对应的位置,对变量赋值,对象也可以实现解构

如何解构不成功,变量的值为undefined

let [,b,c] = [1,2,3]

a // undefined

对象解构允许我们使用变量的名字匹配对象的属性。 匹配成功将对象属性的值赋值给变量

  • 解构赋值就是把数据结构分解,然后给变量进行赋值

  • 如果结构不成功,变量跟数值个数不匹配的时候,变量的值为undefined

  • 数组解构用中括号包裹,多个变量用逗号隔开,对象解构用花括号包裹,多个变量用逗号隔开

  • 利用解构赋值能够让我们方便的去取对象中的属性跟方法

demo: 首先有一个定义好的对象。下面用解构赋值的方法来重新定义,后面就可以直接使用了

let person= {name:‘zhangsan’,age:20};

let {name,age} = person; //解构赋值的方法

console.log(name); console.log(age)

应用场景:频繁使用对象方法、数组元素、就可以使用解构赋值形式。

对象的解构赋值,可以方便的将现有对象的方法,复制到某个变量中 比如 let{ log } = console; log(xxx)即可输出

注意:如果将一个已经声明的变量用于解构赋值需要小心

数组

数组扩展之扩展运算符

扩展运算符(spread)是三个点(...)。将一个数组转为用逗号分隔的参数序列。

之前想读取每个数组中的数值需要for循环遍历,现在用扩展运算符即可。替代了es5中的apply方法。

合并数组es6方法

[...arr1,...arr2,...arr3]

属性的简洁表达法

属性名表达式

对象的扩展运算符,对象可以用...展开了

箭头函数

const fn = (参数) => {}

理解:简化函数操作,默认在括号前加function。箭头后面就是return返回的值

1.函数体中只有一句代码,且代码的执行结果就是返回值,可以省略花括号,如果是return语句,return必须省略

2.如果形参只有一个,可以省略小括号

箭头函数没有this关键字,箭头函数中的this,指向的是函数定义位置的上层this。简单理解为定义箭头函数中的作用域的this指向谁,它就指向谁。

箭头函数适合与this无关的回调,定时器,数组方法回调

箭头函数不适合与this有关的回调。事件回调,对象的方法

箭头函数的优点在于解决了this执行环境所造成的一些问题。比如:解决了匿名函数(没有定义赋值的函数)this指向的问题(匿名函数的执行环境具有全局性),包括setTimeout和setInterval中使用this所造成的问题

set数据结构

ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

Set本身是一个构造函数,用来生成Set数据结构

创建方式

const s = new Set();

const s = new Set([1,2,3])

实例用法:

add(value):添加某个值,返回set结构本身

delete(value):删除某个值,返回布尔表示结果

has(value):返回布尔,表示该值是否为Set的成员

clear():清楚所有成员,没有返回值。 删除的是元素的值不是索引

面向过程与面向对象

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步步实现,使用的时候一个个依次调用,适合和硬件紧密接触,不易维护复用、扩展

面向对象是把事务分解成为一个个对象,然后由对象之间分工与合作。易维护复用、扩展。性能比面向过程低

对象与类

对象由属性和方法组成:是一个无需键值对的集合 ,指的是一个具体的事物

1,创建对象

字面量创建: var ldh = {name:'ldh',age:18} console.log(ldh);

构造函数创建对象: function Star (name, age){this.name=name;this.age=age;}

var ldh = new Star('ldh',18) console.log(ldh);

2,类。 在ES6中新增类的概念,可以使用class声明一个类,之后以这个类来实例化对象。类抽象类对象的公共部分,它泛指某一大类对象特指某一个,通过类实例化一个具体的对象

创建类:

class name {}. Var xx = new name();调用

类创建添加属性和方法

class Star {
​
类的共有属性放到constructor中,它是构造器或者构造函数
​
constructor(uname,age){
​
this.uname = name;
​
this.age = age;
​
}
​
sing(song){
​
Console.log(this.uname+'唱'+song);}
​
}
​
var ldh = new Star(‘刘德华’,18);
​
ldh.sing('冰雨');

注意哟:

  1. 通过class 关键字创建类, 类名我们还是习惯性定义首字母大写

  2. 类里面有个constructor 函数,可以接受传递过来的参数,同时返回实例对象

  3. constructor 函数 只要 new 生成实例时,就会自动调用这个函数, 如果我们不写这个函数,类也会自动生成这个函数

  4. 多个函数方法之间不需要添加逗号分隔

  5. 生成实例 new 不能省略

  6. 语法规范, 创建类 类名后面不要加小括号,生成实例 类名后面加小括号, 构造函数不需要加function

  7. 类不存在变量提升,必须先定义类在调用类

实例方法

通过类的实例对象调用方法

class People{
    say(){
        console.log("Hello");
    }
}
var p = new People();
p.say()

实例属性

实例属性指的是类的实例对象可调用的属性

class People{
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    say(){
        console.log(this.name,this.age);
    }
}
var p = new People("iwen",20);
p.say()
console.log(p.name,p.age);

静态方法

类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为‘静态方法’。加上关键字可以通过类名来调用。

class Person {
    static classMethod() {
        console.log("Hello");
    }
}
​
Person.classMethod() // Hello 应为classmethod()是静态方法,所有需要通过类名Person来调用。不能通过实例对象来调用
​
var p = new Person();
p.classMethod() // p.classMethod is not a function

注意:如果静态方法包含this关键字,这个this指的是类(是下面自定义的People),而不是实例对象。

class People {
    static getSay() {
        this.say();
    }
      //这个是静态方法,方法名前加了static
    static say() {
        console.log('hello');
    }
    //这个是实例方法
    say() {
        console.log('world');
    }
}
静态方法通过类名.方法名()调用
People.getSay() // hello

静态属性

静态属性在外面通过类名给它添加属性

class People{}
People.status = "等待"
console.log(People.status);

类的继承

Class可以通过extends关键字实现继承,让子类继承父类的属性和方法。

父类: class Father{}

子类继承父类:class Son extends Father{} //括号内不用写参数,继承了父类的属性和方法

ES6规定子类必须在constructor()方法中调用super()关键字访问调用父类上的函数。可以调用父类的构造函数,也可以调用父类的普通函数。super中把属性拿过来,必须在首行。

实例属性和方法,静态属性和方法都能继承,但是需要用该特有的方法去调用。

注意:

  1. 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的。继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)

  2. 如果子类想要继承父类的方法,同时在自己内部扩展自己的方法,利用super 调用父类的构造函数,super 必须在子类this之前调用!!!!!

  3. 时刻注意this的指向问题,类里面的共有的属性和方法一定要加this使用.

    constructor中this指向的是new出来的实例对象

    自定义的方法,一般也指向的new出来的实例对象

    绑定事件之后this指向的就是触发事件的事件源

4.ES6中类没有变量提升,所以必须先定义类,才能通过类实例化对象 class在前,var定义在后

概述: 类是对象的模版,对象是类的实例,在es6之前,js没有类的概念。对象不是基于类创建的。而是用一种称为构建函数的特殊函数来定义对象和他们的特征。

以下是es5中的方法

构造函数和原型

ES6之前没有类的概念,通过一种构造函数的特殊函数来定义他们的特征。把公共函数抽取出来,在利用构造函数创建对象。

1对象的三种创建方式

1,字面量方式。 Var obj = {};

2,new 关键字。 Var obj = new Object();

3,构造函数方式。

 Function Person(name,age){
​
this.name = name;
​
this.age = age;
this.sing = function(){
console.log('我会唱歌');
}
​
}
var obj = new Person('zs',12);

构造函数是一种特殊的函数,主要用来初始化对象,我们把对象中的一些公共属性和方法抽取出来,然后封装到这个函数里面。

注意:

1.构造函数用于创建某一类对象,首字母要大写

2.构造函数要和new一起使用才有意义

new在执行时候会做的四件事

1,在内存中创建一个新的空对象。

2.让this指向这个新对象

3.构造函数里面的代码,给这个新对象添加属性和方法。

4.返回这个新对象(所以构造函数中不需要return)

静态成员和实例成员

js构造函数中可以添加一些成员,可以在构造函数本身上添加,也可以在构造函数内部的this上添加。

静态成员

在构造函数本身上添加的成员,只能由构造函数本身来访问。

function Star(uname, age) {
this.uname = uname;
this.age = age;
this.sing = function() {
console.log('我会唱歌');
}
}
var ldh = new Star('刘德华', 18);
Star.sex = '男'; 在构造函数身上直接添加一个属性,sex就是一个静态成员
console.log(Star.sex);//静态成员只能通过构造函数来访问,上面叫静态成员

实例成员

在构造函数内部创建的对象成员,只能由实例化的对象来访问

function Star(uname, age) {
this.uname = uname;
this.age = age;
this.sing = function() {
console.log('我会唱歌');
}
​
var ldh = new Star('刘德华', 18);
//实例成员就是构造函数内部通过this添加的成员,uname,age,sing 就是实例成员
ldh.sing()//实例成员只能通过实例化的对象来访问,上面这个就叫实例化对象,具体对象名.方法

构造函数的问题

构造函数很好,但是存在浪费内存的问题。创建不同的实例对象,函数属于复杂数据类型,每个实例对象都要开辟函数空间。代码是一样的但是多占了很多空间

解决方法:prototype

我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法。

构造函数原型prototype对象

构造函数通过原型分配的函数是所有对象共享的,有一个函数就可以,别的实例直接调用节省空间。

每个构造函数都有一个prototype属性,指向另一个对象。这个prototype就是一个对象,这个对象的所有属性和方法啊,都会被构造函数所拥有。

我们要把共享的方法放到prototype对象上,所有实例化对象去访问这个prototype对象,就实现了共享,不需要在开辟 内存空间

function Star(uname, age) {
this.uname = uname;
this.age = age;
}
//方法放到构造函数的原型对象身上
Star.prototype.sing = function() {
console.log('我会唱歌');
}
var ldh = new Star('刘德华', 18);
var zxy = new Star('张学友', 19);
ldh.sing();//我会唱歌
zxy.sing();//我会唱歌

原型是什么: 一个对象,我们也称为prototype为原型对象

原型的作用是什么:共享方法

一般情况下我们的公共属性定义到构造函数里面,公共的方法放到原型对象身上

对象原型___proto___

我们把-- proto--成为对象原型,把prototype称为原型对象。原型对象就是把构造函数共有的方法抽出来单独存放一个空间。

对象 都会有一个属性 proto 指向构造函数(也就是Star)的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有 proto 原型的存在。

__proto__对象原型和原型对象 prototype 是等价的 __proto__对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象 prototype

constructor构造函数

对象原型( --proto--)和构造函数(prototype)原型对象里面都有一个属性 constructor 属性 ,constructor 我们称为构造函数,因为它指回构造函数本身。

constructor 主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。

一般情况下,对象的方法都在构造函数的原型对象中设置。

function Star (naume){
​
this.uname = uname;
​
}
​
Star.prototype.sing = function(){
​
console.log('我会唱歌');}

如果有多个对象的方法,我们可以给原型对象采取对象形式赋值,但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor 就不再指向当前构造函数了。

function Star (naume){
​
this.uname = uname;
​
}
​
Star.prototype = {
​
Constructor: Star;
​
Sing:function(){
​
console.log('我会唱歌');
​
},
​
Move: function(){
​
Console.log('我会演电影')
​
}

此时,我们可以在修改后的原型对象中,添加一个 constructor 指向原来的构造函数。

原型链

只要是对象里面都有一个原型——proto——这个原型指向的是原型对象。原型对象中也有--proto--指向Object原型对象,Object 原型对象的原型指向的是null

每一个实例对象(Star原型对象)又有一个__proto__属性,指向的构造函数的原型对象,构造函数的原型对象也是一个对象,也有__proto__属性,这样一层一层往上找就形成了原型链。

原型链和成员的查找机制

任何对象都有原型对象,也就是prototype属性,任何原型对象也是一个对象,该对象就有__proto__属性,这样一层一层往上找,就形成了一条链,我们称此为原型链;

当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。 如果没有就查找它的原型(也就是 _ _proto__指向的 prototype 原型对象)。 如果还没有就查找原型对象的原型(Object的原型对象)。 依此类推一直找到 Object 为止(null)。 __proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线。

原型对象中this指向

构造函数中的this和原型对象的this都指向我们new出来的实例对象 也就是var出来的ldh

扩展内置对象

可以通过原型对象对原来的内置对象进行扩展自定义的方法。

注意:数组和字符串内置对象不能给原型对象覆盖操作Array.prototype = {} , 只能是Array.prototype .xxx= function(){}方式。

继承

ES6之前没有提供extends继承,我们可以通过构造函数+原型对象模拟实现继承,被称为组合继承

call()

调用这个函数,并且修改函数运行时的this指向。使用c all()的时候 参数一是修改后的this指向

fun.call(thisArg,arg1,arg2,...)

thisArg:当前调用函数this的指向对象

arg1,arg2:传递的其他参数

function fn(x,y) {
  console.log(this);
}
var o = {
name:'andy'
};
fn.call(o,1,2)
此时this指向的是o对象

借用构造函数继承父类型属性

ES6之前没有提供extends继承,我们可以通过构造函数+原型对象模拟实现继承,被称为组合继承

核心原理:通过call()把父类型的this指向指向子类型的this,这样就可以实现子类型继承父类型的属性。

function Father(name,age){
            this.name = name;
            this.age = age;
            // this.sing = function(){
            //     console.log('我会唱歌');
            // }
        }
        function Son(name,age){
           Father.call(this,name,age) 
        //    调用父构造函数,把父构造函数的this指向子构造函数,子构造函数就可以使用name属性
        
        }
         var son = new Son('刘德华',12)
         console.log(son)

借用原型对象继承父类型方法

共有的属性写到构造函数中,共有的方法写到原型对象上。

方法就是父构造函数创建了一个实例对象,它可以关联子原型对象,也可以关联父原型对象。作为中间变量不影响修改子元素父元素也跟着变的问题

 function Father(name,age){
            this.name = name;
            this.age = age;
            // this.sing = function(){
            //     console.log('我会唱歌');
            // }
        }
        // 方法写到了原型对象身上
        Father.prototype.money = function(){
            console.log(1000);
        }
        function Son(name,age,score){
           Father.call(this,name,age) 
        //    调用父构造函数,把父构造函数的this指向子构造函数,子构造函数就可以使用name属性
            this.score = score;
        }
        //Son.prototype = Father.prototype;这样赋值有问题,如果修改了子原型对象,父原型对象也会跟着一起变化。
        
        Son.prototype = new Father();
       //如果利用对象的形式修改了原型对象,要利用constructor指回原来的原型对象。
       Son.prototype.constructor = Son;
       
       Son.prototype.exam = function(){
       console.log('孩子要考试');
       }
        
         var Son = new Son('刘德华',12,100)
         console.log(son)

ES5新增方法

数组方法 forEach遍历数组

arr.forEach(function(数组元素,数组元素的索引,当前的数组))

函数的定义

1,函数声明方式function关键字(命名函数)

function fn(){}

2, 函数表达式(匿名函数)

var fn = function(){}

3,利用new Function()构造函数

var fn = new Function('参数1','参数2','函数体')

参数必须是字符串,执行效率低用的少。所有的函数都是Function的实例对象。函数也属于对象

函数的调用

  1. 普通函数

    function fn() { console.log('人生的巅峰'); } fn();

  2. 对象的方法

    var o = {
    sayHi: function() {
    console.log('人生的巅峰');
    }
    }
    o.sayHi();
    1. 构造函数

      function Star() {};
      new Star();
  3. 绑定事件函数 btn.onclick = function() {}; // 点击了按钮就可以调用这个函数

  4. 定时器函数 setInterval(function() {}, 1000); 这个函数是定时器自动1秒钟调用一次

  5. 立即执行函数(自调用函数) (function() { console.log('人生的巅峰'); })()

函数内部的this指向

this指向,是当我们调用函数的时候确定的。调用方式的不同决定了this的指向不同。一般指向我们的调用者

普通函数 --- window         
构造函数-----  实例对象,原型对象里面的方法也指向实例对象
对象方法调用-----该方法所属的对象。      
事件绑定方法------ 绑定事件对象。
定时器函数 ------window           
立即执行函数-----window

改变函数内部this指向(call,apply,bind)

call()方法调用一个对象,可以改变函数的this指向.主要作用是实现继承

fn.call(对象,1,2)。  无对象指向window,有对象指向对象

apply()方法调用一个函数。简单理解为调用函数的方式。可以改变函数的this指向 经常跟数组有关系 和call主要原因是参数不一样

fn.apply(o,\[1,2])//此时的this指向的是对象o,参数使用必须是数组传递

 

bind()方法不会调用函数,但是能改变函数内部this指向问题。

fun.bind(thisArg,arg1,arg2,...)

thisArg: 在fun函数运行时指定的this值

arg1,arg2:传递的其他参数

 var o = {
            name : 'ni'
         };
         function fn() {
            console.log(this); 
            // 指向window
         };
         var f =fn.bind(o);
         f()
        //  不会调用函数只会改变指向

1.不会调用原来的函数,可以改变原来函数内部的this指向

2.返回的是原函数改变this之后产生的新函数

3.如果有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向此时使用bind

demo:

  var btn = document.querySelector('button');
        btn.onclick = function(){
            this.disabled = true;  //这个this指向的是btn
            setTimeout(function(){
                this.disabled = false;  
            }.bind(this) ,3000);
            // 这个this 指向的是btn这个对象
        }
        

call、apply、bind三者的异同

共同:都可以改变this指向

不同:

call 和apply会调用函数,并且改变函数内部this指向

call和apply传递的参数不一样,call传递参数使用逗号隔开,apply使用数组传递

bind不会立即调用函数,返回的是函数。加括号才立即执行。可以改变函数内部this指向。

应用场景

1,call经常做继承

2,apply经常跟数组有关系,比如借助数学对象是想数组最大值最小值

3,bind不调用函数,但是还想改变this指向,比如改变定时器内部this指向。

严格模式

严格模式可以应用到整个脚本或个别函数。我们可以将严格模式分为 为脚本开启严格模式和为函数开启严格模式。

1,为脚本开启严格模式。 在所有语句前放一个特定语句。 use strict

2,为函数开启严格模式。 需要把use strict 声明放在函数所有语句前

严格模式后使用未声明的变量

严格模式不允许删除变量

严格模式下全局作用域中函数中的 this 是 undefined

严格模式下,如果 构造函数不加new调用, this 指向的是undefined 如果给他赋值则 会报错.

严格模式下,定时器 this 还是指向 window

高阶函数

高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出(简单理解:传值是函数或者return出去的也是函数)

函数也是一种数据类型,同样可以作为参数,传递给另外一个参数使用。最典型的就是作为回调函数。

同理函数也可以作为返回值传递回来

闭包

闭包(closure)指有权访问另一个函数作用域中变量的函数。

简单理解就是 ,一个作用域访问另外一个函数内部的局部变量。

闭包作用:延伸变量的作用范围。

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

递归

如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。简单理解:函数内部自己调用自己, 这个函数就是递归函数

注意:递归函数的作用和循环效果一样,由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件return。

  var num = 1;
        function fn (){
            console.log('调用六次')
            if(num == 6) {
                return;
            }
            num++;
            fn();
        }
        fn();

浅拷贝和深拷贝

浅拷贝只拷贝一层,更深层次对象级别或者数组的只拷贝地址,地址引用,原来的数据变新的也变。

深拷贝拷贝多层,每一级别的数据都会拷贝,碰到对象或者数组单独开辟空间,原对象改变现对象不变。


浅拷贝方法:

   var obj = {
                id:1,
                name:'andy',
                msg:{
                    age:18,
                }
            };
            var o = {};
            for(var k in obj){
                // k是属性名,obj[k]属性值
                o[k] = obj[k];
            }
            console.log(o);

深拷贝方法:遇到对象再次遍历复制

封装一个函数的方式来解决问题
        var obj = {
            id: 1,
            name: 'andy',
            msg: {
                age: 18,
            }
        };
        var o = {};
        function deepCopy(newobj, oldobj) {
            for (var k in oldobj) {
                // 判断我们的属性值属于那种数据类型
                var item = oldobj[k];
                if (item instanceof Array) {
                    newobj[k] = [];
                    deepCopy(newobj[k], item)
                } else if (item instanceof Object) {
                    newobj[k] = {};
                    deepCopy(newobj[k], item)
                } else {
                    newobj[k] = item;
                }
            }
        }
        deepCopy(o, obj);
        console.log(o)

正则表达式

正则表达式是用于匹配字符串中字符组合的模式。在js中,正则表达式也是对象。

创建

方法一: 通过点用RegExp对象的构造函数创建

Var regexp = new RegExp(/123/);

方法二:利用字面量创建

var rg = /123/;

检测正则表达式 : 正则表达式.test(测试文本) 返回布尔值

边界符

^ 表示匹配行首的文本。 以谁开始

$ 表示匹配行尾的文本。 以谁结尾。

字符类

[] 有一系列字符可以选择,只要匹配其中一个就为true;

方括号内加^ 表示取返。

量词符 跟在指定符号后面

正则替换replace

replace() 方法可以实现替换字符串操作,用来替换的参数可以是一个字符串或是一个正则表达式。


防抖和节流

1,什么是防抖

防抖策略是多次触发事件,事件处理函数只能执行一次。

n秒内执行该事件,如果n秒内被被重复触发,则重新计时(回城)

实现输入框的防抖

//1.定义延迟器的id
var timer = null
//2.定义防抖的函数
function debounceSearch(keywords){
timer=setTimeout(function(){
 getSuggestList(keywords)
},500)
}
//3.在触发keyup事件,立即清空他imer
$('#ipt').on('keyup',function(){
clearTimeout(timer)
....执行的代码
debounceSearch(keywords)
})
 

节流

节流策略,可以减少一段时间内事件的触发频率

n秒内只运行一次,若在n秒内重复触发,只有第一次生效(cd期间放技能)

节流的应用场景

1.鼠标连续不断的触发某个事件(比如点击),只在单位时间内触发一次;

2.懒加载时要监听计算滚动条的位置,但不必每次滑动都触发,可以降低计算的频率,而不必去浪费cpu资源;

节流阀

节流阀为空,表示可以执行下次操作;不为空,表示不呢个执行下次操作。

当前操作执行完,必须将节流重置为空,表示可以进行下次操作

每次操作前,必须先判断节流阀是否为空

定义一个timer节流阀
当效果执行完毕以后,清空timer节流阀,方便下次开启延时器
判断节流阀是否为空,如果不为空,则证明距离上次执行间隔不足

防抖和节流的区别

防抖:如果事件被频繁的触发,防抖能保证只有最后一次触发生效,前面N多次触发都会被忽略!

节流:如果事件被频繁触发,节流能够减少事件触发的频率,因此节流是有选择性的执行一部分事件

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值