复习
函数作用域
- 全局作用域
- 局部作用域
- 块级作用域(es6-let,const)
-
优先级
- 局部变量(函数体内声明的变量)>参数变量(函数参数)>全局变量
函数种类
- 无参数无返回值
- 只是将代码封装起来,以供调用
- 有参数无返回值
- 在无参数无返回值的基础上优化,对传入参数进行操作
- 无参数有返回值
- 对函数处理结果进行接收
- 有参数有返回值
- 箭头函数--
()=>{}
- 默认值
- es5 --需要手动设置传入参数的默认值
- es6 --
function(a='1'){}
当无参数传入时,括号内即为默认值
this指向
- 普通函数中的this 指向调用该函数的对象
- 构造函数中的this 指向new出来的实例化对象
- 构造函数的返回值如果是引用值,则new得到的是返回值,如果是原始值类型,则仍返回实例化对象,但是this指向不会改变 (一般情况下不会在构造函数内设置return)
- 事件函数中的this指向事件源
- 箭头函数的this指向会发生改变,所以:
- 事件函数不适合箭头函数--如使用将不再指向触发事件的对象
- 对象中的方法不适合使用箭头函数--将不再指向对应的对象
- 但:
- 可以在一些特定的this函数中,如果需要调用另外的匿名函数,可以使用箭头函数代替
- 函数表达式创建的函数可以使用箭头函数来缩减代码
函数this指向的修改方法--3种
- call
- 调用函数时使用
fn.call(this指向,参数1,参数2)
- apply
- 调用函数时使用
fn.applay(this指向,[参数1,参数2])
- call与apply的区别就在于参数的传递方式不同
- call视参数多少改变传参数量
- apply只有两个参数
- bind
- 声明函数时使用
- bind时函数体的一种方法,调用该方法会得到一个新的函数体,更多情况使用函数表达式来配合bind
-
var fn=function(){}.bind(this指向)
--结合函数表达式,生成新的修改this指向后的函数体
arguments
- 函数内使用,接收传递的超出形参的参数,形成伪数组
- es6中
rest
参数可以完成arguments的功能 -
rest
参数会直接把所有的多余参数转换成一个数组 -
function fn (num,...a){console.log(a)}
--...a
将接收到的多余实参存入数组
js中的对象
Null->Object.prototype->其它对象
- 通过call/apply调用原型链上的方法实现对数据类型的判断
- Object.prototype.toString.call(数组)-->[Object,Array]
- 将类数组对象,转换成数组
- es6--
Array.from()
Array.prototype.slice.call()
- es6--
类 class--es6新增
const Demo = function (a, b) {
this.a = a;
this.b = b;
return this;
};
Demo.prototype = {
constructor: Demo,
print: function () {
console.log(this.a + ' ' + this.b);
}
};
const demo = new Demo('hello', 'world').print();
- 将构造函数的属性与原型链上的方法分开
class Demo {
constructor(a, b) {
this.a = a;
this.b = b;
return this;
}
print() {
console.log(this.a + ' ' + this.b);
}
};
const demo = new Demo('hello', 'world').print();
console.log(typeof demo);
- 可以直接将方法写在构造函数内部
- 不需要逗号-会报错
- super
- super作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次super函数。
- super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类
- super代表了父类A的构造函数,但是返回的是子类B的实例,即super内部的this指的是B,因此super()在这里相当于A.prototype.constructor.call(this)。
- 类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”
- new.target
- new是从构造函数生成实例的命令。ES6为new命令引入了一个new.target属性,(在构造函数中)返回new命令作用于的那个构造函数。如果构造函数不是通过new命令调用的,new.target会返回undefined,因此这个属性可以用来确定构造函数是怎么调用的。
- Class内部调用new.target,返回当前Class。
- 静态方法
- 函数命前声明static,就为静态方法。该方法不会被实例继承,而是直接通过类来调用。
fetch
- IE8+
- 到现在为止,fetch的支持性还不是很好,但是在谷歌浏览器中已经支持了fetch。fetch挂在在BOM中,可以直接在谷歌浏览器中使用。
- Fetch基于Promise
-
Promise
- Promise 对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象
- 一个Promise有以下几个状态
- pending:初始状态,既不是成功,也不是失败状态
- fulfilled:意味着操作成功完成
- rejected:操作失败
- 旧浏览器不支持需要使用polyfilles6-promise
-
Promise
- 使用
- GET请求
// 通过fetch获取百度的错误提示页面 fetch('https://www.baidu.com/search/error.html', { method: 'GET' }) .then((res)=>{ return res.text() }) .then((res)=>{ console.log(res) })
- GET请求传参
// 通过fetch获取百度的错误提示页面 fetch('https://www.baidu.com/search/error.html?a=1&b=2', { // 在URL中写上传递的参数 method: 'GET' }) .then((res)=>{ return res.text() }) .then((res)=>{ console.log(res) })
- POST请求
// 通过fetch获取百度的错误提示页面 fetch('https://www.baidu.com/search/error.html', { method: 'POST' // 指定是POST请求 }) .then((res)=>{ return res.text() }) .then((res)=>{ console.log(res) })
- POST请求传参
// 通过fetch获取百度的错误提示页面 fetch('https://www.baidu.com/search/error.html', { method: 'POST', body: new URLSearchParams([["foo", 1],["bar", 2]]).toString() // 这里是请求对象 }) .then((res)=>{ return res.text() }) .then((res)=>{ console.log(res) })
- 设置请求头
- 在POST提交的过程中,一般是表单提交,可是,经过查询,发现默认的提交方式是:Content-Type:text/plain;charset=UTF-8,这个显然是不合理的
- 请求方式content-type:application/x-www-form-urlencoded。
// 通过fetch获取百度的错误提示页面 fetch('https://www.baidu.com/search/error.html', { method: 'POST', headers: new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' // 指定提交方式为表单提交 }), body: new URLSearchParams([["foo", 1],["bar", 2]]).toString() }) .then((res)=>{ return res.text() }) .then((res)=>{ console.log(res) })
- 通过接口得到JSON数据
// 通过fetch获取百度的错误提示页面 fetch('https://www.baidu.com/rec?platform=wise&ms=1&rset=rcmd&word=123&qid=11327900426705455986&rq=123&from=844b&baiduid=A1D0B88941B30028C375C79CE5AC2E5E%3AFG%3D1&tn=&clientWidth=375&t=1506826017369&r=8255', { // 在URL中写上传递的参数 method: 'GET', headers: new Headers({ 'Accept': 'application/json' // 通过头指定,获取的数据类型是JSON }) }) .then((res)=>{ return res.json() // 返回一个Promise,可以解析成JSON }) .then((res)=>{ console.log(res) // 获取JSON数据 })
- 强制带Cookie
- 默认情况下, fetch 不会从服务端发送或接收任何 cookies, 如果站点依赖于维护一个用户会话,则导致未经认证的请求(要发送 cookies,必须发送凭据头).
// 通过fetch获取百度的错误提示页面 fetch('https://www.baidu.com/search/error.html', { method: 'GET', credentials: 'include' // 强制加入凭据头 }) .then((res)=>{ return res.text() }) .then((res)=>{ console.log(res) })
- 优点
语法简洁,更加语义化
基于标准 Promise 实现,支持 async/await
同构方便,使用 isomorphic-fetch
- 原生支持率并不高,幸运的是,引入下面这些 polyfill 后可以完美支持 IE8+
由于 IE8 是 ES3,需要引入 ES5 的 polyfill: es5-shim, es5-sham
引入 Promise 的 polyfill: es6-promise
引入 fetch 探测库:fetch-detector
引入 fetch 的 polyfill: fetch-ie8
可选:如果你还使用了 jsonp,引入 fetch-jsonp
可选:开启 Babel 的 runtime 模式,现在就使用 async/await
过渡、动画
- transition
- 一个状态 过渡 到另一个状态的动画效果
- 只有开始和结束两个关键帧
- 必须要认为触发才能执行
- animation
- 可以设置多个关键帧
- 动画本身可以自动执行并且设置执行的次数,最多无限次infinite
- 可以实现transiton的效果,但相对而言代码更复杂
- 必须与@keyframes配合使用
- 过程
- 通过@keyframes创建动画规则,然后使用animation和该动画规则进行绑定
- animate.css
transform
- translate
- translate
- 2d平移
- translate3d
- 3d平移-强制使用gpu(显卡)渲染,比2d平移的动画性能更好-即使不涉及z轴平移,为获取更好效果,仍然使用translate3d
- translate
- rotate
- rotate
- rotatex
- rotatey
- rotate3d(x,y,z,角度)
- 三个矢量确定一个方向,这个方向的轴,作为旋转轴,旋转对应的角度
- skew
- 变形,填写角度是元素变形,一般用作果冻动画
- 轴心
- transform-origin
- 改变原点的位置
- transform-origin
- 3d效果
- transform-style:preserve-3d;给容器增加3d效果,name该容器内的元素就能展现3d效果
- perspective
- 视距-加给所有的3d效果元素的最顶层元素即可
- perspection-origin 改变视角
- backface-visibility 背面是否可见
Vue组件通信
- 为啥会有组件通信
- 因为使用组件-组件通信
- 分类
- 父子通信
- 通过props属性进行数据传递
- 子组件配置对象中设置props为对应的名字
- 父组件的组件模板中,为子组件标签添加prop
- 不加v-bind传递静态数据,加则传递动态数据(除key外)
- 子父通信
- 利用自定义事件实现
- 子组件中通过原生事件触发对应函数,在其函数内触发自定义事件
this.$emit("自定义事件","数据")
- 父组件的组件模板中找到对应的子组件标签
@自定义事件="函数"
,然后在父组件methods中设置对应函数接收并处理数据即可 -
sync
修饰符-通过修饰符sync实现类似v-model的效果- 子组件中通过原生事件触发自定义事件
this.$emit("update:自定义事件名x","数据")
- 父组件的组件模板中找到对应的子组件标签
@自定义事件名x.sync="需要修改的数据"
- 子组件中通过原生事件触发自定义事件
- 非父子通信
- 利用自定义事件实现,非父子通信需要借助一个vue实例去触发和监听自定义事件
-
bus.$emit("自定义事件","数据")
,新建一个公共的vue,在触发组件中触发自定义事件 -
bus.$on("自定义事件",(数据)=>{处理数据})
,对应组件中的created周期函数中监听自定义事件
- 父子通信
Vuex
- 提供统一的状态管理
- 生成
var store=new Vuex.Store({})
- 属性
- state
- getters
- state、getters需放在组件的computed中
this.$store.state.xx
/this.$store.getters.xx
- state、getters需放在组件的computed中
- mutations-提交
- actions-分发
- mutations/actions需要放在methods中的某个函数中进行commit、dispatch
- actions不能直接对state中的数据进行修改-在异步操作完成之后提交commit,通过mutations修改state中的数据
生命周期
- create-创建
- mount-挂载
- update-更新
- destroy-销毁-八个声明周期钩子函数
- 组件如果在页面结构中消失,那么正常情况下是被销毁了-触发destroy钩子函数
- 如果在组件外层添加keep-alive组件-缓存对应组件-不会触发destroy钩子函数
- 组件隐藏触发deactivated替换destroyed
- 当组件再次激活时,触发activated
errorCaptured
- 捕捉子孙组件的错误状态
nextTick
- DOM更新完成后执行对应代码
自己上传npm包
- 注册一个自己的npm账号
- npm login // 在自己电脑上登录自己的npm账号
- npm init 初始化自己的包的仓库
- 完成后
npm publish 上传报内容到npm仓库
-
更新
- 修改package.json中的版本号
- 在执行npm publish命令即可
-
删除npm仓库中的包
- npm unpublish 包名 --force
- 强制删除对应包
gulp
- 前端自动化构建工具
- 帮助处理前端需要手动重复完成的一些操作
//基本流程-流水线 gulp.task('任务名',[前置任务],function(){ gulp.src('path') //获取需要进行操作的原材料 .pipe(sass()) //将sass/scss转为css .pipe(autoprefixer()) //将css自动添加前缀 .pipe(gulp.dest('路径'))//将对应处理后的文件输出到指定位置 }) //还可设置监听-文件修改后,自动执行对应操作 gulp.watch('path',['任务名']) //分生产环境,开发环境 不同的环境,执行不同的代码
获取DOM对象 (六种方法)#
- ID
- name
- ClassName
- TagName
- queryselector (兼容不好)
- queryselectorAll (兼容不好)
事件流
- 捕获
- document -》-》 事件源
- 冒泡
- 事件源 -》 -》 Document
绑定事件
- 零级事件
- dom.onclick=function(){}
- 仅绑定对应事件,可能不会执行,当出现该事件时执行对应的函数
- 移除=》dom.onclick=null(dom零级事件只能绑定一个函数,再次绑定则会覆盖之前的)
- 二级事件
- dom.addEventListener("click",fn,false)(第三个属性=》是否在捕获阶段执行对应函数,默认false)
- dom.removeEventListener("click",fn,false)(移除时,三个属性都要相同,否则移除失败)
- dom.attachEvent("onclick",fn)(添加事件监听,兼容模式(兼容更好))
- dom.detachEvent("onclick",fn)(移除,无第三属性,默认为起泡阶段执行对应事件)
事件委托
- 利用冒泡机制实现
- 不管事件绑定给谁,对应事件对象中的target肯定是交互上的目标元素
- 将事件绑定给父元素或祖先元素
兼容
- e(事件对象)
- var e=e||window.event
- target(事件目标)
- e.target||e.srcElement
阻止
- 阻止事件冒泡
- stopPropagation()
- cancleBubble=true
- 组织事件的默认行为
- 表单的提交(伴随页面的刷新) / a标签的跳转(href="javascript:;")
- preventDefault()
- returnValue=false
- return false(只能写在最后,其后代码不再执行)
闭包
闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁
-
使用闭包的注意点
(1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
(2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
-
三大特点
- 函数嵌套函数
- 内部函数可以访问外部函数的变量
- 参数和变量不会被回收
闭包的作用在于,可以通过闭包,设计私有变量及方法
构造函数
- new出来的实例对象中是没有对应的方法的,但可以调用
- 原型对象为什么叫原型对象(因为上一层的proto指向它)
- 继承-》当前对象拥有另外一个对象的属性和方法
- 继承=》将父对象的相关原型链嫁接到子对象上
IIFE(Immediately-invoked function expression)
- 创建块级(私有)作用域,避免了向全局作用域中添加变量和函数,因此也避免了多人开发中全局变量和函数的命名冲突
- IIFE中定义的任何变量和函数,都会在执行结束时被销毁。这种做法可以减少闭包占用的内存问题,因为没有指向匿名函数的引用。只要函数执行完毕,就可以立即销毁其作用域链了
跨域
CORS跨域(Cross-Origin Eesource Sharing 跨域资源共享)
- html5规范定义的如何跨域访问资源
-
报错
- No 'Access-Control-Allow-Origin' header is present on the requested resource
-
原因
- 请求的url的协议,域名,端口,三者任意一个当前页面地址不同即为跨域
- 根本原因浏览器的安全措施:同源策略-域名、端口、协议
-
隐患
- CSRF(Cross-site request forgery)跨站请求伪造
- 用户通过浏览器,访问正常网站A(例如某银行),通过用户的身份认证(比如用户名/密码)成功A网站。
- 网站A产生Cookie信息并返回给用户的浏览器;
- 用户保持A网站页面登录状态,在同一浏览器中,打开一个新的TAB页访问恶意网站B;
- 网站B接收到用户请求后,返回一些攻击性代码,请求A网站的资源(例如转账请求);
- 浏览器执行恶意代码,在用户不知情的情况下携带Cookie信息,向网站A发出请求。
- 网站A根据用户的Cookie信息核实用户身份(此时用户在A网站是已登录状态),A网站会处理该请求,导致来自网站B的恶意请求被执行。
- CSRF(Cross-site request forgery)跨站请求伪造
- 实现方法
vue proxyTable-接口跨域请求调试(代理)
- vue-route提供的结局跨域的方法
- 文件路径
- config-》index.js->dev(对象)->proxyTable(属性)=》
'/apis': { // 测试环境 target: 'https://goods.footer.com', // 接口域名 changeOrigin: true, //是否跨域 pathRewrite: { '^/apis': '' //需要rewrite重写的, } } }
- config-》index.js->dev(对象)->proxyTable(属性)=》
JSONP
- 只能使用GET请求,并且要求返回JavaScript。利用浏览器允许跨域引用JavaScript资源
- JSONP通常以函数调用的形式返回
- 将需要获取的数据,放在请求到的JavaScript返回函数中,作为参数传回
- 请求的方式
- GET、POST、HEAD、PUT、DELETE