2021届秋招腾讯前端一面面经
码字不易,有帮助的同学希望能关注一下我的微信公众号:Code程序人生,感谢!代码自用自取。
基本信息
部门:QQ音乐
方式:电话面试
题目总结
JavaScript篇
- 自我介绍
- 学习前端多久
- JavaScript常见的数据类型有哪些
typeof null
返回什么- 原始类型和对象类型有什么区别
- 如何判断是
Object
还是Array
- 有接触过闭包吗?闭包有哪些应用场景
- js的垃圾回收机制
- 如何自己实现一个
new
- 如何自己实现一个
instanceof
- 原型链的最顶层是什么(
null
) - 原型链的继承方式有哪些,举例说明
- 原型链有没有什么缺点
- 子类
child
继承了父类的parent
之后,oarent
有一个属性name。这时new
一个子类的实例b
,如果修改了b.name
是否会修改父类上的name
属性
HTTP篇 - 如何用
ajax
原生实现一个post
请求(XMLHTTPRequest) - 其中有
ReadyState
,解释一下它的每个值代表的含义 - 使用
ajax
如何解决跨域问题 - 使用
JSONP
时服务端返回什么样的数据,如何处理(callback(json拼好))
DOM篇 - 假设一个
ul
下有一万个li
,li
的innerHTML
是从0
到9999
,当点击某个li
时输出该li
代表的值,如何实现 windowOnload
和DOMready
哪个先触发
浏览器安全篇- 讲讲
CSRF
和XSS
攻击的原理,和解决方式 - 假设有两个
tab
,一个是a.qq.com
,另一个是黑客的域名,你在黑客的域名下向a.qq.com
发起了一个请求,请问是否会带上a
页面的cookie
算法篇
爬楼梯
部分题目答案:
JavaScript常见的数据类型有哪些?
答案:
共8种。包括7种基本数据类型:
- 表示空:
null
,undefined
- 三大件:
string
,number
,boolean
- 两个新类型:
BigInt
,Symbol
和object
解读:
这里是按照 MDN 的说法回答的。也可以回答为 7 种 基本 数据类型,和 引用 类型。引用类型包括: - 普通对象
Object
- 数组对象
Array
- 正则对象
RegExp
- 函数
Function
如何判断是 Object 还是 Array
答案:
Object.prototype.toString.call([]) // "[object Array]"
Object.prototype.toString.call({}) // "[object Object]"
解读:
这是目前最准确的方法,网上流传了很多种判断方法,这个是最核心的,答出这个就可以了。
除此之外,还有一种提问方式是 如何判断是不是 Array,这是偏向于考察 ES6 新增的数组方法了,可以用Array.isArray()
和instanceof
来回答。
Array.isArray([1,2,3,4]) // true
Array.isArray({a:1, b:{c:'4'}}) // false
[1,2,3,4] instanceof Array // true
({a:1, b:{c:'4'}}) instanceof Object // true,这里使用 () 保证代码运行的优先级,不然会报语法错误
JS的垃圾回收机制
答案:
2012 年以前,相对旧的浏览器使用「引用-计数」算法(Reference Counting)进行垃圾回收,缺点是会由于循环应用导致内存泄漏。现代浏览器都使用「标记-清除」算法(Mark and Sweep),即从全局对象作为的根节点开始,向下查询引用的对象,没有查询到的对象都将被回收。
解读:
相对旧的浏览器如 ie6,ie7 是使用「引用-计数」法进行垃圾回收的。
参考链接:MDN
如何自己实现一个 new
答案:
function funcNew(obj, ...args) {
const newObj = Object.create(obj.prototype);
const result = obj.apply(newObj, args);
return (typeof result === 'object' && result !== null) ? result : newObj;
}
解读:
先通过一个例子来理解 new
的作用吧:
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function() {
console.log(this.name);
}
const p = new Person('orange')
console.log(p.name) // 'orange'
p.sayName(); // 'orange'
代码中我们新建了一个对象 Person
,它具有属性 name
,且在Person.prototype
上定义了函数 sayName
。
当我们通过 new
创建一个新的实例 p
时,便同时具有了属性 p.name
和 p.sayName()
,关系如下图:
知道了原理,就可以自己实现了。也就是说,自己写一个函数 funcNew()
,使得 const p = new Person('orange')
和 const p = funcNew('orange')
得到的 p
完全相同,于是得到了答案中的代码。
答案中最后一行代码如何理解?
前面的例子我们只考虑了 Person
中没有返回值的情况,如有有返回值,new
一个实例将会受到 Person
中返回值的影响。比如说:
/**
* --- Person 中 return 一个对象,p 为该对象 ---
*/
function Person(name) {
this.name = name;
return {age: 35}
}
Person.prototype.sayName = function() {
console.log(this.name);
}
const p = new Person('orange')
console.log(p) // { age: 35 }
console.log(p.name) // undefined
p.sayName(); // TypeError: p.sayName is not a function
/**
* --- Person 返回非对象,return 不影响结果 ---
*/
function Person(name) {
this.name = name;
return 'free'
}
Person.prototype.sayName = function() {
console.log(this.name);
}
const p = new Person('orange')
console.log(p) // Person { name: 'orange' }
console.log(p.name) // orange
p.sayName(); // orange
上面的例子中,如果返回了一个对象,我们需要返回该对象;如果不是对象,则 return
没用,正常处理。
如何自己实现一个instanceof
答案:
/*
* --- 手动实现 instanceof ---
*/
function newInstanceOf (leftValue, rightValue) {
if (typeof leftValue !== 'object' || rightValue == null) {
return false;
}
let rightProto = rightValue.prototype;
leftValue = leftValue.__proto__;
while (true) {
if (leftValue === null) return false;
if (leftValue === rightProto) return true;
leftValue = leftValue.__proto__;
}
}
/*
* --- 验证 ---
*/
const a = [];
const b = {};
function Foo () {}
var c = new Foo()
function Child () {}
function Father() {}
Child.prototype = new Father()
var d = new Child()
console.log(newInstanceOf(a, Array)) // true
console.log(newInstanceOf(b, Object)) // true
console.log(newInstanceOf(b, Array)) // false
console.log(newInstanceOf(a, Object)) // true
console.log(newInstanceOf(c, Foo)) // true
console.log(newInstanceOf(d, Child)) // true
console.log(newInstanceOf(d, Father)) // true
console.log(newInstanceOf(123, Object)) // false
console.log(123 instanceof Object) // false
解读:
这个问题既考察了 instanceof
的原理,又考察了原型链,还考察了代码能力,是一个好问题。
在实现代码中,我们判断 leftValue
是否为 rightValue
的实例,思想是在 leftValue
的原型链上,即 leftValue.__proto__
上寻找是否存在 rightValue.prototype
。原理图如下:
这需要我们熟练掌握原型链的相关知识。
如何用ajax
原生实现一个post
请求
答案:
function ajax_post(url, data) {
// 1. 异步对象 ajax
var ajax = new XMLHttpRequest();
// 2. url 方法
ajax.open('post', url);
// 3. 设置请求报文
ajax.setRequestHeader('Content-type', 'text/plain');
// 4. 发送
if (data) {
ajax.send(data);
} else {
ajax.send();
}
// 5. 注册事件
ajax.onreadystatechange = function () {
if (ajax.readyState === 4 && ajax.status === 200) {
console.log(ajax.respenseText);
}
}
}
上述代码中,ReadyState
每个值的含义
答案:
DOM题目
假设一个 ul
下有一万个 li
,li
的 innerHTML
是从 0
到 9999
,当点击某个 li
时输出该 li
代表的值,如何实现
答案:
采用事件委托:
<ul id="ul">
<li>0</li>
<li>1</li>
<li>2</li>
...
<li>9999</li>
</ul>
window.onload = function () {
var uli = document.getElementById("ul");
uli.onclick = function(event) {
alert(event.target.innerText);
}
}
解读:
首先,我们当然不可能为每一个 li
标签手动添加一个 click
事件(容易累死);其次,我们可能会想到使用 for
循环遍历每个元素,然后为其添加 click
事件,但这样会频繁操作 DOM,降低性能,卡到爆炸。
而事件委托意义就在于此:减少 DOM 操作,从而减少浏览器的重绘与重排次数,提升性能。
事件委托的原理是,将 li
上监听的 click
事件委托到 ul
上。这里运用到了 事件冒泡 的机制,即 onclick
事件以 li -> ul -> body -> html -> document
的冒泡顺序逐步传递。
所以,我们可以选择在其中的 ul
上监听 click
事件,从而实现事件委托。
如何创建 100000 个
<li>
呢?总不能复制粘贴 100000 次吧?
创建 100000个 <li>
标签,思路是将 0∼9999
保存在数组中,然后转化为字符串 "<li>0</li><li>1</li>...<li>9999</li>"
,最后将他们作为 ul
标签的 innerHTML
即可。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<script src="create100000li.js"></script>
<body>
<ul>
</ul>
</body>
</html>
/* --- create100000li.js --- */
window.onload = function() {
var ul = document.getElementsByTagName("ul");
var arr = [];
for (let i = 0; i < 100000; i++) {
arr.push(i);
}
ul[0].innerHTML = '<li>' + arr.join('</li><li>') + '</li>'
}
有微信小程序课设、毕设需求联系个人QQ:505417246
关注下面微信公众号,可以领取微信小程序、Vue、TypeScript、前端、uni-app、全栈、Nodejs、Python等实战学习资料
最新最全的前端知识总结和项目源码都会第一时间发布到微信公众号,请大家多多关注,谢谢
关注公众号后,回复前端面试题,领取大量前端面试题汇总pdf资料
相关文章
- 一文速览:华为、腾讯、淘宝面试流程+面试技术题深度分析
- 4月4日,每天30秒,昨夜今晨一览无余 //腾讯获杭州首批高级辅助驾驶地图许可//我国移动网络IPv6流量首次突破50%
- uniapp - 最详细 H5 网页接入腾讯地图的完整流程,提供地图显示、IP 属地定位、地理位置名称、获取经纬度等超多功能示例(可一键复制并运行的功能源代码,详细的注释及常见问题汇总)小白直接上手!
- 终于有腾讯大牛把网络编程,TCP/IP 通信协议,HTTP 一次讲清了
- 2016年腾讯产品笔试真题
- Vue3前端项目加载使用腾讯地图
- SwiftUI 内功之整合腾讯地图map实现地图导览卫星路况手绘大头钉合集 在Swift中使用Objective-C类(教程含源码)
- 腾讯大数据平台Oceanus: A one-stop platform for real time stream processing powered by Apache Flink
- 《腾讯iOS测试实践》一一第1章 测试观概述 1.1 引言
- 腾讯定位的使用
- 华为腾讯互掐背后物联网数据的重要性