赞
踩
题目描述:给你一个对象,统计一下它的层数
const obj = {
a: { b: [1] },
c: { d: { e: { f: 1 } } }
}
console.log(loopGetLevel(obj)) // 4
实现如下:
function loopGetLevel(obj) {
var res = 1;
function computedLevel(obj, level) {
var level = level ? level : 0;
if (typeof obj === ‘object’) {
for (var key in obj) {
if (typeof obj[key] === ‘object’) {
computedLevel(obj[key], level + 1);
} else {
res = level + 1 > res ? level + 1 : res;
}
}
} else {
res = level > res ? level : res;
}
}
computedLevel(obj)
return res
}
题目描述:
const obj = {
a: {
b: 1,
c: 2,
d: {e: 5}
},
b: [1, 3, {a: 2, b: 3}],
c: 3
}
flatten(obj) 结果返回如下
// {
// ‘a.b’: 1,
// ‘a.c’: 2,
// ‘a.d.e’: 5,
// ‘b[0]’: 1,
// ‘b[1]’: 3,
// ‘b[2].a’: 2,
// ‘b[2].b’: 3
// c: 3
// }
实现如下:
const isObject = (val) => typeof val === “object” && val !== null
function flatten(obj) {
if (!isObject(obj)) return
const res = {}
const dfs = (cur, prefix) => {
if (isObject(cur)) {
if (Array.isArray(cur)) {
cur.forEach((item, index) => {
dfs(item, ${prefix}[${index}]
)
})
} else {
for(let key in cur) {
dfs(cur[key], ${prefix}${prefix ? '.' : ''}${key}
)
}
}
} else {
res[prefix] = cur
}
}
dfs(obj, ‘’)
return res
}
// 测试
console.log(flatten(obj))
题目描述:
实现(a == 1 && a == 2 && a == 3)为true
// 第一种方法
var a = {
i: 1,
toString: function () {
return a.i++;
}
}
console.log(a == 1 && a == 2 && a == 3) // true
// 第二种方法
var a = [1, 2, 3];
a.join = a.shift;
console.log(a == 1 && a == 2 && a == 3); // true
// 第三种方法
var val = 0;
Object.defineProperty(window, ‘a’, {
get: function () {
return ++val;
}
});
console.log(a == 1 && a == 2 && a == 3) // true
题目描述:JS 实现一个带并发限制的异步调度器 Scheduler,保证同时运行的任务最多有两个
addTask(1000,“1”);
addTask(500,“2”);
addTask(300,“3”);
addTask(400,“4”);
的输出顺序是:2 3 1 4
整个的完整执行流程:
一开始1、2两个任务开始执行
500ms时,2任务执行完毕,输出2,任务3开始执行
800ms时,3任务执行完毕,输出3,任务4开始执行
1000ms时,1任务执行完毕,输出1,此时只剩下4任务在执行
1200ms时,4任务执行完毕,输出4
实现如下:
class Scheduler {
constructor(limit) {
this.queue = []
this.limit = limit
this.count = 0
}
add(time, order) {
const promiseCreator = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(order)
resolve()
}, time)
})
}
this.queue.push(promiseCreator)
}
taskStart() {
for(let i = 0; i < this.limit; i++) {
this.request()
}
}
request() {
if (!this.queue.length || this.count >= this.limit) return
this.count++
this.queue.shift()().then(() => {
this.count–
this.request()
})
}
}
// 测试
const scheduler = new Scheduler(2);
const addTask = (time, order) => {
scheduler.add(time, order);
};
addTask(1000, “1”);
addTask(500, “2”);
addTask(300, “3”);
addTask(400, “4”);
scheduler.taskStart();
题目描述:
实现一个LazyMan,可以按照以下方式调用:
LazyMan(“Hank”)输出:
Hi! This is Hank!
LazyMan(“Hank”).sleep(10).eat(“dinner”)输出
Hi! This is Hank!
//等待10秒…
Wake up after 10
Eat dinner~
LazyMan(“Hank”).eat(“dinner”).eat(“supper”)输出
Hi This is Hank!
Eat dinner~
Eat supper~
LazyMan(“Hank”).eat(“supper”).sleepFirst(5)输出
//等待5秒
Wake up after 5
Hi This is Hank!
Eat supper
实现如下:
class _LazyMan {
constructor(name) {
this.tasks = []
const task = () => {
console.log(Hi! This is ${name}
)
this.next()
}
this.tasks.push(task)
setTimeout(() => {
this.next()
}, 0)
}
next() {
const task = this.tasks.shift()
task && task()
}
sleep(time) {
this.sleepWrapper(time, false)
return this
}
sleepFirst(time) {
this.sleepWrapper(time, true)
return this
}
sleepWrapper(time, first) {
const task = () => {
setTimeout(() => {
console.log(Wake up after ${time}
)
this.next()
}, time * 1000)
}
if (first) {
this.tasks.unshift(task)
} else {
this.tasks.push(task)
}
}
eat(food) {
const task = () => {
console.log(Eat ${food}
);
this.next();
};
this.tasks.push(task);
return this;
}
}
// 测试
const lazyMan = (name) => new _LazyMan(name)
lazyMan(‘Hank’).sleep(1).eat(‘dinner’)
lazyMan(‘Hank’).eat(‘dinner’).eat(‘supper’)
lazyMan(‘Hank’).eat(‘supper’).sleepFirst(5)
题目描述:实现一个 add 方法 使计算结果能够满足如下预期:
- add(1)(2)(3)()=6
- add(1,2,3)(4)()=10
function add(…args1) {
let allArgs = […args1]
function fn(…args2) {
if (!args2.length) return fn.toString()
allArgs = […allArgs, …args2]
return fn
}
fn.toString = function () {
return allArgs.reduce((pre, next) => pre + next)
}
return fn
}
// 测试
console.log(add(1)(2)(3)())
console.log(add(1, 2)(3)())
Array篇
定义一个测试数组
const players = [
{ name: ‘科比’, num: 24 },
{ name: ‘詹姆斯’, num: 23 },
{ name: ‘保罗’, num: 3 },
{ name: ‘威少’, num: 0 },
{ name: ‘杜兰特’, num: 35 }
]
参数代表含义
item:遍历项
index:遍历项的索引
arr:数组本身
Array.prototype.sx_forEach = function (callback) {
for (let i = 0; i < this.length; i++) {
callback(this[i], i, this)
}
}
players.sx_forEach((item, index, arr) => {
console.log(item, index)
})
// { name: ‘科比’, num: 24 } 0
// { name: ‘詹姆斯’, num: 23 } 1
// { name: ‘保罗’, num: 3 } 2
// { name: ‘威少’, num: 0 } 3
// { name: ‘杜兰特’, num: 35 } 4
参数代表含义
item:遍历项
index:遍历项的索引
arr:数组本身
Array.prototype.sx_map = function (callback) {
const res = []
for (let i = 0; i < this.length; i++) {
res.push(callback(this[i], i, this))
}
return res
}
console.log(players.sx_map((item, index) => ${item.name}--${item.num}--${index}
))
// [ ‘科比–24–0’, ‘詹姆斯–23–1’, ‘保罗–3–2’, ‘威少–0–3’, ‘杜兰特–35–4’ ]
参数代表含义
item:遍历项
index:遍历项的索引
arr:数组本身
Array.prototype.sx_filter = function (callback) {
const res = []
for (let i = 0; i < this.length; i++) {
callback(this[i], i, this) && res.push(this[i])
}
return res
}
console.log(players.sx_filter(item => item.num >= 23))
// [
// { name: ‘科比’, num: 24 },
// { name: ‘詹姆斯’, num: 23 },
// { name: ‘杜兰特’, num: 35 }
// ]
参数代表含义
item:遍历项
index:遍历项的索引
arr:数组本身
Array.prototype.sx_every = function (callback) {
let flag = true
for (let i = 0; i < this.length; i++) {
flag = callback(this[i], i, this)
if (!flag) break
}
return flag
}
console.log(players.sx_every(item => item.num >= 23)) // false
console.log(players.sx_every(item => item.num >= 0)) // true
参数代表含义
item:遍历项
index:遍历项的索引
arr:数组本身
Array.prototype.sx_some = function (callback) {
let flag = false
for (let i = 0; i < this.length; i++) {
flag = callback(this[i], i, this)
if (flag) break
}
return flag
}
console.log(players.sx_some(item => item.num >= 23)) // true
console.log(players.sx_some(item => item.num >= 50)) // false
参数代表含义
pre:前一项
next:下一项
index:当前索引
arr:数组本身
Array.prototype.sx_reduce = function (callback, …args) {
let start = 0, pre
if (args.length) {
pre = args[0]
} else {
pre = this[0]
start = 1
}
for (let i = start; i < this.length; i++) {
pre = callback(pre, this[i], i, this)
}
return pre
}
// 计算所有num相加
const sum = players.sx_reduce((pre, next) => {
return pre + next.num
}, 0)
console.log(sum) // 85
参数代表含义
item:遍历项
index:遍历项的索引
arr:数组本身
Array.prototype.sx_findIndex = function (callback) {
for (let i = 0; i < this.length; i++) {
if (callback(this[i], i, this)) {
return i
}
}
return -1
}
console.log(players.sx_findIndex(item => item.name === ‘科比’)) // 0
console.log(players.sx_findIndex(item => item.name === ‘安东尼’)) // -1
参数代表含义
item:遍历项
index:遍历项的索引
arr:数组本身
Array.prototype.sx_find = function (callback) {
for (let i = 0; i < this.length; i++) {
if (callback(this[i], i, this)) {
return this[i]
}
}
return undefined
}
console.log(players.sx_find(item => item.name === ‘科比’)) // { name: ‘科比’, num: 24 }
console.log(players.sx_find(item => item.name === ‘安东尼’)) // undefined
用处:填充数组
参数代表含义
initValue:填充的值
start:开始填充索引,默认0
end:结束填充索引,默认length
Array.prototype.sx_fill = function (value, start = 0, end) {
end = end || this.length
for (let i = start; i < end; i++) {
this[i] = value
}
return this
}
console.log(players.sx_fill(‘林三心’, 1, 3))
// [
// { name: ‘科比’, num: 24 },
// ‘林三心’,
// ‘林三心’,
// ‘林三心’,
// { name: ‘杜兰特’, num: 35 }
// ]
用处:查找元素,查到返回true
,反之返回false
,可查找NaN
Array.prototype.sx_includes = function (value, start = 0) {
if (start < 0) start = this.length + start
const isNaN = Number.isNaN(value)
for (let i = start; i < this.length; i++) {
if (this[i] === value || (isNaN && Number.isNaN(this[i])) {
return true
}
}
return false
}
console.log([1, 2, 3].sx_includes(2)) // true
console.log([1, 2, 3, NaN].sx_includes(NaN)) // true
console.log([1, 2, 3].sx_includes(1, 1)) // false
用处:将数组用分隔符拼成字符串,分隔符默认为,
Array.prototype.sx_join = function (s = ‘,’) {
let str = ‘’
for(let i = 0; i < this.length; i++) {
str = i === 0 ? ${str}${this[i]}
: ${str}${s}${this[i]}
}
return str
}
console.log([1, 2, 3].sx_join()) // 1,2,3
console.log([1, 2, 3].sx_join('')) // 12*3
Array.prototype.sx_flat = function (num = Infinity) {
let arr = this
let i = 0
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(…arr)
i++
if (i >= num) break
}
return arr
}
const testArr = [1, [2, 3, [4, 5]], [8, 9]]
console.log(testArr.sx_flat(1))
// [1, 2, 3, 4, 5, 8, 9]
难点
Array.prototype.sx_splice = function (start, length, …values) {
if (length === 0) return []
length = start + length > this.length - 1 ? this.length - start : length
console.log(length)
const res = [], tempArr = […this]
for (let i = start; i < start + values.length; i++) {
this[i] = values[i - start]
}
this.length = start + values.length
if (values.length < length) {
const cha = length - values.length
console.log(cha)
for (let i = start + values.length; i < tempArr.length; i++) {
this[i] = tempArr[i + cha]
}
this.length = this.length - cha
}
if (values.length > length) {
for (let i = start + length; i < tempArr.length; i++) {
this.push(tempArr[i])
}
}
for (let i = start; i < start + length; i++) {
res.push(tempArr[i])
}
return res
}
Object篇
定义一个测试对象
const obj = {
name: ‘林三心’,
age: 22,
gender: ‘男’
}
用处:将对象转成键值对数组
Object.prototype.sx_entries = function (obj) {
const res = []
for (let key in obj) {
obj.hasOwnProperty(key) && res.push([key, obj[key]])
}
return res
}
console.log(Object.sx_entries(obj))
// [ [ ‘name’, ‘林三心’ ], [ ‘age’, 22 ], [ ‘gender’, ‘男’ ] ]
用处:跟entries
相反,将键值对数组转成对象
Object.prototype.sx_fromEntries = function (arr) {
const obj = {}
for (let i = 0; i < arr.length; i++) {
const [key, value] = arr[i]
obj[key] = value
}
return obj
}
console.log(Object.sx_fromEntries([[‘name’, ‘林三心’], [‘age’, 22], [‘gender’, ‘男’]]))
// { name: ‘林三心’, age: 22, gender: ‘男’ }
用处:将对象的key转成一个数组合集
Object.prototype.sx_keys = function (obj) {
const keys = []
for (let key in obj) {
obj.hasOwnProperty(key) && res.push(key)
}
return keys
}
console.log(Object.keys(obj))
// [ ‘name’, ‘age’, ‘gender’ ]
用处:将对象的所有值转成数组合集
Object.prototype.sx_values = function (obj) {
const values = []
for (let key in obj) {
obj.hasOwnProperty(key) && values.push(obj[key])
}
return values
}
console.log(Object.sx_values(obj))
// [ ‘林三心’, 22, ‘男’ ]
用处:A instanceOf B,判断A是否经过B的原型链
function instanceOf(father, child) {
const fp = father.prototype
var cp = child.proto
while (cp) {
if (cp === fp) {
return true
}
cp = cp.proto
}
return false
}
function Person(name) {
this.name = name
}
const sx = new Person(‘林三心’)
console.log(instanceOf(Person, sx)) // true
console.log(instanceOf(Person, sx2)) // false
用处:Object.is(a, b),判断a是否等于b
Object.prototype.sx_is = function (x, y) {
if (x === y) {
// 防止 -0 和 +0
return x !== 0 || 1 / x === 1 / y
}
// 防止NaN
return x !== x && y !== y
}
const a = { name: ‘林三心’ }
const b = a
const c = { name: ‘林三心’ }
console.log(Object.sx_is(a, b)) // true
console.log(Object.sx_is(a, c)) // false
难点
assign接收多个对象,并将多个对象合成一个对象
这些对象如果有重名属性,以后来的对象属性值为准
assign返回一个对象,这个对象 === 第一个对象
Object.prototype.sx_assign = function (target, …args) {
if (target === null || target === undefined) {
throw new TypeError(‘Cannot convert undefined or null to object’)
}
target = Object(target)
for (let nextObj of args) {
for (let key in nextObj) {
nextObj.hasOwnProperty(key) && (target[key] = nextObj[key])
}
}
return target
}
const testa = { name: ‘林三心’ }
const testb = { name: ‘sunshine_lin’, age: 22 }
const testc = { age: 18, gender: ‘男’ }
const testd = Object.sx_assign(testa, testb, testc)
console.log(testd) // { name: ‘sunshine_lin’, age: 18, gender: ‘男’ }
console.log(testa === testd) // true
Function篇
Function.prototype.sx_call = function (obj, …args) {
obj = obj || window
// Symbol是唯一的,防止重名key
const fn = Symbol()
obj[fn] = this
// 执行,返回执行值
return objfn
}
const testobj = {
name: ‘林三心’,
testFn(age) {
console.log(${this.name}${age}岁了
)
}
}
const testobj2 = {
name: ‘sunshine_lin’
}
testobj.testFn.sx_call(testobj2, 22) // sunshine_lin22岁了
Function.prototype.sx_apply = function (obj, args) {
obj = obj || window
// Symbol是唯一的,防止重名key
const fn = Symbol()
obj[fn] = this
// 执行,返回执行值
return objfn
}
const testobj = {
name: ‘林三心’,
testFn(age) {
console.log(${this.name}${age}岁了
)
}
}
const testobj2 = {
name: ‘sunshine_lin’
}
testobj.testFn.sx_apply(testobj2, [22]) // sunshine_lin22岁了
难点:
bind是返回一个函数,而不是执行结果
bind返回的函数,拿来当做构造函数,该怎么处理
Function.prototype.sx_bind = function (obj, …args) {
obj = obj || window
// Symbol是唯一的,防止重名key
const fn = Symbol()
obj[fn] = this
const _this = this
const res = function (…innerArgs) {
console.log(this, _this)
if (this instanceof _this) {
this[fn] = _this
this[fn](…[…args, …innerArgs])
delete this[fn]
} else {
obj[fn](…[…args, …innerArgs])
delete obj[fn]
}
}
res.prototype = Object.create(this.prototype)
return res
}
String篇
参数代表含义
start:开始截取的字符索引(包含此字符)
end:结束截取的字符索引(不包含此字符)
注意点
start > end:返回空字符串
start < 0:start = 数组长度 + start
String.prototype.sx_slice = function (start = 0, end) {
start = start < 0 ? this.length + start : start
end = !end && end !== 0 ? this.length : end
if (start >= end) return ‘’
let str = ‘’
for (let i = start; i < end; i++) {
str += this[i]
}
return str
}
console.log(str.sx_slice(2)) // nshine_lin
console.log(str.sx_slice(-2)) // in
console.log(str.sx_slice(-9, 10)) // shine_l
console.log(str.sx_slice(5, 1)) // ‘’
参数代表含义
start:开始截取的字符索引(包含此字符)
length:截取的长度
注意点
start < 0:start = 数组长度 + start
length超出所能截取范围,需要做处理
length < 0:返回空字符串
String.prototype.sx_substr = function (start = 0, length) {
if (length < 0) return ‘’
start = start < 0 ? this.length + start : start
length = (!length && length !== 0) || length > this.length - start ? this.length : start + length
let str = ‘’
for (let i = start; i < length; i++) {
str += this[i]
}
return str
}
console.log(str.sx_substr(3)) // shine_lin
console.log(str.sx_substr(3, 3)) // shi
console.log(str.sx_substr(5, 300)) // ine_lin
功能与slice
大致相同
区别之处
String.prototype.sx_sunstring = function (start = 0, end) {
start = start < 0 ? this.length + start : start
end = !end && end !== 0 ? this.length : end
if (start >= end) [start, end] = [end, start]
let str = ‘’
for (let i = start; i < end; i++) {
str += this[i]
}
return str
}
console.log(str.sx_sunstring(2)) // nshine_lin
console.log(str.sx_sunstring(-2)) // in
console.log(str.sx_sunstring(-9, 10)) // shine_l
console.log(str.sx_sunstring(5, 1)) // unsh
Promise篇
接收一个Promise数组,数组中如有非Promise项,则此项当做成功
如果所有Promise都成功,则返回成功结果数组
如果有一个Promise失败,则返回这个失败结果
function all(promises) {
const result = []
let count = 0
return new MyPromise((resolve, reject) => {
const addData = (index, value) => {
result[index] = value
count++
if (count === promises.length) resolve(result)
}
promises.forEach((promise, index) => {
if (promise instanceof MyPromise) {
promise.then(res => {
addData(index, res)
}, err => reject(err))
} else {
addData(index, promise)
}
})
})
}
接收一个Promise数组,数组中如有非Promise项,则此项当做成功
哪个Promise最快得到结果,就返回那个结果,无论成功失败
function race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
if (promise instanceof MyPromise) {
promise.then(res => {
resolve(res)
}, err => {
reject(err)
})
} else {
resolve(promise)
}
})
})
}
接收一个Promise数组,数组中如有非Promise项,则此项当做成功
把每一个Promise的结果,集合成数组,返回
function allSettled(promises) {
return new Promise((resolve, reject) => {
const res = []
let count = 0
const addData = (status, value, i) => {
res[i] = {
status,
value
}
count++
if (count === promises.length) {
resolve(res)
}
}
promises.forEach((promise, i) => {
if (promise instanceof MyPromise) {
promise.then(res => {
addData(‘fulfilled’, res, i)
}, err => {
addData(‘rejected’, err, i)
})
} else {
addData(‘fulfilled’, promise, i)
}
})
})
}
any与all相反
接收一个Promise数组,数组中如有非Promise项,则此项当做成功
如果有一个Promise成功,则返回这个成功结果
如果所有Promise都失败,则报错
function any(promises) {
return new Promise((resolve, reject) => {
let count = 0
promises.forEach((promise) => {
promise.then(val => {
resolve(val)
}, err => {
count++
if (count === promises.length) {
reject(new AggregateError(‘All promises were rejected’))
}
})
})
})
}
}
接收一个回调函数,但无参数接收
无论成功失败状态,都会执行finally
Promise.prototype.finally = function(callback) {
return this.then(res => {
callback()
return res
}, err => {
callback()
throw err
})
}
结语
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)
回顾项目
往往在面试时,面试官根据你简历中的项目由点及面地展开问答,所以请对你做过的最好的项目进行回顾和反思。回顾你做过的工作和项目中最复杂的部分,反思你是如何完成这个最复杂的部分的。
面试官会重点问你最复杂的部分的实现方法和如何优化。重点要思考如何优化,即使你项目中没有对那部分进行优化,你也应该预先思考有什么优化的方案。如果这部分答好了,会给面试官留下很不错的印象。
重点在于基础知识
这里指的基础知识包括:前端基础知识和学科基础知识。
前端基础知识:html/css/js 的核心知识,其中 js 的核心知识尤为重要。比如执行上下文、变量对象/活动对象(VO/AO)、作用域链、this 指向、原型链等。
学科基础知识:数据结构、计算机网络、算法等知识。你可能会想前端不需要算法,那你可能就错了,在大公司面试,面试官同样会看重学生这些学科基础知识。
你可能发现了我没有提到React/Vue
这些框架的知识,这里得说一说,大公司不会过度的关注这方面框架的知识,他们往往更加考察学生的基础。
这里我的建议是,如果你至少使用或掌握其中一门框架,那是最好的,可以去刷刷相关框架的面试题,这样在面试过程中即使被问到了,也可以回答个 7788。如果你没有使用过框架,那也不需要太担心,把重点放在基础知识和学科基础知识之上,有其余精力的话可以去看看主流框架的核心思想。
ddData(‘rejected’, err, i)
})
} else {
addData(‘fulfilled’, promise, i)
}
})
})
}
any与all相反
接收一个Promise数组,数组中如有非Promise项,则此项当做成功
如果有一个Promise成功,则返回这个成功结果
如果所有Promise都失败,则报错
function any(promises) {
return new Promise((resolve, reject) => {
let count = 0
promises.forEach((promise) => {
promise.then(val => {
resolve(val)
}, err => {
count++
if (count === promises.length) {
reject(new AggregateError(‘All promises were rejected’))
}
})
})
})
}
}
接收一个回调函数,但无参数接收
无论成功失败状态,都会执行finally
Promise.prototype.finally = function(callback) {
return this.then(res => {
callback()
return res
}, err => {
callback()
throw err
})
}
结语
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-3km3jMUr-1711693348842)]
[外链图片转存中…(img-KAVJsx4I-1711693348842)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
[外链图片转存中…(img-DLRc1KYE-1711693348843)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)
回顾项目
往往在面试时,面试官根据你简历中的项目由点及面地展开问答,所以请对你做过的最好的项目进行回顾和反思。回顾你做过的工作和项目中最复杂的部分,反思你是如何完成这个最复杂的部分的。
面试官会重点问你最复杂的部分的实现方法和如何优化。重点要思考如何优化,即使你项目中没有对那部分进行优化,你也应该预先思考有什么优化的方案。如果这部分答好了,会给面试官留下很不错的印象。
重点在于基础知识
这里指的基础知识包括:前端基础知识和学科基础知识。
前端基础知识:html/css/js 的核心知识,其中 js 的核心知识尤为重要。比如执行上下文、变量对象/活动对象(VO/AO)、作用域链、this 指向、原型链等。
学科基础知识:数据结构、计算机网络、算法等知识。你可能会想前端不需要算法,那你可能就错了,在大公司面试,面试官同样会看重学生这些学科基础知识。
你可能发现了我没有提到React/Vue
这些框架的知识,这里得说一说,大公司不会过度的关注这方面框架的知识,他们往往更加考察学生的基础。
这里我的建议是,如果你至少使用或掌握其中一门框架,那是最好的,可以去刷刷相关框架的面试题,这样在面试过程中即使被问到了,也可以回答个 7788。如果你没有使用过框架,那也不需要太担心,把重点放在基础知识和学科基础知识之上,有其余精力的话可以去看看主流框架的核心思想。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。