技术标签: 2024年程序员学习 面试 javascript 开发语言
先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Web前端全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024c (备注前端)
怎么实现 JS 引擎呢?
JS 引擎的构成
一个 JS 引擎由四部分构成:Parser(解析器)、Interperter(解释器)、JIT Compiler(JIT 编译器)、Garbage Collector(垃圾收集器)。
源码经过 Parser 解析成 AST,也就是计算机能处理的对象树的结构,然后用解释器递归的解释每个节点,这就是解释执行的过程。
但是解释执行比较慢,为了优化速度又引入了 JIT 编译器,会把经常执行的热点代码编译成机器码直接执行。
同时,内存是有限制的,要不断的循环清除不再被使用的内存,也就是垃圾回收,这是 GC 做的事情。
如果我们自己实现简单的 JS 引擎,那可以省略掉 JIT 编译器和 GC,这两个分别是优化时间和空间的,不是必须的。
也就是只要实现 Parser 和 Interpreter(解释器)就行:
这就是我们要实现的 JS 引擎的结构。
简易 JS 引擎实现思路分析
Parser 可以是任意的 JS Parser,我们直接用 @babel/parser。
它产生的 AST 可以用 astexplorer.net 可视化的查看:
怎么解释执行呢?
解释 AST 也就是递归解释每个 AST 节点,那具体的 AST 节点又怎么解释呢?
比如这个 {n:1} 的对象表达式,它对应的是 ObjectExpression 节点,它有 ObjectProperty 属性的子节点,子节点有 key、value 属性。
自然可以想到,解释 ObjectExpression 节点就是取出 AST 中的数据构造一个对象返回:
再比如 let a = { n: 1} 这条赋值语句,它对应的是 VariableDeclaration 节点,下面有多个 VariableDeclarator 子节点,这是因为一条声明语句可以声明多个变量,比如 let a = 1, b =1; 而具体的声明 VariableDeclarator 里分别有 id 和 init 部分。
init 部分就是 ObjectExpression,解释它就是构造一个对象返回。那么解释整个声明自然就是在作用域中放一个名字为 id 节点的 value 为名字的变量,值就是 init 节点的解释执行的结果。
Identifier 是标识符的意思,也就是这里的 a。
对象表达式 ObjectExpression 和声明语句 VariableDeclaration 的解释执行就是这样,不难吧。
其他 AST 节点的解释也是这样,递归的解释每个节点,这就是解释执行 JS 代码的实现原理。
知道了该怎么做,那我们来写代码实现下吧:
声明语句的解释执行
我们先实现声明语句的解释执行,后面再实现赋值语句的解释执行:
Parser 使用 babel parser,用它的 parse 方法把源码转成 AST,然后解释执行 AST:
const parser = require(‘@babel/parser’);
function eval() {
const ast = parser.parse(code);
evaluate(ast.program);
}
const scope = new Map();
function evaluate(node) {
}
const code = `
let a = { dong: 111};
let b = { guang: 222};
let c = b;
`
eval(code);
console.log(scope);
我们声明了一个 Map 对象作为全局作用域。
接下来就是实现解释器了,也就是 evaluate 方法。
我们前面分析过了,解释执行就是递归处理每个 AST,每种 AST 的处理方式不同:
const astInterpreters = {
Program(node) {
node.body.forEach(item => {
evaluate(item);
})
},
VariableDeclaration(node) {
},
VariableDeclarator(node) {
},
ObjectExpression(node) {
},
Identifier(node) {
return node.name;
},
NumericLiteral(node) {
return node.value;
}
}
function evaluate(node) {
try {
return astInterpretersnode.type;
} catch(e) {
console.error(‘不支持的节点类型:’, e);
}
}
我们实现了几个简单的 AST 的解释:Program 根节点,它的解释执行就是解释执行 body 的每一条语句。Identifier(标识符) 就是取 name 属性,NumericLiteral(数字字面量)就是取 value 属性。
然后是对象表达式 ObjectExpression 的解释了,这个就是构造一个对象返回:
ObjectExpression(node) {
const obj = {};
node.properties.forEach(prop => {
const key = evaluate(prop.key);
const value = evaluate(prop.value);
obj[key] = value;
});
return obj;
}
也就是取 properties 中的每个节点,拿到 key 和 value 的解释执行结果,设置到对象中,最后把对象返回。
声明语句的解释就是在作用域(我们声明的 Map)中设置下就行:
VariableDeclaration(node) {
node.declarations.forEach((item) => {
evaluate(item);
});
},
VariableDeclarator(node) {
const declareName = evaluate(node.id);
if (scope.get(declareName)) {
throw Error(‘duplicate declare variable:’ + declareName);
} else {
const valueNode = node.init;
let value;
if (valueNode.type === ‘Identifier’) {
value = scope.get(valueNode.name);
} else {
value = evaluate(valueNode);
}
scope.set(declareName, value);
}
},
VariableDeclaration 是声明语句,因为具体的声明可能有多个,所以要循环执行每个声明。
具体的声明 VariableDeclarator 就是在 scope 中设置变量名和它的值。
变量名是 node.id 的执行结果,如果声明过就报错,因为只能声明一次。
否则就取 node.init 的值设置到 scope 中,也就是 scope.set(declarationName, value)。
但是值的处理要注意下,如果是 Identifier 也就是标识符,它其实是一个引用,比如变量 a,那么我们要先从作用域中拿到它的具体值。
这些节点的解释执行逻辑写好了,那么我们就能解释这段代码了:
let a = { dong: 111};
let b = { guang: 222};
let c = b;
声明了 a、b、c 三个变量,a、b 初始值都是对象字面量、c 是引用自 b。
执行之后我们打印下 scope:
执行成功!我们实现了最简单的 JS 引擎!
当然,只是声明还不够,接下来再实现赋值语句的解释:
赋值语句的解释执行
赋值语句的解释也就是解释 AssignmentExpression 节点,用 astexplorer.net 看下它的结构:
它外面怎么还包裹了个 ExpressionStatement 节点呢?
因为表达式不能直接执行,语句才是执行的基本单位,那么表达式包裹一层表达式语句(ExpressionStatement)就可以了。
AssignmentExpression 有 left 和 right 属性,分别是 = 左右部分对应的节点。
如果 right 还是 AssignmentExpression 呢?
那么要继续取 right,知道拿到不是 AssignmentExpression 的节点,这就是要赋值的值。
总的来说,面试官要是考察思路就会从你实际做过的项目入手,考察你实际编码能力,就会让你在电脑敲代码,看你用什么编辑器、插件、编码习惯等。所以我们在回答面试官问题时,有一个清晰的逻辑思路,清楚知道自己在和面试官说项目说技术时的话就好了
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
面试官要是考察思路就会从你实际做过的项目入手,考察你实际编码能力,就会让你在电脑敲代码,看你用什么编辑器、插件、编码习惯等。所以我们在回答面试官问题时,有一个清晰的逻辑思路,清楚知道自己在和面试官说项目说技术时的话就好了
[外链图片转存中…(img-hEVqhF6B-1713085384955)]
[外链图片转存中…(img-ye4uhUUS-1713085384956)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-aVVFeT8H-1713085384956)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
文章浏览阅读3.8k次,点赞9次,收藏28次。直接上一个工作中碰到的问题,另外一个系统开启多线程调用我这边的接口,然后我这边会开启多线程批量查询第三方接口并且返回给调用方。使用的是两三年前别人遗留下来的方法,放到线上后发现确实是可以正常取到结果,但是一旦调用,CPU占用就直接100%(部署环境是win server服务器)。因此查看了下相关的老代码并使用JProfiler查看发现是在某个while循环的时候有问题。具体项目代码就不贴了,类似于下面这段代码。while(flag) {//your code;}这里的flag._main函数使用while(1)循环cpu占用99
文章浏览阅读347次。idea shift f6 快捷键无效_idea shift +f6快捷键不生效
文章浏览阅读135次。Ecmacript 中没有DOM 和 BOM核心模块Node为JavaScript提供了很多服务器级别,这些API绝大多数都被包装到了一个具名和核心模块中了,例如文件操作的 fs 核心模块 ,http服务构建的http 模块 path 路径操作模块 os 操作系统信息模块// 用来获取机器信息的var os = require('os')// 用来操作路径的var path = require('path')// 获取当前机器的 CPU 信息console.log(os.cpus._node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是
文章浏览阅读10w+次,点赞435次,收藏3.4k次。SPSS 22 下载安装过程7.6 方差分析与回归分析的SPSS实现7.6.1 SPSS软件概述1 SPSS版本与安装2 SPSS界面3 SPSS特点4 SPSS数据7.6.2 SPSS与方差分析1 单因素方差分析2 双因素方差分析7.6.3 SPSS与回归分析SPSS回归分析过程牙膏价格问题的回归分析_化工数学模型数据回归软件
文章浏览阅读7.5k次。如何利用hutool工具包实现邮件发送功能呢?1、首先引入hutool依赖<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.19</version></dependency>2、编写邮件发送工具类package com.pc.c..._hutool发送邮件
文章浏览阅读867次,点赞2次,收藏2次。docker安装elasticsearch,elasticsearch-head,kibana,ik分词器安装方式基本有两种,一种是pull的方式,一种是Dockerfile的方式,由于pull的方式pull下来后还需配置许多东西且不便于复用,个人比较喜欢使用Dockerfile的方式所有docker支持的镜像基本都在https://hub.docker.com/docker的官网上能找到合..._docker安装kibana连接elasticsearch并且elasticsearch有密码
文章浏览阅读1.3w次,点赞57次,收藏92次。整理 | 郑丽媛出品 | CSDN(ID:CSDNnews)近年来,随着机器学习的兴起,有一门编程语言逐渐变得火热——Python。得益于其针对机器学习提供了大量开源框架和第三方模块,内置..._beeware
文章浏览阅读7.9k次。//// ViewController.swift// Day_10_Timer//// Created by dongqiangfei on 2018/10/15.// Copyright 2018年 飞飞. All rights reserved.//import UIKitclass ViewController: UIViewController { ..._swift timer 暂停
文章浏览阅读986次,点赞2次,收藏2次。1.硬性等待让当前线程暂停执行,应用场景:代码执行速度太快了,但是UI元素没有立马加载出来,造成两者不同步,这时候就可以让代码等待一下,再去执行找元素的动作线程休眠,强制等待 Thread.sleep(long mills)package com.example.demo;import org.junit.jupiter.api.Test;import org.openqa.selenium.By;import org.openqa.selenium.firefox.Firefox.._元素三大等待
文章浏览阅读3k次,点赞4次,收藏14次。Java软件工程师职位分析_java岗位分析
文章浏览阅读2k次。Java:Unreachable code的解决方法_java unreachable code
文章浏览阅读1w次。1、html中设置标签data-*的值 标题 11111 222222、点击获取当前标签的data-url的值$('dd').on('click', function() { var urlVal = $(this).data('ur_如何根据data-*属性获取对应的标签对象