更新:谢谢你们的支持,最近折腾了一个博客官网出来,方便你们系统阅读,后续会有更多内容和更多优化,猛戳这里查看css
------ 如下是正文 ------html
半月刊第四期来啦,这段时间 Daily-Interview-Question 新增了 14 道高频面试题,今天就把最近半月汇总的面试题和部分答案发给你们,帮助你们查漏补缺,欢迎 加群 互相学习。前端
更多更全的面试题和答案汇总在下面的项目中,点击查看。vue
项目地址:Daily-Interview-Questiongit
若是修改了,Vue 是如何监控到属性的修改并给出警告的。github
解析:面试
if (process.env.NODE_ENV !== 'production') {
var hyphenatedKey = hyphenate(key);
if (isReservedAttribute(hyphenatedKey) ||
config.isReservedAttr(hyphenatedKey)) {
warn(
("\"" + hyphenatedKey + "\" is a reserved attribute and cannot be used as component prop."),
vm
);
}
defineReactive$$1(props, key, value, function () {
if (!isRoot && !isUpdatingChildComponent) {
warn(
"Avoid mutating a prop directly since the value will be " +
"overwritten whenever the parent component re-renders. " +
"Instead, use a data or computed property based on the prop's " +
"value. Prop being mutated: \"" + key + "\"",
vm
);
}
});
}
复制代码
在initProps的时候,在defineReactive时经过判断是否在开发环境,若是是开发环境,会在触发set的时候判断是否此key是否处于updatingChildren中被修改,若是不是,说明此修改来自子组件,触发warning提示。vuex
须要特别注意的是,当你从子组件修改的prop属于基础类型时会触发提示。 这种状况下,你是没法修改父组件的数据源的, 由于基础类型赋值时是值拷贝。你直接将另外一个非基础类型(Object, array)赋值到此key时也会触发提示(但实际上不会影响父组件的数据源), 当你修改object的属性时不会触发提示,而且会修改父组件数据源的数据。segmentfault
未完待续,点击查看更多细节:第 40 题跨域
var a = 10;
(function () {
console.log(a)
a = 5
console.log(window.a)
var a = 20;
console.log(a)
})()
复制代码
解析:
依次输出:undefined -> 10 -> 20
在当即执行函数中,var a = 20;
语句定义了一个局部变量 a
,因为js的变量声明提高机制,局部变量a
的声明会被提高至当即执行函数的函数体最上方,且因为这样的提高并不包括赋值,所以第一条打印语句会打印undefined
,最后一条语句会打印20
。
因为变量声明提高,a = 5;
这条语句执行时,局部的变量a
已经声明,所以它产生的效果是对局部的变量a
赋值,此时window.a
依旧是最开始赋值的10
。
未完待续,点击查看更多细节:第 41题
好比 sleep(1000) 意味着等待1000毫秒,可从 Promise、Generator、Async/Await 等角度实现。
解析:4 种方式
//Promise
const sleep = time => {
return new Promise(resolve => setTimeout(resolve,time))
}
sleep(1000).then(()=>{
console.log(1)
})
//Generator
function* sleepGenerator(time) {
yield new Promise(function(resolve,reject){
setTimeout(resolve,time);
})
}
sleepGenerator(1000).next().value.then(()=>{console.log(1)})
//async
function sleep(time) {
return new Promise(resolve => setTimeout(resolve,time))
}
async function output() {
let out = await sleep(1000);
console.log(1);
return out;
}
output();
//ES5
function sleep(callback,time) {
if(typeof callback === 'function')
setTimeout(callback,time)
}
function output(){
console.log(1);
}
sleep(output,1000);
复制代码
未完待续,点击查看更多细节:第 42 题
解析:
sort
函数,能够接收一个函数,返回值是比较两个数的相对顺序的值
UTF-16
排序的,对于字母数字 你能够利用 ASCII
进行记忆[3, 15, 8, 29, 102, 22].sort();
// [102, 15, 22, 29, 3, 8]
复制代码
[3, 15, 8, 29, 102, 22].sort((a,b) => {return a - b});
复制代码
对于函数体返回
b-a
能够类比上面的返回值进行交换位置
未完待续,点击查看更多细节:第 43 题
解析:
开始加密通讯以前,客户端和服务器首先必须创建链接和交换参数,这个过程叫作握手(handshake)。
假定客户端叫作爱丽丝,服务器叫作鲍勃,整个握手过程能够用下图说明。
握手阶段分红五步。
第一步,爱丽丝给出协议版本号、一个客户端生成的随机数(Client random),以及客户端支持的加密方法。
第二步,鲍勃确认双方使用的加密方法,并给出数字证书、以及一个服务器生成的随机数(Server random)。
第三步,爱丽丝确认数字证书有效,而后生成一个新的随机数(Premaster secret),并使用数字证书中的公钥,加密这个随机数,发给鲍勃。
第四步,鲍勃使用本身的私钥,获取爱丽丝发来的随机数(即Premaster secret)。
第五步,爱丽丝和鲍勃根据约定的加密方法,使用前面的三个随机数,生成"对话密钥"(session key),用来加密接下来的整个对话过程。
参考:
未完待续,点击查看更多细节:第 44 题
解析:
一、首先什么是HTTP协议? http协议是超文本传输协议,位于tcp/ip四层模型中的应用层;经过请求/响应的方式在客户端和服务器之间进行通讯;可是缺乏安全性,http协议信息传输是经过明文的方式传输,不作任何加密,至关于在网络上裸奔;容易被中间人恶意篡改,这种行为叫作中间人攻击;
二、加密通讯: 为了安全性,双方可使用对称加密的方式key进行信息交流,可是这种方式对称加密秘钥也会被拦截,也不够安全,进而仍是存在被中间人攻击风险; 因而人们又想出来另一种方式,使用非对称加密的方式;使用公钥/私钥加解密;通讯方A发起通讯并携带本身的公钥,接收方B经过公钥来加密对称秘钥;而后发送给发起方A;A经过私钥解密;双发接下来经过对称秘钥来进行加密通讯;可是这种方式仍是会存在一种安全性;中间人虽然不知道发起方A的私钥,可是能够作到偷天换日,将拦截发起方的公钥key;并将本身生成的一对公/私钥的公钥发送给B;接收方B并不知道公钥已经被偷偷换过;按照以前的流程,B经过公钥加密本身生成的对称加密秘钥key2;发送给A; 此次通讯再次被中间人拦截,尽管后面的通讯,二者仍是用key2通讯,可是中间人已经掌握了Key2;能够进行轻松的加解密;仍是存在被中间人攻击风险;
三、解决困境:权威的证书颁发机构CA来解决;
四、https主要的思想是在http基础上增长了ssl安全层,即以上认证过程。
未完待续,点击查看更多细节:第 45 题
var obj = {
'2': 3,
'3': 4,
'length': 2,
'splice': Array.prototype.splice,
'push': Array.prototype.push
}
obj.push(1)
obj.push(2)
console.log(obj)
复制代码
解析:
涉及知识点:
一组数据,由数组来存,可是若是要对这组数据进行扩展,会影响到数组原型,ArrayLike的出现则提供了一个中间数据桥梁,ArrayLike有数组的特性, 可是对ArrayLike的扩展并不会影响到原生的数组。
push 方法有意具备通用性。该方法和 call() 或 apply() 一块儿使用时,可应用在相似数组的对象上。push 方法根据 length 属性来决定从哪里开始插入给定的值。若是 length 不能被转成一个数值,则插入的元素索引为 0,包括 length 不存在时。当 length 不存在时,将会建立它。 惟一的原生类数组(array-like)对象是 Strings,尽管如此,它们并不适用该方法,由于字符串是不可改变的。
Array.from()、splice()、concat()等。
题分析: 这个obj中定义了两个key值,分别为splice和push分别对应数组原型中的splice和push方法,所以这个obj能够调用数组中的push和splice方法,调用对象的push方法:push(1),由于此时obj中定义length为2,因此从数组中的第二项开始插入,也就是数组的第三项(下表为2的那一项),由于数组是从第0项开始的,这时已经定义了下标为2和3这两项,因此它会替换第三项也就是下标为2的值,第一次执行push完,此时key为2的属性值为1,同理:第二次执行push方法,key为3的属性值为2。此时的输出结果就是:
Object(4) [empty × 2, 1, 2, splice: ƒ, push: ƒ]---->
[
2: 1,
3: 2,
length: 4,
push: ƒ push(),
splice: ƒ splice()
]
复制代码
由于只是定义了2和3两项,没有定义0和1这两项,因此前面会是empty。 若是讲这道题改成:
var obj = {
'2': 3,
'3': 4,
'length': 0,
'splice': Array.prototype.splice,
'push': Array.prototype.push
}
obj.push(1)
obj.push(2)
console.log(obj)
复制代码
此时的打印结果就是:
Object(2) [1, 2, 2: 3, 3: 4, splice: ƒ, push: ƒ]---->
[
0: 1,
1: 2,
2: 3,
3: 4,
length: 2,
push: ƒ push(),
splice: ƒ splice()
]
复制代码
原理:此时length长度设置为0,push方法从第0项开始插入,因此填充了第0项的empty 至于为何对象添加了splice属性后并无调用就会变成类数组对象这个问题,这是控制台中 DevTools 猜想类数组的一个方式: github.com/ChromeDevTo…
未完待续,点击查看更多细节:第 46 题
解析:
当在严格模式中使用 Vuex 时,在属于 Vuex 的 state 上使用 v-model
会比较棘手:
<input v-model="obj.message">
复制代码
假设这里的 obj
是在计算属性中返回的一个属于 Vuex store 的对象,在用户输入时,v-model
会试图直接修改 obj.message
。在严格模式中,因为这个修改不是在 mutation 函数中执行的, 这里会抛出一个错误。
用“Vuex 的思惟”去解决这个问题的方法是:给 <input>
中绑定 value,而后侦听 input
或者 change
事件,在事件回调中调用 action:
<input :value="message" @input="updateMessage">
复制代码
// ...
computed: {
...mapState({
message: state => state.obj.message
})
},
methods: {
updateMessage (e) {
this.$store.commit('updateMessage', e.target.value)
}
}
复制代码
下面是 mutation 函数:
// ...
mutations: {
updateMessage (state, message) {
state.obj.message = message
}
}
复制代码
双向绑定的计算属性
必须认可,这样作比简单地使用“v-model
+ 局部状态”要啰嗦得多,而且也损失了一些 v-model
中颇有用的特性。另外一个方法是使用带有 setter 的双向绑定计算属性:
<input v-model="message">
复制代码
// ...
computed: {
message: {
get () {
return this.$store.state.obj.message
},
set (value) {
this.$store.commit('updateMessage', value)
}
}
}
复制代码
未完待续,点击查看更多细节:第 47 题
解析:
未完待续,点击查看更多细节:第 48 题
解析:
未完待续,点击查看更多细节:第 49 题
例: 5 + 3 - 2,结果为 6
解析:
Number.prototype.add = function(n) {
return this.valueOf() + n;
};
Number.prototype.minus = function(n) {
return this.valueOf() - n;
};
复制代码
未完待续,点击查看更多细节:第 50 题
为何在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty?
解析:
Object.defineProperty自己有必定的监控到数组下标变化的能力: Object.defineProperty自己是能够监控到数组下标的变化的,可是在 Vue 中,从性能/体验的性价比考虑,尤大大就弃用了这个特性。具体咱们能够参考 《记一次思否问答的问题思考:Vue为何不能检测数组变更》这篇文章,文章底部配图中有尤大大的严肃回复截图; 下方的讨论区也很值得你们下去看一看,有对于 for / forEach / for .. in .. 几个循环方式的讨论。
关于 Vue 3.0 的其余信息咱们能够参考 尤大大发布的 Vue 3.0 新特性预览PPT
直接经过数组的下标给数组设置值,不能实时响应。 为了解决这个问题,通过vue内部处理后可使用如下几种方法来监听数组
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
复制代码
因为只针对了以上几种方法进行了hack处理,因此其余数组的属性也是检测不到的,仍是具备必定的局限性。
Object.defineProperty只能劫持对象的属性,所以咱们须要对每一个对象的每一个属性进行遍历。Vue 2.x里,是经过 递归 + 遍历 data 对象来实现对数据的监控的,若是属性值也是对象那么须要深度遍历,显然若是能劫持一个完整的对象是才是更好的选择。
而要取代它的Proxy有如下两个优势;
能够劫持整个对象,并返回一个新对象 有13种劫持操做
未完待续,点击查看更多细节:第 51 题
解析:
<div class="parent">
<div class="child"></div>
</div>
复制代码
div.parent {
display: flex;
justify-content: center;
align-items: center;
}
复制代码
div.parent {
position: relative;
}
div.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/* 或者 */
div.child {
width: 50px;
height: 10px;
position: absolute;
top: 50%;
left: 50%;
margin-left: -25px;
margin-top: -5px;
}
/* 或 */
div.child {
width: 50px;
height: 10px;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
}
复制代码
div.parent {
display: grid;
}
div.child {
justify-self: center;
align-self: center;
}
复制代码
div.parent {
font-size: 0;
text-align: center;
&::before {
content: "";
display: inline-block;
width: 0;
height: 100%;
vertical-align: middle;
}
}
div.parent{
display: inline-block;
vertical-align: middle;
}
复制代码
未完待续,点击查看更多细节:第 52 题
var a = {n: 1};
var b = a;
a.x = a = {n: 2};
console.log(a.x)
console.log(b.x)
复制代码
解析:
var a = {n: 1};
var b = a;
a.x = a = {n: 2};
a.x // --> undefined
b.x // --> {n: 2}
复制代码
答案已经写上面了,这道题的关键在于
.
的优先级高于=
,因此先执行a.x
,堆内存中的{n: 1}
就会变成{n: 1, x: undefined}
,改变以后相应的b.x
也变化了,由于指向的是同一个对象。从右到左
,因此先执行a = {n: 2}
,a
的引用就被改变了,而后这个返回值又赋值给了a.x
,须要注意的是这时候a.x
是第一步中的{n: 1, x: undefined}
那个对象,其实就是b.x
,至关于b.x = {n: 2}
未完待续,点击查看更多细节:第 53 题
进阶系列文章汇总以下,以为不错点个 Star,欢迎 加群 互相学习。
我是木易杨,公众号「高级前端进阶」做者,跟着我每周重点攻克一个前端面试重难点。接下来让我带你走进高级前端的世界,在进阶的路上,共勉!