1. 为什么data是函数?
因为是对象的话,多处引用,修改一个组件的值,其他组件的值也会发送改变,所有用返回对象的函数,每一次返回的都是object实例,因为存储地址不同,所以不会发送以上的问题
2. this指向?
普通函数中如果没有调用this, 那么他就指向window 在严格模式中就指向undefined
函数中有多个对象时即使这个函数是被最外层的对象调用那this也还是指向上一级对象
箭头函数中不绑定this所以它会捕获上下文的this值作为自己的值
1.在全局中this指向window
2.直接调用函数this指向window
3.事件处理函数中this指向绑定事件的元素
4.obj.fn(); fn函数中this指向obj
5.回调函数中this指向window
6.构造函数中this指向实例化对象
3. 面向对象编程与面向过程的区别:
1)面向对象编程(面向对象特点: 封装 继承 多态 ):
1.面向对象编程是一个基于现实世界模型的一种编程方法
2.将属性抽象成一个对象,在这个对象上创建属性和方法
3.把函数封装变为对对象的封装
ps:创建对象的方法六种:
1.直接给对象绑定属性和方法
2.通过字面量方式创建
3.工厂函数 4.构造函数模式 5.原型模式 6.混合模式
2)面向过程编程:
分析实现效果的步骤,然后按照步骤用函数一步一步实现
ps:构造函数模式与工厂函数的区别:
工厂函数return返回 方法不一样
4. proto与prototype的关系/区别:
__proto__是隐式原型
prototype是显示原型:用来实现基于原型的继承与属性的共享
可通过Object.getPrototypeOf()标准方法访问该属性),指向构造函数的原型对象。
5. 原型链:
每一个对象都要自己的原型_proto_ , 这个原型也有他自身的原型对象prototype ,以此类推, 上升到了object.prototype, 而object.prototype的_proto_是null , null没有属性和方法, 原型链尽头是null.
5.面向对象的继承
原型继承 构造函数继承 实例继承 组合继承 寄生组合继承 class类继承
6.闭包原理:
函数中的函数读取函数内部的变量
优点: 1.能够读取函数内部的变量. 2.让这些变量一直存在于内存中,不会在调用结束后,被垃圾回收机制回收
缺点: 因为闭包会使函数中的变量保存在内存中,内存消耗大,所以不能滥用闭包
解决办法: 退出函数前,将不使用的局部变量删除
7. 构造函数原理
构造函数是一种特殊方法,用于初始化对象.在类的对象创建时,构造函数将被调用
优点: 能够通过instanceof识别对象
缺点: 每次实例化一个对象,都会把属性和方法复制一遍
解决办法: 把对象的方法指向同一个全局函数 通过原型对象(prototype),把方法写在构造函数的原型上
8. 回调函数
回调函数是一段可执行的代码段它作为一个参数传递给其他的代码
其作用是在需要的时候方便调用这段(回调函数)代码
优点: 简单,容易理解和实现
缺点: 不利于代码的阅读和维护,各个部分之间高度耦合(coupling)使得程序结构混乱,流程难以追踪,每个任务只能指定一个回调函数
9.说一说你对promise的理解。
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。
Promise有哪些状态。 答:有三个状态:pending : 等待 fullfilled(resolved) :成功 rejected: 失败
所谓promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
Promise.all(),一个失败后,其他的还返回吗? 答:不会返回,promise.all()失败的时候只返回最先被reject失败状态的那个实例对象的值
Promise.all()、Promise.race()区别? 答:两者都是可以同时调用多个promise实现,Promise.all可以将多个实例组装成一个新的实例,成功的时候返回一个成功数组,失败的时候则返回最先被reject失败状态的值;其中有一个实例不成功则返回reject; race()是赛跑的意思,也就是说Promise.race([p1, p2, p3])里面的结果哪个获取的快,就返回哪个结果,不管结果本身是成功还是失败
10.简单说一下async/await的了解?(****)(请参考https://www.jianshu.com/p/fd6933ff6b81)
答:async/await是写异步代码的新方式,它是generator的语法糖,以前的方法有回调函数和 Promise。async/await是基于Promise实现的,它不能用于普通的回调函数。 async/await与Promise一样,是非阻塞的。async/await使得异步代码看起来像同步代码,这正是它的魔力所在。单一的 Promise 链并不能发现 async/await 的优势, 但是,如果需要处理由多个 Promise 组成的 then 链的时候,优势就能体现出来了
11.Async&await和promise有什么区别?(参考https://www.jianshu.com/p/51f5fd21588e)
答: (1)函数前面多了一个async关键字。await关键字只能用在async定义的函数内。async函数会引式返回一个promise
(2)简洁:使用async和await明显节约了不少代码,不需要.then,不需要写匿名函数处理promise的resolve的值,不需要定义多余的data变量,还避免了嵌套代码。
(3)async/await让try/catch 可以同时处理同步和异步错误。try/catch不能处理JSON.parse的错误,因为他在promise中。此时需要.catch,这样的错误处理代码非常冗余。并且,在我们的实际生产代码会更加复杂
(4)async/await能够使得代码调试更简单
12、写出本地存储和cookie的区别
本地存储: 可以设置有效期限 存储空间只有4KB左右
cookie优缺点
cookie机制将信息存储于浏览器,因此可以作为跨页面全局变量,这是它最大的一个优点
常用场合:(1)保存用户登录状态;(2)跟踪用户行为.等等
cookie的缺点
(1)cookie可能被禁用; (2)cookie与浏览器相关,不能互相访问; (3)cookie可能被用户删除; (4)cookie安全性不够高; (5)cookie存储空间很小(只有4KB左右)
用escape( )函数进行编码 unescape( )进行解码才能
expires=data 设置有效期
localStorage
HTML5 本地存储:
大小最小5MB,可以申请更大的空间
不会随HTTP请求发送给服务器
非常容易操作 移动端普及高
localStorage与sessionStorage两种:
localStorage l localStorage为永久性保存数据,不会随着浏览器的关闭而消失,可以在同域名跨页访问。 l 按域名进行存储,不会和其他域名冲突 l 键值对存储:key/value
13. localStorage和sessionStorage是Web提供的两种本地存储方式。
相比较cookie而言,localStorage和sessionStorage的存储大小很大,localStorage能够长期保存,sessionStorage在会话期间保存。
localStorage和sessionStorage都是window对象提供的全局属性,用途都是在浏览器中存储key/value对的数据。
从使用的角度来看,两者的唯一区别在于时效性。
sessionStorage在关闭窗口或标签页之后将会删除这些数据。
而localStorage则没有这样的特性,它的数据一直都在,除非你手动去删除。
如果你想在浏览器窗口关闭后还保留数据,请使用localStorage。
如果你是想用于临时保存同一窗口(或标签页)的数据,请使用sessionStorage。
14.Vue2和vue3的响应式原理分别是什么,以及vue3为什么要更改实现响应式原理的方式
vue2.x用的核心函数是Object.defineProperty,defineProperty核心并不是为对象做数据绑定的,而是给对象的属性做一些配置, 只不过里面的set和get实现了。
响应式defineProperty的缺陷是只能监听一个属性,所以要想监听一个对象,
vue2的内部做了一个 for in 处理
而vue3用proxy写,proxy可以监听整个对象。省去for in提升效率,并且可以监听数组,不用再去单独的对数组做特异性操作
15.proxy和defineProperty的区别
Object.defineProperty 无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应;
Object.defineProperty只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。
Proxy 可以劫持整个对象,并返回一个新的对象
Proxy 不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性
Proxy 相比于 defineProperty 的优势 ?
数组变化也能监听到 不需要深度遍历监听
16.Async函数用法和promise区别
答:简单的说async函数就相当于自执行的Generator函数,相当于自带一个状态机, 在await的部分等待返回, 返回后自动执行下一步。
而且相较于Promise,async的 优越性就是把每次异步返回的结果从then中拿到最外层的方法中,不需要链式调用, 只要用同步的写法就可以了。更加直观而且,更适合处理并发调用的问题。
但是async 必须以一个Promise对象开始 ,所以async通常是和Promise结合使用的。
总的来说, async函数主要就是为了解决异步的并发调用使用的 ,直接将参数从then里取出来, 相比promise的链式调用,传参更加方便,异步顺序更加清晰。
17.简单说一下事件冒泡
答:IE 的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深 的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。
事件沿 DOM 树向上传播,在每一级节点上都会发生,直至传播到 document 对象。
所有现代浏览器都支持事件冒泡,但在具体实现上还是有一些差别。
IE5.5 及更早版本中的事件冒泡会跳过<html>元素(从<body>直接跳到 document)。
IE9、Firefox、Chrome 和 Safari 则将事件一直冒泡到 window 对象。
18.为什么Vuex中的state数据不放到data里面而放在computed里面
data只会在进入页面的时候初始化一次,计算属性会实时更新
19.声明式与编程式
声明式导航是写在template标签里,通过<router-link to=''></router-link>标签来触发
编程式导航写在js里,通过this.$router.push(xxx)来触发路径
ps: .split('').reverse().join('');拆分 倒序 重组
20.编程式中push有浏览记录 replace不会有浏览记录
注意:在 Vue 实例内部,你可以通过 $router 访问路由实例。
因此你可以调用 this.$router.push。
想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。
当你点击 <router-link> 时,这个方法会在内部调用,所以说,点击 <router-link :to="..."> 等同于调用 router.push(...)。
该方法的参数可以是一个字符串路径,或者一个描述地址的对象。
例如: // 字符串 router.push('home') // 对象 router.push({ path: 'home' }) // 命名的路由 router.push({ name: 'user', params: { userId: '123' }}) // 带查询参数,变成 /register?plan=private router.push({ path: 'register', query: { plan: 'private' }})
注意:如果提供了 path,params 会被忽略,上述例子中的 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 或手写完整的带有参数的 path
const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user
ps:同样的规则也适用于 router-link 组件的 to 属性。
21.route懒加载动态导入
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块, 然后当路由被访问的时候才加载对应组件,这样就会更加高效。
Vue Router 支持开箱即用的动态导入,这意味着你可以用动态导入代替静态导入:
// 将 import UserDetails from './views/UserDetails' 静态导入
替换成
const UserDetails = () => import('./views/UserDetails') 动态导入
有时候我们想把某个路由下的所有组件都打包在同个异步块 (chunk) 中
只需要使用命名 chunk,一个特殊的注释语法来提供 chunk name const UserDetails = () => import(/* webpackChunkName: "group-user" */ './UserDetails.vue') const UserDashboard = () => import(/* webpackChunkName: "group-user" */ './UserDashboard.vue') const UserProfileEdit = () => import(/* webpackChunkName: "group-user" */ './UserProfileEdit.vue') webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中。
23.组件通信:
vuex(三种):
父传子(props):在父组件自定义属性名传递数据,在父组件在引入和挂载子组件,在父组件使用它,
在标签上绑定你想传入的数据,在子组件上用props接受数据,并且使用它子传父($emit): 父组件向子组件传递事件方法,子组件通过$emit触发事件,回调给父组件
兄弟通信bus(需要有共同的父组件):
设定事件中心vue实例 中央通信 let bus = new vue()
A:methods:{函数{bus.$emit("自定义事件名",数据)}} 发送
B:created(){bus.$on("A发送过来的自定义事件名",函数)} 进行数据接受provide&inject:
组件跟后代的通信方法是不可响应的 provide传入 inject注入 父组件以provide将自己的数据以对象方式传出去
$parent&$children:
$parent获取所有父组件 $children获取所有子组件 获取不到的原因是因为created创建后DOM还没有出来所以用mounted
$listeners&$attrs:
跨组件传值 $attrs获取所有父组件里面的属性不包含props传过的
$listeners自定义的事件传入方法
$parent与$attrs有什么区别?
$parent获取所有父组件 $attrs也是获取所有父组件但是不包含props传过的 不自定义属性也是获取不到
24.自定义指令
默认内置指令与自定义指令
自定义指令有 全局 跟 局部
Vue.directive('style', {
// 当被绑定的元素插入到 DOM 中时……
bind: function (el) {
// 聚焦元素 el.style.backgroundColor='res'
}
})
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 一般用于属性
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。 一般用于DOM
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。 我们会在稍后讨论渲染函数时介绍更多 VNodes 的细节。
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。
指令钩子函数会被传入以下参数:
el:指令所绑定的元素,可以用来直接操作 DOM。
binding:一个对象,包含以下 property:
name:指令名,不包括 v- 前缀。
value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
inserted:function(el,binding){
for(var emo in binding.value){
el.style[emo]=binding.value[emo]
}
}
25.vue-过滤器:
1、vue过滤器简介 vue过滤器就是用来过滤模型数据,在显示之前进行数据处理和筛选。
2、vue过滤器使用语法 语法:{{ data | filter1(参数) | filter2(参数) }}
3、vue内置过滤器 使用自定义过滤器
4、自定义过滤器 分类:全局过滤器,局部过滤器
1 自定义全局过滤器 语法:使用全局方法Vue.filter(过滤器ID,过滤器函数),过滤器写在window.οnlοad=function(){ new Vue...} /export default 的外面。
2 自定义局部过滤器 语法:使用局部方法filters:{过滤器ID:(过滤器参数1,过滤器参数2...)=>{函数回调}},过滤器写在new Vue里面。
forEach用于数组遍历 for in 用于对象遍历
Object.keys(obj)参数:要返回其枚举自身属性的对象返回值:一个表示给定对象的所有可枚举属性的字符串数组
Object.values()返回一个数组,成员是参数的对象自身的(不含继承)所有可遍历属性的键值
26.路由守卫的执行过程:
全局前置守卫beforeEach---->路由独享守卫beforeEnter---->组件内的守卫beforeRouteEnter/beforeRouteUpdate/beforeRouteLeave---->全局解析守卫beforeResolve---->全局后置钩子afterEach 组件内守卫--进入 组件内守卫--切换 组件内守卫--离开 全局后置钩子afterEach
ps: afterEach没有next()钩子
beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。
27.$route和$router的区别
$route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。
而$router是“路由实例”对象包括了路由的跳转方法,钩子函数等
28.Vue中hash模式和history模式的区别
在最明显的显示上:
hash模式的URL中会夹杂着#号,而history没有。
Vue底层对它们的实现方式不同:
hash模式是依靠onhashchange事件(监听location.hash的改变)
history模式是主要是依靠的HTML5 history中新增的两个方法,
pushState()可以改变url地址且不会发送请求,
replaceState()可以读取历史记录栈,还可以对浏览器记录进行修改。window.onhashchange = function(event){
// location.hash获取到的是包括#号的,如"#heading-3"
// 所以可以截取一下 let hash = location.hash.slice(1);
}
ps: 当真正需要通过URL向后端发送HTTP请求的时候,比如常见的用户手动输入URL后回车,或者是刷新(重启)浏览器,这时候history模式需要后端的支持。因为history模式下,前端的URL 必须和实际向后端发送请求的URL一致,例如有一个URL是带有路径path的(例如www.libai.wang/blogs/id),如果后端没有对这个路径做处理的话,就会返回404错误。所以需要后端增 加一个覆盖所有情况的候选资源,一般会配合前端给出的一个404页面。
当活动历史记录条目更改时,将触发popstate事件。
如果被激活的历史记录条目是通过对history.pushState()的调用创建的,或者受到对 history.replaceState()的调用的影响,popstate事件的state属性包含历史条目的状态对象的副本。
需要注意的是调用history.pushState()或history.replaceState()不会触发popstate事件。
只有在做出浏览器动作时,才会触 发该事件,如用户点击浏览器的回退按钮(或者在Javascript代码中调用history.back()或者history.forward()方法)
29.nextTick
nextTick可以让我们在下次 DOM 更新循环结束之后执行延迟回调,用于获得更新后的 DOM nextTick主要使用了宏任务和微任务。
根据执行环境分别尝试采用 Promise Mutation Observer setImmediate
如果以上都不行则采用setTimeout 定义了一个异步方法,多次调用nextTick会将方法存入队列中,通过这个异步方法清空当前队列
30. <keep-alive></keep-alive>的作用是什么?
keep-alive可以实现组件缓存,当组件切换时,主要用于保留组件状态或避免重新渲染
使用场景:比如有一个列表和一个详情,那么用户就会经常执行打开详情=>返回列表=>打开详情…这样的话列表和详情都是 一个频率很高的页面,那么就可以对列表组件使用<keep-alive></keep-alive>进行缓存,这样用户每次返回列表的时候, 都能从缓存中快速渲染,而不是重新渲染
常用的两个属性include/exclude,允许组件有条件的进行缓存
两个生命周期activated/deactivated,用来得知当前组件是否处于活跃状态
31.mixins:
mixins 选项接收一个混入对象的数组。
这些混入对象可以像正常的实例对象一样包含实例选项,这些选项将会被 合并到最终的选项中,使用的是和 Vue.extend() 一样的选项合并逻辑。
也就是说,如果你的混入包含一个 created 钩子,而创建组件本身也有一个,那么两个函数都会被调用。
Mixin钩子按照传入顺序依次调用,并在调用组件自身的钩子之前被调用。
32.Proxy
Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
Object.defineProperty的作用----> 用来给对象新增属性,和修改对象中的属性。
writable、enumerable、configurable为false的情况
wirtable:变量不可再被重新赋值
enumerable: 变量不能在遍历器例如for...in和Object.keys()中被读取出来,不可被遍历
configurable:变量不可配置,定义为false之后,不能再为该变量定义配置否则报错。变量被删除(delete)、修改都会无效。
如果对象的属性是存取描述符,只会调用定义了的set和get(configurable、enumrable)
在给一个对象属性做赋值操作,在读取属性值时,这个赋值操作赋值的值会被忽略,会去调用定义的get方法的值
Proxy 相比于 defineProperty 的优势
Object.defineProperty() 的问题主要有三个:
不能监听数组的变化 必须遍历对象的每个属性 必须深层遍历嵌套的对象
Proxy 在 ES2015 规范中被正式加入,它有以下几个特点
针对对象:针对整个对象,而不是对象的某个属性,所以也就不需要对 keys 进行遍历。这解决了上述 Object.defineProperty()
支持数组:Proxy 不需要对数组的方法进行重载,省去了众多 hack,减少代码量等于减少了维护成本,而且标准的就是最好的。
除了上述两点之外,Proxy 还拥有以下优势:
Proxy 的第二个参数可以有 13 种拦截方法,这比起 Object.defineProperty() 要更加丰富 Proxy 作为新标准受到浏览器厂商的重点关注和性能优化,相比之下 Object.defineProperty() 是一个已有的老方法。
get(target, propKey, receiver):拦截对象属性的读取,比如proxy.foo和proxy['foo']。 set(target, propKey, value, receiver):拦截对象属性的设置,比如proxy.foo = v或proxy['foo'] = v,返回一个布尔值。
getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象。 setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值
Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问 进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。
Proxy 支持的拦截操作一览,一共 13 种。
get(target, propKey, receiver):拦截对象属性的读取,比如proxy.foo和proxy['foo']。
set(target, propKey, value, receiver):拦截对象属性的设置,比如proxy.foo = v或
proxy['foo'] = v,返回一个布尔值。
has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值。
deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值。
ownKeys(target):拦截
Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,
返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象
defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs), 返回一个布尔值。
preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个布尔值。 getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象。 isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值。
setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。
construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。
Proxy 实例的方法
get() -------get方法用于拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身(严格地说,是操作行为所针对的对象),其中最后一个参数可选。 get方法可以继承。
set() -------set方法用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。 假定Person对象有一个age属性,该属性应该是一个不大于 200 的整数,那么可以使用Proxy保证age的属性值符合要求。
has()-------has()方法用来拦截HasProperty操作,即判断对象是否具有某个属性时,这个方法会生效。典型的操作就是in运算符。 has()方法可以接受两个参数,分别是目标对象、需查询的属性名。、
construct()------construct()方法用于拦截new命令 construct()方法可以接受三个参数。 target:目标对象。 args:构造函数的参数数组。 newTarget:创造实例对象时,new命令作用的构造函数 deleteProperty() deleteProperty方法用于拦截delete操作,如果这个方法抛出错误或者返回false,当前属性就无法被delete命令删除。 deleteProperty方法拦截了delete操作符,删除第一个字符为下划线的属性会报错。 目标对象自身的不可配置(configurable)的属性,不能被deleteProperty方法删除,否则报错。
defineProperty()---------defineProperty()方法拦截了Object.defineProperty()操作。 如果目标对象不可扩展(non-extensible),则defineProperty()不能增加目标对象上不存在的属性,否则会报错。另外,如果目标对 象的某个属性不可写(writable)或不可配(configurable),则defineProperty()方法不得改变这两个设置。
getOwnPropertyDescriptor()--------getOwnPropertyDescriptor()方法拦截Object.getOwnPropertyDescriptor(),返回一个属性描述对象或者undefined。 handler.getOwnPropertyDescriptor()方法对于第一个字符为下划线的属性名会返回undefined。
getPrototypeOf()---------getPrototypeOf()方法主要用来拦截获取对象原型。具体来说,拦截下面这些操作。
Object.prototype.__proto__
Object.prototype.isPrototypeOf()
Object.getPrototypeOf()
Reflect.getPrototypeOf()
instanceof
getPrototypeOf()方法的返回值必须是对象或者null,否则报错。另外,如果目标对象不可扩展(non-extensible), getPrototypeOf()方法必须返回目标对象的原型对象。
33.文件信息
├── build --------------------------------- webpack相关配置文件
│ ├── build.js --------------------------webpack打包配置文件
│ ├── check-versions.js ------------------------------ 检查npm,nodejs版本
│ ├── dev-client.js ---------------------------------- 设置环境
│ ├── dev-server.js ---------------------------------- 创建express服务器,配置中间件,启动可热重载的服务器,用于开发项目
│ ├── utils.js --------------------------------------- 配置资源路径,配置css加载器
│ ├── vue-loader.conf.js ----------------------------- 配置css加载器等
│ ├── webpack.base.conf.js --------------------------- webpack基本配置
│ ├── webpack.dev.conf.js ---------------------------- 用于开发的webpack设置
│ ├── webpack.prod.conf.js --------------------------- 用于打包的webpack设置
├── config ---------------------------------- 配置文件
├── node_modules ---------------------------- 存放依赖的目录
├── src ------------------------------------- 源码
│ ├── assets ------------------------------ 静态文件
│ ├── components -------------------------- 组件
│ ├── main.js ----------------------------- 主js
│ ├── App.vue ----------------------------- 项目入口组件
│ ├── router ------------------------------ 路由
├── package.json ---------------------------- node配置文件
├── .babelrc--------------------------------- babel配置文件
├── .editorconfig---------------------------- 编辑器配置
├── .gitignore------------------------------- 配置git可忽略的文件
34.Reflect对象 :
Reflect对象与Proxy对象一样,也是 ES6 为了操作对象而提供的新 API。
Reflect对象的设计目的有这样几个。
(1) 将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上。现阶段,某些方法同时在Object和Reflect对象上部署,未来的新方法将只部署在Reflect对象上。也就是说,从Reflect对象上可以拿到语言内部的方法。
(2) 修改某些Object方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)则会返回false。
(3) 让Object操作都变成函数行为。某些Object操作是命令式,比如name in obj和delete obj[name],而Reflect.has(obj, name)和Reflect.deleteProperty(obj, name)让它们变成了函数行为。
(4)Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为,作为修改行为的基础。
也就是说,不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。
Reflect对象一共有 13 个静态方法。
Reflect.apply(target, thisArg, args)
Reflect.construct(target, args)
Reflect.get(target, name, receiver)
Reflect.set(target, name, value, receiver)
Reflect.defineProperty(target, name, desc)
Reflect.deleteProperty(target, name)
Reflect.has(target, name)
Reflect.ownKeys(target)
Reflect.isExtensible(target)
Reflect.preventExtensions(target)
Reflect.getOwnPropertyDescriptor(target, name)
Reflect.getPrototypeOf(target)
Reflect.setPrototypeOf(target, prototype)