- js 中 this指向问题:
var a = 1;
var b = {
c: function () {
console.log(this.a);
},
d: () => {
console.log(this.a);
}
};
b.d.bind({
a: 2
});
var fun = b.c;
fun();
b.c();
b.d();
第一个func应该是隐式类型绑定,this指向window,
window.func() =>1
第三个箭头函数本身不含有this,绑定的是定义时候的上下文,=> 1;
第二个显式绑定,this指向b,b没有a属性打印undefined
2. 事件轮询机制:
console.log(1)
setTimeout(() => {
console.log(2)
Promise.resolve().then(() => {
console.log(3)
})
})
new Promise((resolve) => {
console.log(4)
setTimeout(() => {
console.log(5)
resolve();
}, 2);
}).then(res => {
console.log(res)
});
// 1 4 2 3 5 undefined
3. 手写promsie.all
function all(promises){
const values = [];
return new Promise((resolve, reject)=> {
promises.forEach((promise, index)=> {
promise.then((value)=>{
//values.push(value);
values[index] = value;
if(values.length == promises.length){
resolve(values);
}
}, reason => {
reject(reason);
})
})
})
}
- // 环形链表判断:
说了快慢指针
// 对象是否有循环引用
// 没搞清楚这个题目:
//line=readline()
//print(line)
//.log('Hello World!');
var a = {
b: {
c: {
d: a
}
}
}
function refCycle(obj){
for(let key in obj){
if(obj[key] == obj){
return true;
} else {
refCycle(obj[key]);
}
}
}
console.log(refCycle(a))
function fn(object) {
// 首先判断 object 是否存在于 map.keys 中
if (Array.from(map.keys()).includes(object)) {
// 如果存在则取出值并返回
return map.get(object);
}
var cloneObj = {};
// 设置 object 为 key,cloneObj 为值
map.set(object, cloneObj);
for (var key in object) {
// 赋予新对象相应的 property
// 通过递归调用来拷贝 property 的值
cloneObj[key] = fn(object[key]);
}
// 返回新对象
return cloneObj;
}
var obj = {};
obj.a = obj;
var map = new Map();
fn(obj);
博客地址: https://blog.youkuaiyun.com/weixin_33738982/article/details/91414115?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522160920791616780271113414%252522%25252C%252522scm%252522%25253A%25252220140713.130102334…%252522%25257D&request_id=160920791616780271113414&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-1-91414115.nonecase&utm_term=%E5%AF%B9%E8%B1%A1%E5%BE%AA%E7%8E%AF%E5%BC%95%E7%94%A8
- 手写一个flat函数
刚开始写了一个版本:
Array.prototype.flat1 = function (arr, n){
let newArr = new Array();
for(let i = 0; i < arr.length; i++)(
if(typeof(arr[i]) !== "object" && n-- > 0){
newArr = newArr.concat(this.flat1(arr[i]));
} else {
newArr.push(arr[i]);
}
)
return newArr;
}
var flat = function(arr, depth){
let res = [],
depthArg = depth || 1,
depthNum = 1,
flatMap = (arr) => {
arr.map((element, index, array) => {
if(Object.prototype.toString(element).slice(8,-1) === "Array") {
if(depthNum < depthArg) {
depthNum++;
flatMap(element);
} else {
res.push(element);
if(index === array.length - 1) depthNum = 0;
}
}
})
};
flatMap(arr);
return res;
};
let arr = [[1], [[2]], [3]];
console.log(flat(arr)); // [1,[2], [3]]
- hash模式和history模式的实现原理
监听hash的改变:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<a href="#/home">首页</a>
<a href="#/about">关于</a>
</div>
<div class="router-view"></div>
<script>
// 获取router-view的dom
const routerViewEl = document.getElementsByClassName("router-view")[0];
// 监听url的改变
window.addEventListener("hashchange", () => {
switch (location.hash) {
case "#/home":
routerViewEl.innerHTML = "首页";
break;
case "#/about":
routerViewEl.innerHTML = "关于";
break;
default:
routerViewEl.innerHTML = "";
}
});
// html5 中的history
// history接口是HTML5新增加的,它有六种模式改变url而不刷新页面
// replaceState: 替换原来的路径
// pushState: 使用新的路径
// popState: 路径的回退
// go: 向前或向后 forward: 向前改变路径 back: 向后改变路径.
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
div id="app">
<a href="/home">首页</a>
<a href="/about">关于</a>
</div>
<div class="router-view"></div>
<script>
// 1. 获取router-view的dom
const routerViewEl = document.getElementsByClassName("router-view")[0];
// 获取所有的a元素,自己来监听a元素的改变
const aEls = document.getElementsByTagName("a");
for (let el of aEls) {
el.addEventListener("click", e => {
e.preventDefault();
const href = el.getAttribute("href");
history.pushState({}, "", href);
urlChange();
// history.go(-1)
// history.back();
// urlChange();
})
}
// 执行返回操作时候,依然来到urlChange
window.addEventListener('popstate', urlChange);
// window.addEventListener("go", urlChange);
// window.addEventListener("pushState", urlChange);
// 监听URL的改变
function urlChange() {
console.log(location.pathname);
switch (location.pathname) {
case "/home":
routerViewEl.innerHTML = "首页";
break;
case "/about":
routerViewEl.innerHTML = "关于";
break;
default:
routerViewEl.innerHTML = "";
}
};
</script>
</body>
</html>
- 实现数组的slice方法:
Array.prototype.slice = function(start, end){
let len = this.length;
let l = start === undefined ? 0 : start < 0 ? Math.max(start + len, 0) : Math.min(start, len);
let r = end === undefined ? len : end < 0 ? Math.max(end + len, 0) : Math.min(end, len);
const res = [];
while(l < r) {
res.push(this[l++]);
}
return res;
}
- 判断数据类型3种方法,实现instaneOf
const instance_of = (left, rigth) => {
const baseType = ['number', 'string', 'boolean', 'undefined', 'symbol'];
const RP = right.prototype;
while(true){
if(left == null) {
return false;
} else if (left == RP) {
return true;
}
left = left.__proto__;
}
}