- day01 4.13日背诵*
- Vue相关 vue的全是重点,其他重点都标上了*号
- 一、vue双向数据绑定
- 二、vue虚拟dom,diff算法
- 三、组件通讯
- 四、Vuex
- 五、自定义指令,自定义过滤器
- vue中自定义过滤器
- 六、vue-router(路由原理?路由守卫?传参)
- 七、生命周期(那几个?每一个生命周期的特点,可以做什么)
- 八、自定义组件
- 九、常见的指令,修饰符
- 十、Vue2和vue3的区别
- 十一、Keep-alive
- 十二、多环境变量
- 十三、对axios封装(url统一管理、axios请求拦截、响应拦截、函数封装)
- 十四、Element-ui和vant-ui按需引入
- 十五、Sass配置
- 十六、Rem、vm/vh设置
- 十七、Webpack配置(配置跨域、路径别名、打包分析、cdn引入、去掉console.log、单独打包第三方模块、ie兼容、eslint规范、图片压缩)
- 十八、Slot插槽
- 十九、为什么v-for使用key
- 二十、为什么data是一个函数
- day02 4.14号背诵*
- css相关
- day03 4.15*
- JS相关
- day 04 4.16**
- 7、Ajax
- 7-2、JSONP原理:
- 8、存储
- 9、let、var、const区别
- 10、es6解构赋值
- 11、箭头函数与普通函数的区别
- 12.class与class继承 *
- 13、promise使用及实现
day01 4.13日背诵*
Vue相关 vue的全是重点,其他重点都标上了*号
一、vue双向数据绑定
是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图,实现数据和视图同步。
第一步: 需要observer的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter,这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
第二步: compile(模板解析器)解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
第三步: Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:
1、在自身实例化时往属性订阅器(dep)里面添加自己
2、自身必须有一个update()方法
3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
第四步: MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。
二、vue虚拟dom,diff算法
想要理解虚拟dom首先要知道什么是虚拟dom?
虚拟dom可以简单的用一句话概括,就是根据模板(真实的dom)生成的一个js对象,因为不是真实DOM,所以称之为虚拟DOM。
虚拟dom是相对于浏览器所渲染出来的真实dom而言的,在react,vue等技术出现之前,我们要改变页面展示的内容,只能通过遍历查询dom树的方式,找到需要修改的dom,然后修改样式行为或者结构,来达到更新视图的目的。
创建真实DOM成本比较高,如果用js对象来描述一个dom节点,成本比较低,另外我们在频繁操作dom是一种比较大的开销。所以建议用虚拟dom来描述真实dom。
Diff算法
diff算法就是进行虚拟节点对比,并返回一个patch对象,用来存储两个节点不同的地方,最后用patch记录的消息去局部更新Dom。
你觉得虚拟DOM的性能一定高于常规DOM吗?
答案是不一定,虚拟DOM和Diff算法的出现是为了解决由命令式编程转变为函数式编程、数据驱动后所带来的性能问题的。换句话说,直接操作DOM的性能并不会低于虚拟DOM和Diff算法,甚至还会优于。
你觉得使用了虚拟DOM就真的不操作dom元素了吗?其实不是的,只是减少用户操作dom,虚拟DOM在渲染的时候其实还是会操作dom的
三、组件通讯
1.父传子:
在父组件的子组件标签上绑定一个属性,挂载要传输的变量。在子组件中通过props来接受数据,props可以是数组也可以是对象,接受的数据可以直接使用 props:["属性名"] props:{属性名:数据类型}
2.子传父:
在父组件的子组件标签上通过绑定自定义事件,接受子组件传递过来的事件。子组件通过$emit触发父组件上的自定义事件,发送参数
3.兄弟组件传值:
通过main.js初始化一个全局的$bus,在发送事件的一方通过$bus.$emit(“事件名”,传递的参数信息)发送,在接收事件的一方通过$bus.$on("事件名",参数)接收传递的事件
四、Vuex
1.vuex :是一个专为vue.js开发的状态管理器,采用集中式存储的所有组件状态,通过vuex我们可以解决组件之间数据共享的问题,后期也方便我们管理以及维护
有五个属性分别是: state、getters、mutations、actions、module
state属性: 存放状态,例如你要存放的数据
getters: 类似于共享属性,可以通过this.$store.getters来获取存放在state里面的数据
mutations: 唯一能改变state的状态就是通过提交mutations来改变,this.$store.commit()
actions: 异步的mutations,可以通过dispatch来分发从而改变state
module:模块
2.基本使用:我通过是在根目录下新建一个store文件夹,里面创建一个index.js文件,最后在main.js中引入,并挂载到实例上,之后那个组件中需要用到vuex就调用就行
3.高级用法-数据持久化
vuex里面存放的数据,页面一经刷新会丢失:
解决办法: 存放在localStorage或者sessionStorage里面,进入页面时判断是否丢失,丢失再去localStorage或者sessionStorage里面取;
在vuex中可以通过安装vuex-persist 插件,进行持久化的配置就行
4.高级用法-辅助函数(语法糖)
1. 有那几个辅助函数(4大金刚)
mapState,mapActions,mapMutations,mapGetters
2. 辅助函数可以把vuex中的数据和方法映射到vue组件中。达到简化操作的目的
3. 如何使用:
Import { mapActions, mapGetters, mapMutations, mapState } from 'vuex'
五、自定义指令,自定义过滤器
vue中的自定义指令:
vue中除了核心功能内置的指令外,也允许注册自定义指令。有的情况下,对普通DOM元素进行底层操作,这时候就会用到自定义指令。自定义指令又分为全局的自定义指令和局部自定义指令。
全局自定义指令是通过Vue.directive(‘第一个参数是指令的名称’,{第二个参数是一个对象,这个对象上有钩子函数})
Vue.directive(‘focus’, {
// el:指令所绑定的元素,可以用来直接操作 DOM。
//binding:一个对象,包含以下 property:
inserted: function (el) { // inserted 表示被绑定元素插入父节点时调用
el.focus();
}
});
局部自定义指令:
是定义在组件内部的,只能在当前组件中使用
directives: {
// 指令名称
dir1: {
inserted(el) {
// 指令中第一个参数是当前使用指令的DOM
console.log(el);
console.log(arguments);
// 对DOM进行操作
el.style.width = ‘200px’;
el.style.height = ‘200px’;
el.style.background = ‘#000’;
}
},
color: { // 为元素设置指定的字体颜色
bind(el, binding) {
el.style.color = binding.value;
}
}
}
钩子函数:
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。
项目中:拖拽
vue中自定义过滤器
过滤器是对即将显示的数据做进一步的筛选处理,然后显示,过滤器并没有改变原来的数据,只是在原数据的基础上产生新的数据
过滤器分为全局过滤器和局部过滤器
全局过滤器
全局过滤器是通过Vue.filter()来定义的,定义好后,它在所有组件中都可以使用。
// global-filter是过滤器名称
// 函数第一个参数是需要过滤的数据.
// 函数第二个参数是给过滤器传递的值.
Vue.filter(‘global-filter’,(val,…args)=>{
console.log(需要过滤的数据是:${val}
)
return val + ‘ 过滤器追加的数据’
})
局部过滤器
局部过滤器,定义在组件内部 filters 属性上.它只能在此组件内部使用.
过滤器的使用方式是,在双花括号或v-bind中通过一个管道符来拼接,
项目中使用过滤器:时间,价钱
六、vue-router(路由原理?路由守卫?传参)
路由原理
1.路由就是用来解析URL实现不同页面之间的跳转
hash模式:在浏览器中符号的“#”,以及#后面的字符称之为hash,用window.location.hash读取;
特点:
hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,
hash不会重加载页面。
hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。
history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),
replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
特点:
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 地址后加上/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。
路由传参:
三种:
分别是query,params,动态路由传参
接收:
通过query方式传递过来的参数一般是通过this.route.params接收
通过动态路由传参方式传递过来的参数一般是通过this.$route.params接收
query使用path和name传参跳转都可以,而params只能使用name传参跳转。
传参跳转页面时,query不需要再路由上配参数就能在新的页面获取到参数,params也可以不用配,但是params不在路由配参数的话,当用户刷新当前页面的时候,参数就会消失。
也就是说使用params不在路由配参数跳转,只有第一次进入页面参数有效,刷新页面参数就会消失。
路由守卫:
2.路由守卫使用的方式有几种? 全局的 单个路由独享的 组件级的
3.vue-router全局有三个守卫:
router.beforeEach 全局前置守卫 进入路由之前
router.beforeResolve 全局解析守卫(2.5.0+) 在beforeRouteEnter调用之后调用 router.afterEach 全局后置钩子 进入路由之后
组件内的守卫:
beforeRouteEnter
beforeRouteUpdata(2.2新增)
beforeRouteLeave
- 路由守卫钩子函数里面的三个参数分别是什么?
to,from,next 这三个参数:
to和from是将要进入和将要离开的路由对象,路由对象指的是平时通过this.$route获取到的路由对象。
next:Function 这个参数是个函数,且必须调用,否则不能进入路由(页面空白)。
next() 进入该路由。
next(false): 取消进入路由,url地址重置为from路由地址(也就是将要离开的路由地址)。 next 跳转新路由,当前的导航被中断,重新开始一个新的导航。
七、生命周期(那几个?每一个生命周期的特点,可以做什么)
生命周期让我们在控制整个vue时更容易形成更好的逻辑,可以分为三个阶段,挂载阶段,更新阶段,销毁阶段
分别有:
创建前:beforeCreate() 只有一些实例本身的事件和生命周期函数
创建后:Created() 是最早使用data和methods中数据的钩子函数
挂载前:beforeMount() 指令已经解析完毕,内存中已经生成dom树
挂载后:Mounted() dom渲染完毕页面和内存的数据已经同步
更新前:beforeUptate() 当data的数据发生改变会执行这个钩子,内存中的数据是新的,页面是旧的
更新后:Updated() 内存和页面都是新的
销毁前:beforeDestroy() 即将销毁data和methods中的数据此时还是可以使用的,可以做一些释放内存的操作
销毁后:Destroyed() 已经销毁完毕
Vue3.0中的生命周期做了一些改动:
beforeCreate -> setup() 开始创建组件之前,创建的是data和method
created -> setup()
beforeMount -> onBeforeMount 组件挂载到节点上之前执行的函数。
mounted -> onMounted 组件挂载完成后执行的函数
beforeUpdate -> onBeforeUpdate 组件更新之前执行的函数。
updated -> onUpdated 组件更新完成之后执行的函数。
beforeDestroy -> onBeforeUnmount 组件挂载到节点上之前执行的函数。
destroyed -> onUnmounted 组件卸载之前执行的函数。
八、自定义组件
在vue中开发,都是用的组件化的思想开发的,
在vue中使用组件封装的方式可以使我们的开发效率提高,能够把页面抽象成相对独立的模块。
一个组件由三部分构成 template script 和 style,我们在开发项目中会定定义一些公共组件。如:swiper(轮播功能组件),tabbar(切换功能组件)、list(上拉加载更多功能组件))。
定义好的组件通过import导入,component注册好名称,最后挂载到父组件中的template即可。
组件封装的方式解决了我们传统项目,开发效率低,难以维护,复用性低等问题。
九、常见的指令,修饰符
常用指令
指令就是根据不同的值,框架会进行相关DOM操作的绑定
vue中的指令有很多,我们平时做项目常用的有:
v-if:是动态的向DOM树中添加或者删除元素;
v-else是搭配v-if使用的,它必须紧跟在v-if或者v-else-if后面,否则不起作用
v-show:是通过标签的CSS样式display的值是不是none,控制显示隐藏
区别:
1、当条件为真的时候 没有区别 当条件为假的时候 v-if通过创建或删除DOM节点来实现元素的显示隐藏,v-show通过css中的display属性来控制
2、v-if更适合数据的筛选和初始渲染 v-show更适合元素的切换
v-for: v-for是根据遍历数据来进行渲染,要配合key使用。要注意的是当v-for和v-if同处于一个节点时,v-for的优先级比v-if更高。这意味着v-if将运行在每个v-for循环中
v-on:用来绑定一个事件或者方法,简写方式是@click=””
v-bind: v-bind用来动态的绑定一个或者多个属性。没有参数时,可以绑定到一个包含键值的对象。常用于动态绑定class和style。以及href等。简写的方式是“:属性名=”””一个冒号
v-model 只能适用于在表单元素上,可以实现数据双向绑定 ,
修饰符:
在Vue中,事件修饰符处理了许多DOM事件的细节,让我们不再需要花大量的时间去处理这些烦恼的事情,而能有更多的精力专注于程序的逻辑处理。在Vue中事件修饰符常用的主要有:
.stop :阻止事件冒泡:由内而外,通俗的将就是阻止事件将向上级DOM元素传递
.capture :事件捕获:由外而内,在捕获阶段,事件从window开始,之后是document对象,一直到触发事件的元素。
.self :当事件作用在元素本身时才会触发
.once :只触发一次
.prevent: 阻止默认事件
·passive:告诉浏览器你不想阻止事件的默认行为
·trim:自动过滤用户输入的首尾空格
语法:@事件名.修饰符=“方法名”
十、Vue2和vue3的区别
1.双向数据绑定原理发生了改变,使用proxy替换Object.defineProerty,使用Proxy的优势:
可直接监听数组类型的数据变化
监听的目标为对象本身,不需要像Object.defineProperty一样遍历每个属性,有一定的性能提升
可直接实现对象属性的新增/删除
2.默认使用懒加载
在2.x版本里。不管数据多大,都会在一开始就为其创建观察者,在数据很大时,就会造成性能的问题。在3.x中,只会对渲染出来的数据创建观察者,而且3.x的观察者更高效。
3.3.0新加入了TypeScript以及PWA支持
4.重构Virtual DOM
模板编译时的优化,将一些静态节点编译成常量
Slot优化,将slot编译为lazy函数,将slot的渲染的决定权交给子组织
5.生命周期有了一定的区别
Vue2———————vue3
beforeCreate -> setup() 开始创建组件之前,创建的是data和method
created -> setup()
beforeMount -> onBeforeMount 组件挂载到节点上之前执行的函数。
mounted -> onMounted 组件挂载完成后执行的函数
beforeUpdate -> onBeforeUpdate 组件更新之前执行的函数。
updated -> onUpdated 组件更新完成之后执行的函数。
beforeDestroy -> onBeforeUnmount 组件挂载到节点上之前执行的函数。
destroyed -> onUnmounted 组件卸载之前执行的函数。
activated -> onActivated 组件卸载完成后执行的函数
deactivated -> onDeactivated
十一、Keep-alive
keep-alive 是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件链中。
在组件切换过程中 把切换出去的组件保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性
被包含在 keep-alive 中创建的组件,会多出两个生命周期的钩子: activated(组件激活时使用) 与 deactivated(组价离开时调用)
如果需要缓存整个项目,直接在app.vue中用keep-alive包裹router-view即可。
两种方法:第一种要缓存部分页面,需要在路由地址配置中,在meta属性中添加一个状态,在app.vue中判断一下包裹的router-view即可,
第二种也可以使用exclude和include规定缓存哪个组件不缓存哪个组件
例如有一个商品页面和一个详情页面,这样在两个页面切换的时候就可以用到keep-alive,在切换到详情的时候,把状态保留在内存中,而不是销毁,从而提高一个性能的优化
十二、多环境变量
首先是通过在根目录下创建.env.*(配置文件)文件,development 本地开发环境配置、test测试环境配置、production 正式环境配置。我们可以在封装的接口api文件夹中定义baseUrl文件,来区分不同环境下对应的不同的基本路径。
十三、对axios封装(url统一管理、axios请求拦截、响应拦截、函数封装)
首先要安装axios,创建request.js。request.js文件用来封装我们的axios,api.js用来统一管理我们的接口url,
在request.js中添加请求拦截和响应拦截。在请求拦截中,会给请求头添加token字段,还有loading动画的开启。在响应拦截中,可以做一些loading动画的关闭,还有可以根据后端返回的状态码,做一些检验token是否有效或者过期的操作。接着就是做一些axios进行的api接口的封装,这里我用到了async,await封装请求接口函数,这样可以将异步操作同步化操作,代码更加友好,避免回调地域的出现。
十四、Element-ui和vant-ui按需引入
首先安装按需引入的插件,在babel.config.js中添加按需引入的配置,创建一个plugin文件夹,定义一个js文件用来存放按需引入的代码,之后在建好的js文件中首先导入vue,再导入需要的vant-ui插件,通过vue.use()全局注入。
修改样式可以用样式穿透 /deep/0
十五、Sass配置
安装node-sass sass-loader
使用lang=”scss”
十六、Rem、vm/vh设置
第一种方式
使用app.js 在这个js中获取屏幕的宽度,设置根元素的font-size,一般以750的设计图为基准,那么我们需要在375的屏幕下设置根元素的font-size为50 (理由是好计算),所以是屏幕的宽度除7.5 ,把这个js引入main.js使用,在定义元素的宽度的时候可以转化为rem
第二种方式 使用插件 lib-flexible计算rem的 postcss-pxtorem 把px转化为rem
1.通过安装cnpm install lib-flexible postcss-pxtorem —save-dev
2.Main.js 中导入插件
3.根目录创建.postcssrc.js配置
十七、Webpack配置(配置跨域、路径别名、打包分析、cdn引入、去掉console.log、单独打包第三方模块、ie兼容、eslint规范、图片压缩)
在vue中定义vue.config.js文件,定义proxy用来跨域,publicPath用来定义路径别名,assetsDir用来规定放止静态资源的文件夹,
cdn的意思是使用外部script或者link的方式引入外部资源比如说axios等插件而不把这个文件打包在上线文件夹中,在配置文件中首先定义externals忽略这些文件,使之不打包进项目中,然后配置cdn定义外部引入的链接
压缩图片使用第三方插件cnpm i image-webpack-loader -D 在vue.config.js中对这个插件进行配置,用test方法筛选要压缩的图片格式,use方法使用插件,就可以在打包npm run build 的对图片进行压缩
十八、Slot插槽
插槽就是父组件往子组件中插入一些内容。
有三种方式,默认插槽,具名插槽,作用域插槽
1.默认插槽就是把父组件中的数据,显示在子组件中,子组件通过一个slot插槽标签显示父组件中的数据
2.具名插槽是在父组件中通过slot属性,给插槽命名,在子组件中通过slot标签,根据定义好的名字填充到对应的位置。
3.作用域插槽是带数据的插槽,子组件提供给父组件的参数,父组件根据子组件传过来的插槽数据来进行不同的展现和填充内容。在标签中通过slot-scope来接受数据。
十九、为什么v-for使用key
key是给每一个vnode的唯一id,也是diff的一种优化策略,可以根据key,更准确, 更快的找到对应的vnode节点
二十、为什么data是一个函数
1.根实例对象data可以是对象也可以是函数(根实例是单例),不会产生数据污染情况
如果不是一个函数,每个组件实例的data都是同一个引用数据,当该组件作为公共组件共享使用,一个地方的data更改,所有的data一起改变,如果data是一个函数,每个实例的data都在闭包中,就不会各自影响了。
day02 4.14号背诵*
css相关
一、什么是盒模型
把所有的网页元素都看成一个盒子,它具有: content,padding ,border,margin 四个属性,这就是盒子模型
盒子模型有两种形式:标准盒子模型,怪异盒子模型
两种模式可以利用box-sizing属性进行自行选择:
标准模式:box-sizing:content-box;
怪异模式:box-sizing:border-box;
两种模式的区别:
标准模式会被设置的padding撑开
而怪异模式则相当于将盒子的大小固定好,再将内容装入盒子,盒子的大小并不会被padding所撑
二、BFC *
1、什么是BFC?
BFC是一块独立的布局环境,保护其中内部元素不受外部影响,也不影响外部。本身BFC是一种css的布局方式,只是我们可以利用它来解决外边距折叠的问题,BFC并不是专门用来解决这个问题而创的;
2、如何触发BFC?
float的值不是none、
position的值不是static或relative 、
display的值是inline-block 、
或 table-cell 或 flex 、
或 table-caption 、
或 inline-flex、overflow的值不是visible;
BFC的用途?
a.解决父子的外边距折叠问题(因为BFC模型只作用于本身的内部元素,就是父子关系),给父元素加入上述的css属性即可,(注意:无法解决父元素兄弟之间的外边距折叠问题)、
b.实现了块级元素独占一行的特性,并且规定了浮动元素不被静态文档流元素影响。(这是为什么块级元素独占一行的原因)、
c.清除浮动影响,BFC在计算高度时,会一同计算浮动元素的高度,所以也可以清除浮动带来的影响。
使用after伪元素清除浮动
优点:符合闭合浮动思想,结构语义化正确,不容易出现其他问题 缺点:IE6-7不支持伪元素:after,使用zoom:1触发
【不常用:除了这四种还有一种更为简单的方式,给父元素定义好height高度,就解决了父级元素无法获取到高度的问题。】
四、元素居中的方式 》
方法一:父相子绝后,子分部向左向上移动本身宽度和高度的一半(也可以用
transform:translate(-50%,-50%))最常用方法
方法二:父元素设置成弹性盒,子元素横向居中,纵向居中
方法三:父相子绝,子元素所有定位为0,margin设置auto自适应。
五、两/三栏布局(圣杯双飞翼)
1、两栏布局,左边定宽,右边自适应
左边左浮动,右边加overflow:hidden;变成BFC清除左侧浮动元素的影响
2、三栏布局,圣杯布局,双飞翼布局
首先定义出整个布局的DOM结构,主体部分是由conatiner包裹的center,left,right三列,其中center定义在最前面。
(1)假设左侧的固定宽度为200px,y右侧的固定宽度为150px,则首先在container上设置
(2)随后分别为三列设置宽度与浮动,同时对footer设置清除浮动:
(3)根据浮动的特性,由于center的宽度为100%,即占据了第一行的所有空间,所以left和right被挤到了下一行,接下来的工作是将left放置到之前预留出的位置上,这里使用负外边距:
(4)随后使用定位方法
六、flex布局 》
我在项目中常用到的有九宫格布局,列表布局等,都会经常用到。
Flex 布局,可以简便、完整、响应式地实现各种页面布局,任何一个容器都可以指定为 Flex 布局,行内元素也可以使用 Flex 布局。
Flex的属性:
flex-direction (决定主轴的方向)
flex-wrap (换行样式)
flex-flow (flex-direction和flex-wrap的简写形式,默认为flex-flow: row nowrap)
justify-content (定义项目在横轴上的对齐方式)
align-items (定义项目在纵轴上如何对齐)
align-content (定义了多行的对齐方式。如果项目只有一行,该属性不起作用。)
七、常见的块级、行级、空元素 》
(1)、块级元素
- 没有设置宽度时,它的宽度是其容器的 100%;
- 可以给块级元素设置宽高、内边距、外边距等盒模型属性;
- 块级元素可以包含块级元素和行内元素;
- 常见的块级元素有:<div>、<h1> ~ <h6>、<p>、<ul>、<ol>、<dl>、<table>、<address> <form>
(2)行内元素
- 行内元素不会独占一行,只会占领自身宽高所需要的空间;
- 给行内元素设置宽高不会起作用,margin 值只对左右起作用,padding 值也只对左右起作用;
- 行内元素一般不可以包含块级元素,只能包含行内元素和文本;
- 常见的行内元素有 : <a>、<b>、<label>、<span>、<img>、<em>、<strong>、<i>、<input>
(3)空元素 ( 在 HTML[1] 元素中,没有内容的 HTML 元素被称为空元素 )
<br/> ---换行 <hr> ---分隔线 <input> ---文本框等
<img> ---图片 <link>---外链 <meta>
八、Css Hack
由于不同的浏览器和浏览器各版本对CSS的支持及解析结果不一样,以及CSS优先级对浏览器展现效果的影响**,我们可以据此针对**不同的浏览器情景来应用不同的CSS。
(1)、选择符
(1)IE6 能识别 `*html .class{}`
(2)IE7 能识别 `*+html .class{}` 或 `*:first-child+html .class{}
(2)、属性
(1)IE6 能识别下划线" _ "和星号" * "
(2)IE7 能识别星号" * ",但不能识别下划线" _ "
(3)IE6~IE10 都识别" \9 "
(4)firefox 前述三个都不能识别。`
(3)、条件
(1)所有 IE (注:IE10+ 已经不再支持条件注释)能识别
<!--[if IE]>IE浏览器显示的内容 <![endif]-->
(2)IE6及以下版本能识别
<!--[if lt IE 6]>只在IE6-显示的内容 <![endif]-->
这类 Hack 不仅对 CSS 生效,对写在判断语句里面的所有代码都会生效。
(3)实际项目中 CSS Hack 大部分是针对 IE 浏览器不同版本之间的表现差异而引入的。
九、src与href的区别 》
主要区别:
1.请求资源类型不同
(1)href是网络资源,src是外部资源。
(5-2)href是超链接,src资源会嵌套到当前标签。
2.作用结果不同
(1)href 用于在当前文档和引用资源之间确立联系;
(2)src 用于替换当前内容;
3.浏览器解析方式不同
(1)若在文档中添加href ,浏览器会识别该文档为 CSS 文件,就会并行下载资源并且不会停止对当前文档的处理。
(2)当浏览器解析到src ,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,图片和框架等也如此,类似于将所指向资源应用到当前内容。这也是为什么建议把 js 脚本放在底部而不是头部的原因。
十、link与@import区别
两者都是外部引用CSS的方式,但是存在一定的区别:
区别1:link除了引用样式文件,还可以引用图片等资源文件,而import只引用样式文件
区别2:link引用CSS时,在页面载入时同时加载;@import需要页面网页完全载入以后加载。
区别3:link是XHTML标签,无兼容问题;@import是在CSS2.1提出的,低版本的浏览器不支持。
区别4:link支持使用Javascript控制DOM去改变样式;而@import不支持。
十一、css3/H5新特性 (各记两个)》
一、css3
1、选择器
:last-child /* 选择元素最后一个孩子 */ :nth-child(even) /* 按照偶数 */
:first-child /* 选择元素第一个孩子 */ :nth-child(odd) /* 按照奇数 */
:disabled /* 选择每个禁用的dom元素 */ checked /* 选择每个被选中的dom元素 */
:nth-child(1) /* 按照第几个孩子给它设置样式 */
2.背景和边框
border-radius: 圆角
border-shadow/text-shadow: 阴影
border-image: 边框图片
3.文本效果 (单词)
text-shadow 向文本添加阴影
text-justify 规定当 text-align 设置为 “justify” 时所使用的对齐方法
text-emphasis 向元素的文本应用重点标记以及重点标记的前景色
text-outline 规定文本的轮廓
text-overflow 规定当文本溢出包含元素时发生的事情
text-wrap 规定文本的换行规则
word-break 规定非中日韩文本的换行规则
word-wrap 允许对长的不可分割的单词进行分割并换行到下一行
text-decoration 文本修饰符:overline、line-through、underline (上划线、中划线、下划线)
二、html5新特性
1. 语义化标签:
文档头部:header、文档尾部:footer、文档中的节点:section、
导航:nav、侧边栏:aside、独立内容区域:article
2. 增强型表单:HTML5 拥有多个新的表单 Input 输入类型。这些新特性提供了更好的输入控制和验证
3. 新增表单属性:(placehoder、required、min 和 max)、
音频视频:(audio、video、canvas )画布、地理定位、拖拽、
本地存储:localStorage 没有时间限制的数据存储;
sessionStorage, session 的数据存储,当用户关闭浏览器窗口后,数据会被删除
三、新事件:(可以看情况多记几个)
onresize 当调整窗口大小时触发 ondrag 当拖动元素时触发
onscroll 当滚动滚动元素的滚动条时触发 onmousewheel 当转动鼠标滚轮时触发
onerror 当错误发生时触发 onplay 当媒介数据将要开始播放时触发
onpause 当媒介数据暂停时触发
十二、浏览器兼容性问题 (html css js每种背两个) *
一、不同浏览器的标签默认间距不同,所以在网页解析有一定的差异
1、.css3新属性,加浏览器前缀兼容早期浏览
-moz- 火狐浏览器
-webkit- Safari, 谷歌浏览器等使用Webkit引擎的浏览器
-o- Opera浏览器(早期)
-ms- IE
2、.IE浏览器div最小高度和宽度的问题
加宽高,并且宽高加auto
3、.不同浏览器的标签默认的margin和padding不同
解决办法:可以通过设置全局样式来解决这个问题,这样所有的样式都会重置,初始值都会相同了
4、.图片默认有间距
几个img标签放在一起的时候,有些浏览器会有默认的间距,通配符清除间距也不起作用。
可以通过使用float属性为img布局(所有图片左浮)。
二、js兼容 (多记几个)
1、. 事件绑定
IE: dom.attachEvent();
标准浏览器: dom.addEventListener(‘click',function(event){},false);
var x = document.getElementById("myBtn");
if (x.addEventListener) { //所有主流浏览器,ie9+
x.addEventListener("click", myFunction);
} else if (x.attachEvent) { // IE 8 及更早 IE 版本
x.attachEvent("onclick", myFunction);
}
2、. event.srcElement(事件源对象)问题
IE: event对象有srcElement属性,但是没有target属性;
Firefox: event对象有target属性,但是没有srcElement属性。
解决办法:srcObj = event.srcElement?event.srcElement:event.target;
3、.阻止事件冒泡传播
//js阻止事件传播,这里使用click事件为例
document.onclick=function(e){
var e=e||window.event;
if (e.stopPropagation) {
e.stopPropagation();//W3C标准
}else{
e.cancelBubble=true;//IE.... true: 不被上层元素的事件控制
}
}
4、.阻止事件默认行为
//js阻止默认事件 一般阻止a链接href,form表单submit提交
document.onclick=function(e){
var e=e||window.event;
if (e.preventDefault) {
e.preventDefault();//W3C标准
}else{
e.returnValue='false';//IE.. false: 不会进行判断就直接执行下去
}
}
day03 4.15*
JS相关
JavaScript分三个部分:
1. ECMAScript标准---基本语法
2. DOM--->Document Object Model 文档对象模型,操作页面元素的
3. BOM--->Browser Object Model 浏览器对象模型,操作浏览器的
浏览器中有个顶级对象:window----皇上
页面中顶级对象:document-----总管太监
页面中所有的内容都是属于浏览器的,页面中的内容也都是window的,因为页面中的所有内容都是window的,window是可以省略的.
变量是window的
一、 原型和原型链 *
1. prototype
每个函数都有一个prototype属性,被称为显示原型
2._ _proto_ _
每个实例对象都会有_ _proto_ _属性,其被称为隐式原型
每一个实例对象的隐式原型_ _proto_ 属性指向自身构造函数的显式原型prototype
3. constructor
每个prototype原型都有一个constructor属性,指向它关联的构造函数。
4. 原型链
获取对象属性时,如果对象本身没有这个属性,那就会去他的原型_ _proto_ _上去找,如果还查不到,就去找原型的原型,一直找到最顶层(Object.prototype)为止。Object.prototype对象也有_ _proto_ _属性值为null。
二、 作用域 *
1、作用域
作用域就是一个变量和函数可以使用的范围,主要分为全局作用域和局部(函数)作用域
全局作用域就是Js中最外层的作用域。
2、全局变量、局部变量:
1).全局变量:
在全局范围内声明的变量,如var a=1;
只有赋值没有声明的值,如a=2; (注:如果a=2在函数环境中,也是全局变量)
2)局部变量:
写入函数中的变量,叫做局部变量。
3)作用:
程序的安全。
内存的释放。
3、自由变量:
当前作用域外的变量都是自由变量,一个变量在当前作用域没有定义,但是被使用了,就会向上级作用域,一层一层依次查找,直至找到为止,找到这个变量后就会停止,不会继续查找这个变量,如果全局作用域都没有找到这个变量就会报错。这个自由变量查找的过程就是作用域链。
4、变量提升:
提升声明,不提升赋值
三、 闭包 *
1、闭包
闭包就是能够读取其他函数内部变量的函数。
闭包是将函数内部和函数外部连接起来的桥梁。
vue中的data就是一种闭包的形式。闭包作为回调函数,可以实现函数的复用
2、优点缺点
优点:1.长期驻留内存,可以缓存数据
2.可以重复使用变量,不会造成变量污染
缺点:1.占内存、
2.对捕获的变量是引用,不是复制
3.父函数每调用一次会产生不同的闭包.
四、 This的指向*
【在js中this不是固定不变的,它会随着执行环境的改变而改变。this取什么值,是在执行时确认的,定义时无法确认。】
this的调用大概分为五种场景:
1.浏览器里,在全局范围内的this 指向window对象;
2.在函数中,this永远指向最后调用他的那个对象;
3.构造函数中,this指向new出来的那个新的对象;
4.Call、apply、bind中的this被强绑定在指定的那个对象上;
5.箭头函数中this比较特殊,箭头函数this为父作用域的this,不是调用时的this.
前四种都是调用时确定,也就是动态的,而箭头函数的this指向是静态的,声明的时候就确定了下来;
call:和apply:区别==========
Call和 apply 都可以改变this,会让函数立即执行
区别是传参的时候call 传的是字符串,apply传的是数组
Bind 改变this,不会改变数据。不会让函数立刻执行,调用的地方加一个括号
五、垃圾回收和内存机制 **
垃圾回收
1.垃圾收集器会定期找出那些不在继续使用的变量,然后释放其内存。
2.垃圾回收器会按照固定的时间间隔周期性的执行。
3.垃圾回收策略:标记清除和引用计数。最常用的是标记清除。
标记清除:
定义和用法:当变量进入环境时,将变量标记"进入环境",当变量离开环境时,标记为:"离开环境"。某一个时刻,垃圾回收器会过滤掉环境中的变量,以及被环境变量引用的变量,剩下的就是被视为准备回收的变量。
引用计数:
定义和用法:引用计数是跟踪记录每个值被引用的次数。
基本原理:就是变量的引用次数,被引用一次则加1,当这个引用计数为0时,被视为准备回收的对象。
【到目前为止,IE、Firefox、Opera、Chrome、Safari的js实现使用的都是标记清除的垃圾回收策略或类似的策略,只不过垃圾收集的时间间隔互不相同。 了解】
内存泄漏
1.循环引用
一个很简单的例子:一个DOM对象被一个Javascript对象引用,与此同时又引用同一个或其它的Javascript对象,这个DOM对象可能会引发内存泄露。
这个DOM对象的引用将不会在脚本停止的时候被垃圾回收器回收。要想破坏循环引用,引用DOM元素的对象或DOM对象的引用需要被赋值为null。
2.闭包
在闭包中引入闭包外部的变量时,当闭包结束时此对象无法被垃圾回收(GC)。
3.DOM泄露
当原有的DOM被移除时,子结点引用没有被移除则无法回收
4.Times计时器泄露
六、宏任务和微任务 **
1.宏任务是浏览器发起的;
2.微任务是js引擎发起的;
3.除了promise和async 是微任务外
4.其他的任务都是宏任务,比如说 ajax,计时器,dom节点操作,引入script标签
【至于谁先谁后执行的问题,同步任务先执行,异步任务后执行,
js是一个单线程的语言,同步任务在主线程上,异步任务放在任务队列里,
当主线程上的同步任务执行完成后,任务队列里的异步任务就会被推进主线程里】
七、数据类型 *
1.数据类型:
1).基本数据类型又叫简单数据类型: number string Boolean null undefined symble
简单数据类型存在栈里
2).复杂数据类型又叫引用数据类型
object array data function regexp
复杂数据类型存在堆里 但是在栈里有一个地址指向真正的堆内存
2.Typeof运算符:
typeof 能有效检测基本类型,检测引用类型都返回object,其中null属于特殊的引用类型返回 object,function属于特殊引用类型类型不用于存储数据,typeof检测返回function.
3.==和===
===三等表示全等,判断左右两边对象或值是否类型相同且值相等。
==二等表示值相等。判断操作符两边对象或值是否相等类型可以不同,
4.if语句和逻辑运算
所有基本类型中Boolean值是false的只有6个,分别是 : 0 NaN ' ' null undefined false
引用类型Boolean值全是true.
if条件是单个值时,如果是truly值,条件成立, 如果是falsely值,条件不成立
[了解扩展]. 和=
类型不同时,使用Number()转换成Number类型在进行判断。
[例外规则,null==undefined,null/undefined进行运算时不进行隐式类型转换。通常把值转为Boolean值,进行条件判断。Boolean(null)=Boolean(undefined)>false=false 结果为true
let%20obj2%20%3D%20JSON.parse(JSON.stringify(obj))%3B%0A%20%20%20%202.%E9%80%92%E5%BD%92%20%E8%87%AA%E8%BA%AB%E8%B0%83%E7%94%A8%E8%87%AA%E8%BA%AB%0A%20%20%20%20%E5%BD%93%E5%8E%BB%E5%A4%8D%E5%88%B6%E4%B8%80%E4%B8%AA%E5%A4%8D%E6%9D%82%E7%9A%84%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%BF%99%E4%B8%AA%E5%AF%B9%E8%B1%A1%E7%9A%84key%E6%98%AF%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%B1%BB%E5%9E%8B%EF%BC%8C%E5%B0%B1%E7%9B%B4%E6%8E%A5%E5%A4%8D%E5%88%B6%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%BF%98%E6%98%AF%E4%B8%80%E4%B8%AA%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B%E5%B0%B1%E8%B0%83%E7%94%A8%E8%87%AA%E8%BA%AB%E5%86%8D%E6%AC%A1%E8%BF%9B%E8%A1%8C%E5%BE%AA%E7%8E%AF%E5%A4%8D%E5%88%B6%0A%60%60%60%0A%0A%0A%0A%23%23%23%20%E4%B9%9D%E3%80%81%E7%B1%BB%E5%9E%8B%E5%88%A4%E6%96%AD%20*%0A%0A%60%60%60%0A1.%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%88%A4%E6%96%AD%E5%A4%A7%E6%A6%82%E6%9C%89%E5%9B%9B%E7%A7%8D%EF%BC%9A%20%0A%20%20%20%20%20%20%20typeof%E3%80%81instanceof%E3%80%81constructor%E3%80%81Object.prototype.toString.call()%0A%60%60%60%0A#card=math&code=%23%23%23%20%E5%85%AB%E3%80%81%E6%89%8B%E5%86%99%E6%B7%B1%E6%8B%B7%E8%B4%9D%EF%BC%88%E6%B7%B1%E6%8B%B7%E8%B4%9D%E5%92%8C%E6%B5%85%E6%8B%B7%E8%B4%9D%E7%9A%84%E5%8C%BA%E5%88%AB%EF%BC%89%20%2A%2A%2A%0A%0A%60%60%60%0A1.%20%E6%B7%B1%E5%A4%8D%E5%88%B6%E5%92%8C%E6%B5%85%E5%A4%8D%E5%88%B6%0A%20%20%20%E2%80%8B%E6%B7%B1%E5%A4%8D%E5%88%B6%E5%A4%8D%E5%88%B6%E7%9A%84%E6%98%AF%E7%9C%9F%E6%AD%A3%E7%9A%84%E5%80%BC%20%E7%AE%80%E5%8D%95%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E9%83%BD%E6%98%AF%E6%B7%B1%E5%A4%8D%E5%88%B6%0A%20%20%20%E2%80%8B%E6%B5%85%E5%A4%8D%E5%88%B6%E5%A4%8D%E5%88%B6%E7%9A%84%E6%98%AF%E5%9C%B0%E5%9D%80%20%E5%A4%8D%E6%9D%82%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E6%99%AE%E9%80%9A%E7%9A%84%E5%A4%8D%E5%88%B6%E9%83%BD%E6%98%AF%E6%B5%85%E5%A4%8D%E5%88%B6%0A2.%E6%95%B0%E7%BB%84%E6%98%AF%E4%B8%80%E4%B8%AA%E5%BC%95%E7%94%A8%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%20%E6%99%AE%E9%80%9A%E7%9A%84%E5%A4%8D%E5%88%B6%E5%8F%AA%E8%83%BD%E5%AE%9E%E7%8E%B0%E6%B5%85%E6%8B%B7%E8%B4%9D%0A3.%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E6%95%B0%E7%BB%84%E7%9A%84%E6%B7%B1%E6%8B%B7%E8%B4%9D%0A%20%20%20%E2%80%8B%2A%E4%BD%BF%E7%94%A8concat%E5%90%88%E5%B9%B6%E6%95%B0%E7%BB%84%EF%BC%8C%E4%BC%9A%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E6%95%B0%E7%BB%84%0A%20%20%20%E2%80%8B%2A%E5%AF%B9%E8%B1%A1%E6%98%AF%E4%B8%80%E4%B8%AA%E5%BC%95%E7%94%A8%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%20%E6%99%AE%E9%80%9A%E7%9A%84%E5%A4%8D%E5%88%B6%E6%98%AF%E4%B8%80%E4%B8%AA%E6%B5%85%E6%8B%B7%E8%B4%9D%0A%20%20%20%E2%80%8B%2A%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%B7%B1%E6%8B%B7%E8%B4%9D%E6%96%B9%E6%B3%95%0A%20%20%20%201.%28%E8%BD%AC%E6%8D%A2%29let%20obj2%20%3D%20JSON.parse%28JSON.stringify%28obj%29%29%3B%0A%20%20%20%202.%E9%80%92%E5%BD%92%20%E8%87%AA%E8%BA%AB%E8%B0%83%E7%94%A8%E8%87%AA%E8%BA%AB%0A%20%20%20%20%E5%BD%93%E5%8E%BB%E5%A4%8D%E5%88%B6%E4%B8%80%E4%B8%AA%E5%A4%8D%E6%9D%82%E7%9A%84%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%BF%99%E4%B8%AA%E5%AF%B9%E8%B1%A1%E7%9A%84key%E6%98%AF%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%B1%BB%E5%9E%8B%EF%BC%8C%E5%B0%B1%E7%9B%B4%E6%8E%A5%E5%A4%8D%E5%88%B6%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%BF%98%E6%98%AF%E4%B8%80%E4%B8%AA%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B%E5%B0%B1%E8%B0%83%E7%94%A8%E8%87%AA%E8%BA%AB%E5%86%8D%E6%AC%A1%E8%BF%9B%E8%A1%8C%E5%BE%AA%E7%8E%AF%E5%A4%8D%E5%88%B6%0A%60%60%60%0A%0A%0A%0A%23%23%23%20%E4%B9%9D%E3%80%81%E7%B1%BB%E5%9E%8B%E5%88%A4%E6%96%AD%20%2A%2A%2A%0A%0A%60%60%60%0A1.%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%88%A4%E6%96%AD%E5%A4%A7%E6%A6%82%E6%9C%89%E5%9B%9B%E7%A7%8D%EF%BC%9A%20%0A%20%20%20%20%20%20%20typeof%E3%80%81instanceof%E3%80%81constructor%E3%80%81Object.prototype.toString.call%28%29%0A%60%60%60%0A&id=vFXqy)
【1.Type: 了解!!
基本数据类型中:Number,String,Boolean,undefined 以及引用数据类型中Function ,可以使用typeof检测数据类型,分别返回对应的数据类型小写字符。
另:用typeof检测构造函数创建的Number,String,Boolean都返回object
基本数据类型中:null 引用数据类型中的:Array,Object,Date,RegExp。不可以用typeof检测。都会返回小写的object
2.instanceof
除了使用typeof来判断,还可以使用instanceof。instanceof运算符需要指定一个构造函数,或者说指定一个特定的类型,它用来判断这个构造函数的原型是否在给定对象的原型链上。
3.constructor
constructor是prototype对象上的属性,指向构造函数。根据实例对象寻找属性的顺序,若实例对象上没有实例属性或方法时,就去原型链上寻找,因此,实例对象也是能使用constructor属性的
4.使用Object.prototype.toString.call()检测对象类型
可以通过toString() 来获取每个对象的类型。为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用,传递要检查的对象作为第一个参数,称为thisArg。】
十、数组方法 *
1.push() 添加一个或多个参数到数组的尾部,原来数组会改变,返回的是添加后的数组的长度
2.pop() 从数组尾部删除一个元素,原数组会改变,返回的是被删除的元素
3.unshift() 添加一个或多个参数到数组的头部,原来的数组会改变,是添加后的数组的长度
4.shift() 从数组头部删除一个元素,原数组会改变,返回数组中被删除的元素
5.slice() 从数组中截取,不传参返回原数组。传一个参数,从头部开始删除,到数组结束,原数组不变;传两个参数,开始截取的索引和结束的索引,原数组不变。最接受两个参数。
6.splice()截取类 没有参数,返回空数组,原数组不变;一个参数,从该参数表示的索引开始截取,直至数组结束,返回截取的 数组,原数组改变;两个参数,第一个是截取的索引位,第二个表示截取的长度,返回截取的 数组,原数组改变;三个及以后的参数表示要从截取位插入的值。
7.reverse() 数组翻转
8.sort() 数组排序
9.join() 数组拼接
10.isArray() 判断是否是数组
11.toString() 数组转字符串
十一、数组去重 *
1.使用ES6中的set是最简单的去重方法
let arr = [12,43,23,43,68,12];
let item = new Set(arr);
console.log(item);//结果输出的是一个对象
let arr = [12,43,23,43,68,12];
let item = Array.from(new Set(arr));
//使用Array.from转成数组
2.利用Map数据结构去重
创建一个空Map数据结构,遍历需要去重的数组,把数组的每一个元素作为key存到Map中。由于Map中不会出现相同的key值,所以最终得到的就是去重后的结果。
3.递归去重
4.forEach+indexOf
定义一个空数组,通过forEach循环,indexOf判断值是否是-1,如果是push到新的数组中
十二、数组排序 (常用)*
1.冒泡排序法
将数组中的相邻两个元素进行比较,将比较大(较小)的数通过两两比较移动到数组末尾(开始),
执行一遍内层循环,确定一个最大(最小)的数,外层循环从数组末尾(开始)遍历到开始(末尾)
2. 插入排序法(插队排序)
将要排序的数组分成两部分,每次从后面的部分取出索引最小的元素插入到前一部分的适当位置
从第一个元素开始,该元素可以认为已经被排序;
取出下一个元素,在已经排序的元素序列中从后向前扫描;
如果该元素(已排序)大于新元素,将该元素移到下一位置;
重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
将新元素插入到该位置后;
重复步骤2~5。
3.快速排序法
实现思路是,将一个数组的排序问题看成是两个小数组的排序问题,以一个数为基准(中间的数),比基准小的放到左边,比基准大的放到右边,而每个小的数组又可以继续看成更小的两个数组,一直递归下去,直到数组长度大小最大为2。
4.选择排序法:将要排序的数组分成两部分,一部分是从大到小已经排好序的,一部分是无序的,从无序的部分取出最小的放到已经排序的最后面。
十三、数组扁平化
数组扁平化就是将一个多维数组转换为一个一维数组
实现基本方式:
1、对数组的每一项进行遍历。
2、判断该项是否是数组。
3、如果该项不是数组则将其直接放进新数组。
4、是数组则回到1,继续迭代。
5、当数组遍历完成,返回这个新数组。
十四 for…in和for…of的区别*
1.从遍历数组角度来说,for···in遍历出来的是key(即下标),for···of遍历出来的是value(即数组的值);
2.从遍历字符串的角度来说,同数组一样。
3.从遍历对象的角度来说,for···in会遍历出来的为对象的key,但for···of会直接报错。
4.如果要使用for…of遍历普通对象,需要配合Object.keys()一起使用。
十五、null和undefined区别
- 在 if 语句中 null 和 undefined 都会转为false两者用相等运算符比较也是相等
1.null表示没有对象,可能将来要赋值一个对象,即该处不应该有值
1) 作为函数的参数,表示该函数的参数不是对象
2) 作为对象原型链的终点
2.undefined表示缺少值,即此处应该有值,但没有定义
1)定义了形参,没有传实参,显示undefined
2)对象属性名不存在时,显示undefined
3)函数没有写返回值,即没有写return,拿到的是undefined
4)写了return,但没有赋值,拿到的是undefined
day 04 4.16**
1..this, call, apply, bind (涉及)*
1.浏览器里,在全局范围内的this 指向window对象;
2.在函数中,this永远指向最后调用他的那个对象;
3.构造函数中,this指向new出来的那个新的对象;
4.Call、apply、bind中的this被强绑定在指定的那个对象上;
5.箭头函数中this比较特殊,箭头函数this为父作用域的this,不是调用时的this.要知道前四种方式,都 是调用时确定,也就是动态的,而箭头函数的this指向是静态的,声明的时候就确定了下来;
6.apply、call、bind都是js给函数内置的一些API,调用他们可以为函数指定this的执行,同时也可以传参。
2、继承 *
1.原型链继承
核心:将父类的实例作为子类的原型
特点:子类的实例也是父类的实例
可以方便的继承父类型的原型中的方法,但是属性的继承无意义
缺点:只执行一次,无法给属性传值 属性的继承无意义
2.借用构造函数继承
核心:在子类的内部调用父类,通过call改变父类中this的指向
等于是复制父类的实例属性给子类
特点:创建子类实例时,可以向父类传递参数,可以实现多继承
可以方便的继承父类型的属性,但是无法继承原型中的方法
缺点:实例并不是父类的实例,只是子类的实例,无法继承原型中的方法。
无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
3.组合继承(组合原型链继承和借用构造函数继承)
核心:结合了两种模式的优点,传参和复用
特点:可以继承父类原型上的属性,可以传参,可复用。每个新实例引入的构造函数属性是私有的。
缺点:调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那个父类构造函数。
4.原型式继承
核心:用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象。object.create()就是这个原理。
核心:用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象。object.create()就是这个原理。
特点: 类似于复制一个对象,用函数来包装。
缺点:所有实例都会继承原型上的属性。无法实现复用。(新实例属性都是后面添加的)
【可展开了解·!!!】ES5继承和ES6继承的区别:
es5继承首先是在子类中创建自己的this指向,最后将方法添加到this中
Child.prototype=new Parent() || Parent.apply(this) || Parent.call(this)
es6继承是使用关键字先创建父类的实例对象this,最后在子类class中修改this
3.、设计模式
一、单例模式
1. 定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点
2. 核心:确保只有一个实例,并提供全局访问
3. 实现:
在vue脚手架项目开发中,我们需要对axios进行请求拦截,响应拦截,多次调用封装好的axios实例也仅设置一次,封装后的axios就是要一个单例
二、观察者、订阅者模式
vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
4.dom操作 (概念展开查看)
概念:
DOM是网页中用来表示文档中对象的标准模型,他是由节点和对象组成的结构集合。javascript 原生方法对dom节点的操作包括:访问(查找)、创建、添加、删除、替换、插入、复制、移动等。
一、dome元素获取
1.1.document.getElementById(id的值) 通过id来获取元素的对象,返回值是一个对象
2.document.getElementsByName(name) 通过name属性来获取对象的,返回值是一个数组,
与getElementById()方法类似,但他是查询的name元素,而不是id属性
3.document.getElementsByTagName() 通过标签来获取元素的对象, 返回值是一个数组
4.document.getElementsByClassName() 通过class类名来获取的对象,返回值是一个数组
5.document.querySelector() css选择器,返回与该模式匹配的第一个元素,结果为一个元素;如果没找到匹配的元素,则返回null
6.document.querySelectorAll() css选择器,返回与该模式匹配的所有元素,
结果为一个类数组二、dom创建
二、dom操作
1. 创建:新的标签(元素节点) = document.createElement("标签名")
2. 删除:父节点.removeChild(子节点);
3. 插入:insertBefore(新插入的节点,参照物节点) 往某个节点的前面插入一个新的节点
4. 追加:appendChild(新的节点的名) 当前对象追加一个子节点
5、js操作BOM
浏览器对象模型(BOM :Browser Object Model)是JavaScript的组成之一,它提供了独立于内容与浏览器窗口进行交互的对象,使用浏览器对象模型可以实现与HTML的交互。它的作用是将相关的元素组织包装起来,提供给程序设计人员使用,从而降低开发人员的劳动量,提高设计Web页面的能力
BOM是一个分层结构:
浏览器中有个顶级对象:window----皇上
页面中顶级对象:document-----总管太监
页面中所有的内容都是属于浏览器的,页面中的内容也都是window的,因为页面中的所有内容都是window 的,window是可以省略的.
变量是window的
6、事件
6-1、事件绑定、事件流、自定义事件
1、DOM事件三种级别:
#DOM0级事件
DOM0 级时间分两种,一是直接在标签内直接添加执行语句,二是定义执行函数。
#DOM2 级事件
第一个参数:事件名称
第二个参数:执行函数
第三个参数:指定冒泡还是捕获,默认是false,冒泡。
#DOM3 级事件
同DOM2级一样,只不过添加了更多的事件类型,鼠标事件、键盘事件
2、DOM事件类型分两种:事件捕获、事件冒泡。
事件捕获就是由外往内,从事件发生的顶点开始,逐级往下查找,一直到目标元素。
事件冒泡就是由内往外,从具体的目标节点元素触发,逐级向上传递,直到根节点
3、DOM事件的事件流(事件传播)
DOM完整的事件流包括三个阶段:
事件捕获阶段、目标阶段、事件冒泡阶段。
事件通过捕获到达目标元素,这个时候就是目标阶段。从目标节点元素将事件上传到根节点的过程就是第三个阶段,冒泡阶段。
4.事件捕获的具体流程
当事件发生在 DOM元素上时,该事件并不完全发生在那个元素上。在捕获阶段,事件从window开始,之后是document对象,一直到触发事件的元素。
5.事件冒泡的具体过程
当事件发生在DOM元素上时,该事件并不完全发生在那个元素上。在冒泡阶段,事件冒泡,或者事件发生在它的父代,祖父母,直到到达window为止。
6.我们也可以通过 new Event()自定义事件
1、创建事件 2、注册事件 3、触发事件
6-2、事件委托
事件委托原理**:事件冒泡机制
优点:
1.大量减少内存占用,减少事件注册。
2.新增元素实现动态绑定事件
实现方式:
一、可用addEventListener();** //所有主流浏览器,除了IE8及更早IE版本。
二、attachEvent()** //IE8及IE更早版本
%3B%20%20%2F%2F%E6%89%80%E6%9C%89%E4%B8%BB%E6%B5%81%E6%B5%8F%E8%A7%88%E5%99%A8%EF%BC%8C%E9%99%A4%E4%BA%86IE8%E5%8F%8A%E6%9B%B4%E6%97%A9IE%E7%89%88%E6%9C%AC%E3%80%82%0A%20%201.%E8%AF%AD%E6%B3%95%EF%BC%9Aelement.addEventListener(event%2C%20function%2C%20useCapture)%EF%BC%9B%0A%20%20%20%20%20event%3A%E5%BF%85%E9%A1%BB%E3%80%82%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%8C%E6%8C%87%E5%AE%9A%E4%BA%8B%E4%BB%B6%E5%90%8D%E3%80%82%20%E4%B8%8D%E5%8A%A0’on’%EF%BC%8C%E5%A6%82click%0A%20%20%20%20%20function%3A%E5%BF%85%E9%A1%BB%E3%80%82%E6%8C%87%E5%AE%9A%E8%A6%81%E4%BA%8B%E4%BB%B6%E8%A7%A6%E5%8F%91%E6%97%B6%E6%89%A7%E8%A1%8C%E7%9A%84%E5%87%BD%E6%95%B0%E3%80%82%0A%20%20%20%20%20useCapture%EF%BC%9A%E5%8F%AF%E9%80%89%E3%80%82%E5%B8%83%E5%B0%94%E5%80%BC%EF%BC%8C%E6%8C%87%E5%AE%9A%E4%BA%8B%E4%BB%B6%E6%98%AF%E5%90%A6%E5%9C%A8%E6%8D%95%E8%8E%B7%E6%88%96%E5%86%92%E6%B3%A1%E9%98%B6%E6%AE%B5%E6%89%A7%E8%A1%8C(true-%E4%BA%8B%E4%BB%B6%E5%8F%A5%E6%9F%84%E5%9C%A8%E6%8D%95%E8%8E%B7%E9%98%B6%E6%AE%B5%E6%89%A7%E8%A1%8C%EF%BC%9Bfalse-%E9%BB%98%E8%AE%A4%E3%80%82%E4%BA%8B%E4%BB%B6%E5%8F%A5%E6%9F%84%E5%9C%A8%E5%86%92%E6%B3%A1%E9%98%B6%E6%AE%B5%E6%89%A7%E8%A1%8C)%E3%80%82%0A%20%20%20%20%20%0A%20%202.%E7%A7%BB%E9%99%A4%E4%BA%8B%E4%BB%B6%E7%9B%91%E5%90%AC%EF%BC%9A%E7%A7%BB%E9%99%A4%E6%97%B6%E4%BC%A0%E5%85%A5%E7%9A%84%E5%8F%82%E6%95%B0%E4%B8%8E%E6%B7%BB%E5%8A%A0%E5%A4%84%E7%90%86%E7%A8%8B%E5%BA%8F%E6%97%B6%E4%BD%BF%E7%94%A8%E7%9A%84%E5%8F%82%E6%95%B0%E7%9B%B8%E5%90%8C%E3%80%82%E6%84%8F%E5%91%B3%E7%9D%80%E9%80%9A%E8%BF%87addEventListener()%E6%B7%BB%E5%8A%A0%E7%9A%84%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0%E6%97%A0%E6%B3%95%E7%A7%BB%E9%99%A4%E3%80%82%0A%20%203.%E5%8A%9F%E8%83%BD%EF%BC%9A%E5%8F%AF%E5%A4%9A%E6%AC%A1%E7%BB%91%E5%AE%9A%E5%90%8C%E4%B8%80%E4%B8%AA%E4%BA%8B%E4%BB%B6%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%B8%8D%E4%BC%9A%E8%A6%86%E7%9B%96%E4%B8%8A%E4%B8%80%E4%B8%AA%E4%BA%8B%E4%BB%B6%E3%80%82%0A%0A%E4%BA%8C%E3%80%81attachEvent()%20%20%20%2F%2FIE8%E5%8F%8AIE%E6%9B%B4%E6%97%A9%E7%89%88%E6%9C%AC%0A%20%20%201.%E7%94%A8%E6%B3%95%EF%BC%9Aelement.attachEvent(event%2Cfunction)%EF%BC%9B%0A%20%20%20%20%EF%BC%881%EF%BC%89event%E4%BA%8B%E4%BB%B6%E5%8A%A0’on’%EF%BC%8ConClick%0A%20%20%20%20%EF%BC%882%EF%BC%89%E6%B2%A1%E6%9C%89%E7%AC%AC%E4%B8%89%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%8C%E5%9B%A0%E4%B8%BAIE%E5%8F%AA%E6%9C%89%E5%86%92%E6%B3%A1%EF%BC%8C%E6%B2%A1%E6%9C%89%E5%8F%8D%E5%90%91%E5%86%92%E6%B3%A1%E3%80%82%0A%20%20%20%20%EF%BC%883%EF%BC%89%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F%E6%8C%89%E7%85%A7%E7%BB%91%E5%AE%9A%E7%9A%84%E5%8F%8D%E5%BA%8F%EF%BC%88%E5%85%88%E6%89%A7%E8%A1%8C%E5%90%8E%E7%BB%91%E5%AE%9A%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%89%E3%80%82%0A%20%20%202.%E7%A7%BB%E9%99%A4%E4%BA%8B%E4%BB%B6%E7%9B%91%E5%90%AC%EF%BC%9Aelement.detachEvent(event%2Cfunction)%0A#card=math&code=%E4%B8%80%E3%80%81%E5%8F%AF%E7%94%A8addEventListener%28%29%3B%2A%2A%20%20%2F%2F%E6%89%80%E6%9C%89%E4%B8%BB%E6%B5%81%E6%B5%8F%E8%A7%88%E5%99%A8%EF%BC%8C%E9%99%A4%E4%BA%86IE8%E5%8F%8A%E6%9B%B4%E6%97%A9IE%E7%89%88%E6%9C%AC%E3%80%82%0A%20%201.%E8%AF%AD%E6%B3%95%EF%BC%9Aelement.addEventListener%28event%2C%20function%2C%20useCapture%29%EF%BC%9B%0A%20%20%20%20%20event%3A%E5%BF%85%E9%A1%BB%E3%80%82%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%8C%E6%8C%87%E5%AE%9A%E4%BA%8B%E4%BB%B6%E5%90%8D%E3%80%82%20%E4%B8%8D%E5%8A%A0%27on%27%EF%BC%8C%E5%A6%82click%0A%20%20%20%20%20function%3A%E5%BF%85%E9%A1%BB%E3%80%82%E6%8C%87%E5%AE%9A%E8%A6%81%E4%BA%8B%E4%BB%B6%E8%A7%A6%E5%8F%91%E6%97%B6%E6%89%A7%E8%A1%8C%E7%9A%84%E5%87%BD%E6%95%B0%E3%80%82%0A%20%20%20%20%20useCapture%EF%BC%9A%E5%8F%AF%E9%80%89%E3%80%82%E5%B8%83%E5%B0%94%E5%80%BC%EF%BC%8C%E6%8C%87%E5%AE%9A%E4%BA%8B%E4%BB%B6%E6%98%AF%E5%90%A6%E5%9C%A8%E6%8D%95%E8%8E%B7%E6%88%96%E5%86%92%E6%B3%A1%E9%98%B6%E6%AE%B5%E6%89%A7%E8%A1%8C%28true-%E4%BA%8B%E4%BB%B6%E5%8F%A5%E6%9F%84%E5%9C%A8%E6%8D%95%E8%8E%B7%E9%98%B6%E6%AE%B5%E6%89%A7%E8%A1%8C%EF%BC%9Bfalse-%E9%BB%98%E8%AE%A4%E3%80%82%E4%BA%8B%E4%BB%B6%E5%8F%A5%E6%9F%84%E5%9C%A8%E5%86%92%E6%B3%A1%E9%98%B6%E6%AE%B5%E6%89%A7%E8%A1%8C%29%E3%80%82%0A%20%20%20%20%20%0A%20%202.%E7%A7%BB%E9%99%A4%E4%BA%8B%E4%BB%B6%E7%9B%91%E5%90%AC%EF%BC%9A%E7%A7%BB%E9%99%A4%E6%97%B6%E4%BC%A0%E5%85%A5%E7%9A%84%E5%8F%82%E6%95%B0%E4%B8%8E%E6%B7%BB%E5%8A%A0%E5%A4%84%E7%90%86%E7%A8%8B%E5%BA%8F%E6%97%B6%E4%BD%BF%E7%94%A8%E7%9A%84%E5%8F%82%E6%95%B0%E7%9B%B8%E5%90%8C%E3%80%82%E6%84%8F%E5%91%B3%E7%9D%80%E9%80%9A%E8%BF%87addEventListener%28%29%E6%B7%BB%E5%8A%A0%E7%9A%84%2A%2A%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0%2A%2A%E6%97%A0%E6%B3%95%E7%A7%BB%E9%99%A4%E3%80%82%0A%20%203.%E5%8A%9F%E8%83%BD%EF%BC%9A%E5%8F%AF%E5%A4%9A%E6%AC%A1%E7%BB%91%E5%AE%9A%E5%90%8C%E4%B8%80%E4%B8%AA%E4%BA%8B%E4%BB%B6%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%B8%8D%E4%BC%9A%E8%A6%86%E7%9B%96%E4%B8%8A%E4%B8%80%E4%B8%AA%E4%BA%8B%E4%BB%B6%E3%80%82%0A%0A%E4%BA%8C%E3%80%81attachEvent%28%29%2A%2A%20%20%20%2F%2FIE8%E5%8F%8AIE%E6%9B%B4%E6%97%A9%E7%89%88%E6%9C%AC%0A%20%20%201.%E7%94%A8%E6%B3%95%EF%BC%9Aelement.attachEvent%28event%2Cfunction%29%EF%BC%9B%0A%20%20%20%20%EF%BC%881%EF%BC%89event%E4%BA%8B%E4%BB%B6%E5%8A%A0%27on%27%EF%BC%8ConClick%0A%20%20%20%20%EF%BC%882%EF%BC%89%E6%B2%A1%E6%9C%89%E7%AC%AC%E4%B8%89%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%8C%E5%9B%A0%E4%B8%BAIE%E5%8F%AA%E6%9C%89%E5%86%92%E6%B3%A1%EF%BC%8C%E6%B2%A1%E6%9C%89%E5%8F%8D%E5%90%91%E5%86%92%E6%B3%A1%E3%80%82%0A%20%20%20%20%EF%BC%883%EF%BC%89%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F%E6%8C%89%E7%85%A7%E7%BB%91%E5%AE%9A%E7%9A%84%2A%2A%E5%8F%8D%E5%BA%8F%2A%2A%EF%BC%88%E5%85%88%E6%89%A7%E8%A1%8C%E5%90%8E%E7%BB%91%E5%AE%9A%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%89%E3%80%82%0A%20%20%202.%E7%A7%BB%E9%99%A4%E4%BA%8B%E4%BB%B6%E7%9B%91%E5%90%AC%EF%BC%9Aelement.detachEvent%28event%2Cfunction%29%0A&id=aLijv)
6-3、封装一个通用的事件绑定函数
需要点击每个a,来。弹出他们的内容 (展开可详细查看)
// 封装通用的事件绑定函数
function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
//获取父元素
const fu = document.getElementById(‘div3’)
bindEvent(fu, ‘click’, function (event) {
// console.log(event.target) // 获取触发的元素
let target=event.target
event.preventDefault() // 阻止默认行为
//过滤符合条件的子元素,主要是过滤掉 加载更多
if(target.nodeName.toLowerCase()===”A”){
alert(target.innerHTML;
}
7、Ajax
7-1原生Ajax的创建过程
1.创建xhr 核心对象
var xhr=new XMLHttpRequest();
2.调用open 准备发送
参数一:请求方式
参数二: 请求地址
参数三:true异步,false 同步
例:xhr.open('post','http://www.baidu.com/api/search',true)
3.如果是post请求,必须设置请求头。
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
4.调用send 发送请求 (如果不需要参数,就写null)
xhr.send('user=tom&age=10&sex=女')
5.监听异步回调 onreadystatechange
判断readyState 为4 表示请求完成
判断status 状态码 为 200 表示接口请求成功
备注:如果是post请求,想要传json格式数据
responeseText 为相应数据。字符串类型。
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200){
console.log(xhr.responseText);
var res=JSON.parse(xhr.responseText);
console.log(res);
if(res.code==1){
modal.modal('hide');
location.reload();
}
}
}
备注:如果是post请求,想要传json格式数据。
设置请求头
1.xhr.setRequestHeader(‘Content-Type’, ‘application/json’)
open发送数据
2.xhr.open({_id:xxx,user:xxxx,age:xxxx})
7-2、JSONP原理:
通过script标签中的src属性不受同源策略的影响实现跨域。
JSONP原理:
ajax 请求受同源策略影响,不允许进行请求,我们利用 script 标签的 src 属性不受同源策略的约束,利用这个特性jsonp需要以下步骤:
1.动态创建<script></script>(document.createElement('script'))
2.设置src 属性,(src中要包含参数callback=fn)进行跨域请求
3.将 <script></script>添加到页面中执行 (body.appendChild('script'))
4.页面要提前定义好callback。
5.后端会返回回调函数执行并包裹参数callback(data)
备注:
服务端不再返回JSON格式的数据,而是返回回调函数包裹数据(fn({name:'tom',age:18}),在src中进行了调用,这样实现了跨域。
8、存储
在HTML5中,新加入了一个localStorage/sessionStorage特性,这个特性主要是用来作为本地存储来使用的,解决了cookie存储空间不足的问题(cookie中每条cookie的存储空间为4k),localStorage中一般浏览器支持的是5M大小。
本地存储分为cookie、localStorage、sessionStorage,
(1)sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
(2)数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。
Cookie
Cookie设计初衷是用来和服务器通讯,而不是本地存储,他只是被‘借用’到本地存储。
Cookie有一些缺点:存储空间小,最大4k、http请求时需要发送到服务器,增加请求数据量、只能用document.cookie=’…’ 来修改,太过简陋
localStorage、sessionStorage
优点:HTML5专门为存储而设计,最大可存5M、API简单易用setItem getItem、不会随着http请求被发送出去
localStorage、sessionStorage不同点:
localStorage数据会永久存储,除非代码或手动删除
sessionStroage 数据只存在于当前会话,浏览器关闭则清空
一般用localStorage会更多一些
注意:localStorage只支持string类型的存储。
9、let、var、const区别
在ES5中,声明变量只有var和function两种形式。但是因为var声明的变量会有一定的缺点(内层变量可能覆盖外层变量的问题以及用来计数的循环变量泄露为全局变量,下面有介绍),ES6提出了使用let和const声明变量,弥补了ES5中var的缺点。
1.是否存在变量提升?
var声明的变量存在变量提升(将变量提升到当前作用域的顶部)。即变量可以在声明之前调用,值为undefined。
let和const不存在变量提升。即它们所声明的变量一定要在声明后使用,否则报ReferenceError错。
2.是否存在暂时性死区?
let和const存在暂时性死区。即只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
3.是否允许重复声明变量?
var允许重复声明变量。
let和const在同一作用域不允许重复声明变量。
4.是否存在块级作用域?
var不存在块级作用域。
let和const存在块级作用域。
什么是块级作用域:
ES5中作用域有:全局作用域、函数作用域。没有块作用域的概念。因此也有一系列的问题。
ECMAScript 6(简称ES6)中新增了块级作用域。块作用域由{ }包括,if语句和for语句里面的{ }也属于块作用域。
- 是否能修改声明的变量?
var和let可以。
const声明一个只读的常量。一旦声明,常量的值就不能改变。const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
10、es6解构赋值
概念:解构赋值就是从目标对象或数组中提取自己想要的变量。最常用的场景是:element-ui,vant-ui按需引入,请求接口返回数据,提取想要数据。
常见的几种方式有
1.默认值
2.交换变量
3.将剩余数组赋给一个变量
当结构一个数组时,可以使用剩余模式,将数组剩余部分赋值给一个变量
4.给新的变量名赋值
可以从一个对象中提取变量并赋值给和对象属性名不同的新的变量名
11、箭头函数与普通函数的区别
1、箭头函数是匿名函数,不能作为构造函数,不能使用new
箭头函数相当于匿名函数,并且简化了函数定义。箭头函数有两种格式:一种只包含一个表达式,连{ ... }和return都省略掉。还有一种可以包含多条语句,这时候就不能省略{ ... }和return。
2.箭头函数内没有arguments,可以用展开运算符…解决
arguments:是一个方法调用的集合,是一个伪数组,不是真的数组,不具有数组的操作的方法,可以用展开运算解决(...)
3.箭头函数的this,始终指向父级上下文(箭头函数的this取决于定义位置父级的上下文,跟使用位置没关系,普通函数this指向调用的那个对象)
4.箭头函数不能通过call()、apply()、bind()方法直接修改它的this指向。
5.箭头函数没有原型属性
12.class与class继承 *
传统的javascript中只有对象,没有类的概念。它是基于原型的面向对象语言。原型对象特点就是将自身的属性共享给新对象。这样的写法相对于其它传统面向对象语言来讲,独树一帜也可以说难以接受!
ES5中如果要生成一个对象实例,需要先定义一个构造函数,然后通过new操作符来完成。
构造函数生成实例的执行过程:
1.当使用了构造函数,并且new 构造函数(),后台会隐式执行new Object()创建对象;
2.将构造函数的作用域给新对象,(即new Object()创建出的对象),而函数体内的this就代表new Object()出来的对象。
3.执行构造函数的代码。
4.返回新对象(后台直接返回);
ES6中的类
ES6引入了class(类)这个概念,通过class关键字可以定义类。该关键字的出现使得javascript在对象写法上更加清晰,更像是一种面向对象的语言。
注意项:
1.在类中声明方法的时候,千万不要给该方法加上function关键字
2.方法之间不要用逗号分隔,否则会报错
ES5中的继承 (组合继承:原型链继承 + 借用构造函数)
原型链继承:
父类的实例作为子类的原型
借用构造函数继承:
在子类内,使用call()调用父类方法,并将父类的this修改为子类的this.相当于是把父类的实例属性复制了一份放到子类的函数内.
组合继承:
既能调用父类实例属性,又能调用父类原型属性
13、promise使用及实现
什么是promise
promise是es6 中专门用来处理异步回调的,可以解决回调地狱
promise是一个构造函数,这个构造函数中放一个回调函数作为参数,这个回调函数中放的是异步的操作,
对于一个异步操作来说执行是需要时间的,所以一开始promise是一个pending状态
到了一定的条件就会变成fulfilled(成功)或者reject(失败的状态)
在成功的时候我们执行resolve回调函数,其实调用的是.then里的回调,在失败的时候执行reject回调函数其实调用的是catch回调
说白了 promise就是把原来的回调函数嵌套在里面的写法变成了链式写法(.then的写法)
Promise对象的状态不受外界影响
1)pending 初始状态 等待
2)fulfilled 成功状态
3)rejected 失败状态
Promise 有以上三种状态,只有异步操作的结果可以决定当前是哪一种状态,其他任何操作都无法改变这个状态
Promise的状态一旦改变,就不会再变,任何时候都可以得到这个结果,状态不可以逆,只能由 pending变成fulfilled或者由pending变成rejected
all()方法: Promise 的 all 方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。
race()方法: race 按字面解释,就是赛跑的意思。race 的用法与 all 一样,只不过 all 是等所有异步操作都执行完毕后才执行 then 回调。而 race 的话只要有一个异步操作执行完毕,就立刻执行 then 回调。
promise简单举例
//Promise异步封装ajax