码字不易,有帮助的同学希望能关注一下我的微信公众号:Code程序人生,感谢!代码自用自取。
部门:QQ音乐
方式:电话面试
JavaScript篇
typeof null
返回什么Object
还是Array
new
instanceof
null
)child
继承了父类的parent
之后,oarent
有一个属性name。这时new
一个子类的实例b
,如果修改了b.name
是否会修改父类上的name
属性ajax
原生实现一个post
请求(XMLHTTPRequest)ReadyState
,解释一下它的每个值代表的含义ajax
如何解决跨域问题JSONP
时服务端返回什么样的数据,如何处理(callback(json拼好))ul
下有一万个 li
,li
的 innerHTML
是从 0
到 9999
,当点击某个 li
时输出该 li
代表的值,如何实现windowOnload
和 DOMready
哪个先触发CSRF
和 XSS
攻击的原理,和解决方式tab
,一个是 a.qq.com
,另一个是黑客的域名,你在黑客的域名下向 a.qq.com
发起了一个请求,请问是否会带上 a
页面的 cookie
答案:
共8种。包括7种基本数据类型:
null
,undefined
string
,number
,boolean
BigInt
,Symbol
object
Object
Array
RegExp
Function
答案:
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,这里使用 () 保证代码运行的优先级,不然会报语法错误
答案:
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 ---
*/
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
每个值的含义假设一个 ul
下有一万个 li
,li
的 innerHTML
是从 0
到 9999
,当点击某个 li
时输出该 li
代表的值,如何实现
答案:
采用事件委托:
<ul id="ul">
<li>0li>
<li>1li>
<li>2li>
...
<li>9999li>
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 个
呢?总不能复制粘贴 100000 次吧?
创建 100000个 标签,思路是将
0∼9999
保存在数组中,然后转化为字符串 "
,最后将他们作为 ul
标签的 innerHTML
即可。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
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 = '' + arr.join('' ) + ''
}
有微信小程序课设、毕设需求联系个人QQ:505417246
关注下面微信公众号,可以领取微信小程序、Vue、TypeScript、前端、uni-app、全栈、Nodejs、Python等实战学习资料
最新最全的前端知识总结和项目源码都会第一时间发布到微信公众号,请大家多多关注,谢谢