Open JayFate opened 2 years ago
JavaScript 的核心 ECMAScript 描述了该语言的语法和基本对象; DOM 描述了处理网页内容的方法和接口; BOM 描述了与浏览器进行交互的方法和接口。
手写 promise、promise.all、promise.retry
后端一次给你10万条数据,如何优雅展示,到底考察我什么? https://juejin.cn/post/7031923575044964389
抖音 PC 版 https://www.douyin.com/
死磕 36 个 JS 手写题 https://juejin.cn/post/6946022649768181774
31.Vue、Vuex、Vue-router、vue-loader面试
class MyPromise {
constructor(fn) {
this.callbacks = [];
this.state = "PENDING";
this.value = null;
fn(this._resolve.bind(this), this._reject.bind(this));
}
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) =>
this._handle({
onFulfilled: onFulfilled || null,
onRejected: onRejected || null,
resolve,
reject,
})
);
}
catch(onRejected) {
return this.then(null, onRejected);
}
_handle(callback) {
if (this.state === "PENDING") {
this.callbacks.push(callback);
return;
}
let cb =
this.state === "FULFILLED" ? callback.onFulfilled : callback.onRejected;
if (!cb) {
cb = this.state === "FULFILLED" ? callback.resolve : callback.reject;
cb(this.value);
return;
}
let ret;
try {
ret = cb(this.value);
cb = this.state === "FULFILLED" ? callback.resolve : callback.reject;
} catch (error) {
ret = error;
cb = callback.reject;
} finally {
cb(ret);
}
}
_resolve(value) {
if (value && (typeof value === "object" || typeof value === "function")) {
let then = value.then;
if (typeof then === "function") {
then.call(value, this._resolve.bind(this), this._reject.bind(this));
return;
}
}
this.state === "FULFILLED";
this.value = value;
this.callbacks.forEach((fn) => this._handle(fn));
}
_reject(error) {
this.state === "REJECTED";
this.value = error;
this.callbacks.forEach((fn) => this._handle(fn));
}
}
const p1 = new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error("fail")), 3000);
});
const p2 = new Promise(function (resolve, reject) {
setTimeout(() => resolve(p1), 1000);
});
p2.then((result) => console.log(result)).catch((error) => console.log(error));
Object.create() 会创建一个 “新” 对象,然后将此对象内部的 [[Prototype]] 关联到你指定的对象(Foo.prototype)。Object.create(null) 创建一个空 [[Prototype]] 链接的对象,这个对象无法进行委托。
function Foo(name) {
this.name = name;
}
Foo.prototype.myName = function () {
return this.name;
}
// 继承属性,通过借用构造函数调用
function Bar(name, label) {
Foo.call(this, name);
this.label = label;
}
// 继承方法,创建备份
Bar.prototype = Object.create(Foo.prototype);
// 必须设置回正确的构造函数,要不然在会发生判断类型出错
Bar.prototype.constructor = Bar;
// 必须在上一步之后
Bar.prototype.myLabel = function () {
return this.label;
}
var a = new Bar("a", "obj a");
a.myName(); // "a"
a.myLabel(); // "obj a"
// demos/01.js
const Koa = require('koa');
const route = require('koa-route');
const serve = require('koa-static');
const app = new Koa();
const about = ctx => {
ctx.response.type = 'html';
ctx.response.body = '<a href="/">Index Page</a>';
};
const main = ctx => {
ctx.response.body = 'Hello World';
};
app.use(serve(path.join(__dirname)));
app.use(route.get('/', main));
app.use(route.get('/about', about));
app.listen(3000);
// node demos/01.js
多个中间件会形成一个栈结构(middle stack),以"先进后出"(first-in-last-out)的顺序执行。
next
函数,把执行权交给下一个中间件。next
函数后面的代码。images
冴羽大佬的这篇博客里,除了 undescore 的部分,你需要全部都能掌握。并且灵活的运用到开发中去。 JavaScript 深入系列、JavaScript 专题系列、ES6 系列
自从 Vue3 横空出世以来,TypeScript 好像突然就火了。这是一件好事,推动前端去学习强类型语言,开发更加严谨。并且第三方包的 ts 类型支持的加入,让我们甚至很多时候都不再需要打开文档对着 api 撸了。
关于 TypeScript 学习,其实几个月前我还对于这门 JavaScript 的超集一窍不通,经过两三个月的静心学习,我能够去理解一些相对复杂的类型了,
可以说 TypeScript 的学习和学一个库或者学一个框架是完全不同的,
一个参数简化的实战,涉及到的高级知识点非常多。
实现一个简化版的 Vuex,同样知识点结合满满。
参考链接:
1.手写js防抖、节流
原理都是利用闭包保存变量。
防抖是任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行,一般用于输入框实时搜索;
节流是规定函数在指定的时间间隔内只执行一次,一般用于scroll事件。
一般不用看 https://segmentfault.com/a/1190000018445196
2.深拷贝和浅拷贝
一般不用看 https://www.cnblogs.com/c2016c/articles/9328725.html
3.数组乱序
4.数组去重:
5.数组flat
数组flat方法是ES6新增的一个特性,可以将多维数组展平为低维数组。如果不传参默认展平一层,传参可以规定展平的层级。
6.数组filter
filter方法经常用,实现起来也比较容易。需要注意的就是filter接收的参数依次为数组当前元素、数组index、整个数组,并返回结果为ture的元素。
7.手写 call、bind、apply
call,bind,apply 的用法及区别
call,bind,apply 都是用于改变函数的 this 的指向,三者第一个参数都是this要指向的对象,如果没有这个参数或参数为undefined或null,则默认 this 指向全局 window 或 global。区别:
核心思路是:
context
扩展一个属性,将原函数指向这个属性context
之外的所有参数全部传递给这个新属性,并将运行结果返回。一些细节:
…args
)可以存储函数多余的参数context
扩展参数扩展新属性使用了Symbol()
数据类型,这样确保不会影响到传入的context
,因为Symbol值一定是独一无二的。…
)将原来是数组的args
转发为逗号分隔一个个参数传入到函数中。为什么能找到this.name
呢?因为方法context[fnSymbol]
中的this
指向的是context
。思路和
call
是一样的只是传参不同方式而已8.手写 eventEmitter
观察者模式是我们工作中经常能接触到的一种设计模式。用过
jquery
的应该对这种设计模式都不陌生。eventEmitter
是node
中的核心,主要方法包括on、emit、off、once
。9.手写继承
10.手写lazyMan
这道题主要考察的是链式调用、任务队列、流程控制等。关键是用手动调用next函数来进行下次事件的调用,类似
express
中间件和vue-router
路由的执行过程。11.函数柯里化(currying)
函数柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术,是高阶函数的一种用法。比如求和函数
add(1,2,3)
, 经过柯里化后变成add(1)(2)(3)
好处
其实
Function.prototype.bind
就是科里化的实现例子12.日期格式化
13.判断电子邮件
参考链接: https://juejin.cn/post/6844903960495538189 https://zhuanlan.zhihu.com/p/69070129