2024 前端javaScript+ES6

Dog.prototype = Object.create(Animal.prototype);

// 添加子类的方法
Dog.prototype.bark = function() {
console.log(‘Woof!’);
};

// 创建子类实例
var myDog = new Dog(‘Buddy’, ‘Golden Retriever’);
myDog.sayName(); // 输出 “My name is Buddy”
myDog.bark(); // 输出 “Woof!”


我们通过原型链的方式实现了子类 Dog 对父类 Animal 的继承。子类 Dog 继承了父类 Animal 的属性和方法,并且还添加了自己的方法。这样就实现了对象之间的继承关系。


图文解析:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/6e9d0d721ba549e9ae3e4e85963da802.png)


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/32f50065c1b349a4acd09ec4c43584bf.png)


1. 显示原型  
 显示原型就是利用prototype属性查找原型,只是这个是函数类型数据的属性。
2. 隐式原型  
 隐式原型是利用\_\_proto\_\_属性查找原型,这个属性指向当前对象的构造函数的原型对象,这个属性是对象类型数据的属性,所以可以在实例对象上面使用:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/d6bd4f4e26cb4315970a4de8eddad8c6.png)


原型链:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/7c28e75063f34a48bff26c01bfd31ec6.png)  
 如果某个对象查找属性,自己和原型对象上都没有,那就会继续往原型对象的原型对象上去找,这个例子里就是Object.prototype,这里就是查找的终点站了,在这里找不到,就没有更上一层了(null里面啥也没有),直接返回undefined。


可以看出,整个查找过程都是顺着\_\_proto\_\_属性,一步一步往上查找,形成了像链条一样的结构,这个结构,就是原型链。所以,原型链也叫作隐式原型链。


正是因为这个原因,我们在创建对象、数组、函数等等数据的时候,都自带一些属性和方法,这些属性和方法是在它们的原型上面保存着,所以它们自创建起就可以直接使用那些属性和方法。


[原型和原型链详细深度讲解,好文章]( )


#### 4、遍历对象中的属性


在 JavaScript 中,可以使用不同的方法来遍历一个对象的属性。以下是几种常见的遍历对象属性的方法:  
 **for…in循环**:使用for…in循环可以遍历对象的所有可枚举属性,并访问每个属性。



const obj1 = {
name: “qq”,
age: “12”,
school: “fudan”,
};
// for in循环
for (let key in obj1) {
if (obj1.hasOwnProperty(key)) {
// 为了避免遍历到原型链上的属性,通常会在循环体内加上 hasOwnProperty 方法的判断。
console.log(key + “:” + obj1[key]); // name: 11, age: 12, school: fudan
}
}


**Object.getOwnPropertyNames()**:使用Object.getOwnPropertyNames()方法可以获取对象的所有属性名,并返回一个包含属性名的数组。通过遍历这个数组,可以访问对象的属性。



// Object.getOwnPropertyNames() 方法:
Object.getOwnPropertyNames(obj1).forEach((key) => {
console.log(key + “:” + obj1[key]); // name: 11, age: 12, school: fudan
});
console.log( " Object.getOwnPropertyNames(obj1)", Object.getOwnPropertyNames(obj1)); // [‘name’, ‘age’, ‘school’]


**Object.keys() 方法:**  
 Object.keys() 方法会返回一个包含对象自身的所有可枚举属性的数组,然后可以使用 forEach 方法遍历这个数组。



// object.kyes()方法
Object.keys(obj1).forEach((key) => {
console.log(key + “:” + obj1[key]); // name: 11, age: 12, school: fudan
});
console.log(“Object.keys(obj1)”, Object.keys(obj1)); // [‘name’, ‘age’, ‘school’]


**Object.entries() ES8+**  
 方法会返回一个包含对象自身的所有可枚举属性键值对的数组,然后可以使用 forEach 方法遍历这个数组。



// Object.entries() 方法(ES8+):
Object.entries(obj1).forEach(([key, value]) => {
console.log(key + ": " + value); // Object.entries() 方法会返回一个包含对象自身的所有可枚举属性键值对的数组,然后可以使用 forEach 方法遍历这个数组。
});
console.log(’ Object.entries(obj1)', Object.entries(obj1)) // [[“name”, “qq”],[“age”, “12”],[“school”, “fudan”]]


#### 5、判断一个变量是否为数组


在 JavaScript 中,有几种方法可以判断一个变量是否为数组。以下是常用的几种方法:


**Array.isArray() 方法:**  
 使用 Array.isArray() 方法是最可靠和推荐的方法来判断一个变量是否为数组。



const arr = [1, 2, 3];
console.log(Array.isArray(arr)); // true
Array.isArray() 方法会返回 true 如果传入的参数是一个数组,否则返回 false。


**instanceof 操作符:**  
 使用 instanceof 操作符也可以判断一个变量是否为数组,但不如 Array.isArray() 方法准确。



const arr = [1, 2, 3];
console.log(arr instanceof Array); // true
instanceof 操作符检查原型链,如果变量是指定类型的实例,则返回 true,否则返回 false。


**Object.prototype.toString.call() 方法:**



const arr = [1, 2, 3];
console.log(Object.prototype.toString.call(arr) === ‘[object Array]’); // true


这种方法通过调用 Object.prototype.toString 方法并传入要检查的变量,然后比较返回的字符串是否为 [object Array] 来判断变量是否为数组。


以上是几种常用的方法来判断一个变量是否为数组。在实际使用中,建议优先使用 Array.isArray() 方法进行判断,因为它更直观和可靠


#### 6、常用数组方法有哪些?



push():向数组末尾添加一个或多个元素,并返回新的长度。
pop():删除并返回数组的最后一个元素。
shift():删除并返回数组的第一个元素,同时将所有其他元素下标减 1。
unshift():向数组的开头添加一个或多个元素,并返回新的长度。
concat():用于合并两个或多个数组,不会修改现有数组,而是返回一个新数组。
slice():从已有的数组中返回选定的元素。
splice():向/从数组中添加/删除项目,然后返回被删除的项目。
indexOf():返回数组中某个元素第一次出现的索引,如果不存在则返回 -1。
lastIndexOf():返回数组中某个元素最后一次出现的索引,如果不存在则返回 -1。
forEach():为数组中的每个元素执行提供的函数。
map():创建一个新数组,其结果是该数组中的每个元素调用一个提供的函数后返回的值。
filter():创建一个新数组,包含通过所提供函数实现的测试的所有元素。
reduce():对数组中的每个元素执行一个提供的函数,将其结果汇总为单个返回值。
find():返回数组中满足提供的测试函数的第一个元素的值。
findIndex():返回数组中满足提供的测试函数的第一个元素的索引。
some():返回数组中是否至少有一个元素通过了所提供函数的测试。
every():返回数组中的所有元素是否都通过了所提供函数的测试。


#### 7、 遍历数组的方法


\*\*for 循环:\*\*使用传统的 for 循环可以遍历数组,通过索引访问数组元素。



const arr = [1, 2, 3];
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}


**forEach() 方法**:forEach() 方法是数组提供的一种遍历方法,它接受一个回调函数作为参数,在数组的每个元素上执行该回调函数。



const arr = [1, 2, 3];
arr.forEach((element) => {
console.log(element);
});


**for…of 循环**:for…of 循环是 ES6 引入的新语法,它可以用来遍历可迭代对象,包括数组。



const arr = [1, 2, 3];
for (const element of arr) {
console.log(element);
}


**map() 方法**:map() 方法可以遍历数组,并将每个元素传递给回调函数进行处理,返回一个新的数组。



const arr = [1, 2, 3];
const newArr = arr.map((element) => {
return element * 2;
});
console.log(newArr);


**filter() 方法**:filter() 方法可以遍历数组,并根据回调函数的返回值筛选出满足条件的元素,返回一个新的数组。



const arr = [1, 2, 3, 4, 5];
const filteredArr = arr.filter((element) => {
return element % 2 === 0;
});
console.log(filteredArr);


#### 8、ajax请求的几种方法?


XMLHttpRequest对象:XMLHttpRequest是原生的JavaScript对象,它提供了一种在后台与服务器进行数据交换的方法。通过创建一个XMLHttpRequest对象,可以发送异步请求并接收服务器返回的数据。


Fetch API:Fetch API是一种现代的Web API,它提供了一种更简洁和强大的方式来进行网络请求。它使用Promise对象来处理异步操作,并提供了更灵活的请求和响应处理方式。


jQuery.ajax()方法:如果你使用jQuery库,可以使用其提供的ajax()方法来发送异步请求。这个方法封装了XMLHttpRequest对象,并提供了简化的语法和更高级的功能,如自动处理数据格式、跨域请求等。


Axios库:Axios是一个流行的第三方库,用于发送HTTP请求。它提供了简单易用的API,并支持Promise对象和拦截器等功能。Axios可以在浏览器和Node.js环境中使用。


**axios请求**  
 Axios 是一个基于 Promise 的 HTTP 客户端,可以在浏览器和 Node.js 中使用。


1)首先,需要在项目中安装axios。可以使用npm或者yarn进行安装。



npm install axios


2)在需要发送请求的文件中,引入axios模块。



const axios = require(‘axios’);
// 或者在浏览器中使用 script 标签引入 Axios,无需导入


3)使用axios的方法发送请求,常见的方法有get、post、put、delete等。



// get 请求
axios.get(url)
.then((response) => {
// 请求成功,处理响应数据
console.log(response.data);
})
.catch((error) => {
// 请求失败,处理错误信息
console.error(error);
});


可以通过配置选项来设置请求的URL、请求头、请求体等信息。  
 使用then方法处理请求成功的响应,使用catch方法处理请求失败的情况。


#### 9、post请求与get请求的区别?


1) 参数传递方式:  
 GET请求:GET请求的参数会暴露在URL中,可以被缓存、浏览器历史记录等获取到。  
 POST请求:参数通过请求体传递,不会暴露在URL中,参数通过请求体以键值对的形式传递。


2)参数长度限制:  
 GET请求:由于参数附加在URL中,URL长度有限制,不同浏览器和服务器对URL长度的限制不同,一般为几千个字符。  
 POST请求:由于参数通过请求体传递,没有URL长度限制,但是服务器和应用程序可能会对请求体的大小进行限制。


3)安全性:  
 GET请求:参数暴露在URL中,容易被拦截、修改或泄露,不适合传递敏感信息。  
 POST请求:参数不暴露在URL中,相对安全,适合传递敏感信息。


4)缓存:  
 GET请求:由于参数暴露在URL中,可以被浏览器缓存,下次相同的请求可以直接使用缓存结果,提高性能。  
 POST请求:由于参数不暴露在URL中,不会被浏览器缓存。


5)幂等性:  
 GET请求:对于相同的请求,多次GET请求不会对服务器产生副作用,即不会改变服务器状态。  
 POST请求:对于相同的请求,多次POST请求可能会对服务器产生副作用,即可能改变服务器状态。


关键区别总结:


GET 请求用于获取资源,参数附加在 URL 中,可以被缓存,参数较少且不敏感。  
 POST 请求用于提交数据,参数包含在请求体中,不会被缓存,参数较多或敏感。


#### 10、Promise


在 JavaScript 中,Promise 是一种用于**处理异步操作**的对象,它代表了一个异步操作的最终完成(或失败)及其结果的承诺。使用 Promise 可以更优雅地处理回调地狱(callback hell)和异步代码。


一个 Promise 可以处于以下三种状态之一:


**Pending(进行中**):初始状态,既不是成功状态,也不是失败状态。  
 **Fulfilled(已成功)**:表示操作成功完成。  
 **Rejected(已失败)**:表示操作失败。  
 创建一个 Promise 的基本语法如下:



const myPromise = new Promise((resolve, reject) => {
// 异步操作,例如请求数据、定时器等
if (/* 异步操作成功 */) {
resolve(“Success”); // 调用 resolve 表示 Promise 成功
} else {
reject(“Error”); // 调用 reject 表示 Promise 失败
}
});


Promise 可以通过 then() 方法来处理成功状态和失败状态:



myPromise.then((result) => {
console.log("Promise resolved: " + result); // 处理成功状态
}).catch((error) => {
console.log("Promise rejected: " + error); // 处理失败状态
});


当 Promise 被 resolve(成功)时,会调用 then() 中的回调函数;当 Promise 被 reject(失败)时,会调用 catch() 中的回调函数。


此外,Promise 还支持链式调用,可以通过返回另一个 Promise 实现连续的异步操作:



myPromise.then((result) => {
return doSomethingElse(result);
}).then((newResult) => {
console.log("Chained Promise resolved: " + newResult);
}).catch((error) => {
console.log("Error in promise chain: " + error);
});


通过使用 Promise,可以更清晰地编写和管理异步代码,避免回调地狱,提高代码可读性和可维护性。  
 [Promise难懂?一篇文章让你轻松驾驭]( )


#### 11、async和await用法


**async/await 出现的原因**


Promise 的编程模型依然充斥着大量的 then 方法,虽然解决了回调地狱的问题,但是在语义方面依然存在缺陷,代码中充斥着大量的 then 函数,这就是 async/await 出现的原因。async/await 让代码更少,更简洁


**定义:**  
 async 是异步的意思,await则可以理解为 async wait。所以可以理解async就是用来声明一个异步方法,而 await是用来等待异步方法执行  
 async作为一个关键字放在函数前面,表示该函数是一个异步函数,异步函数意味着该函数的执行不会阻塞后面代码的执行;而 await 用于等待一个异步方法执行完成;  
 await 等待一个 Promise 对象,如果 Promise的状态变成了 resolve 或者 rejcet,那么 async函数会恢复执行。并会阻塞该函数内后面的代码。  
 使用 async/await 可以实现用同步代码的风格来编写异步代码,这是因为 async/await 的基础技术使用了生成器和 Promise,生成器是协程的实现,利用生成器能实现生成器函数的暂停和恢复。  
 为了优化 .then 链而开发出来的。


详细的介绍和代码分析: [理解异步函数async和await的用法]( )


#### 12、宏任务、微任务?宏任务、微任务有哪些?


首先,我们要先了解下 Js 。js 是一种单线程语言,简单的说就是:只有一条通道,那么在任务多的情况下,就会出现拥挤的情况,这种情况下就产生了 ‘多线程’ ,但是这种“多线程”是通过单线程模仿的,也就是假的。那么就产生了同步任务和异步任务。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/312d42a3d4004932af9a277ea4780e41.png)  
 **宏任务**:


1. script (可以理解为外层同步代码)
2. setTimeout/setInterval
3. UI rendering/UI事件
4. postMessage,MessageChannel5. setImmediate,I/O(Node.js)


**微任务:**  
 1… Promise  
 2.process.nextTick(Node.js)  
 5. Object.observe(已废弃;Proxy 对象替代)  
 6. MutaionObserver


**执行顺序:**  
 执行顺序:先执行同步代码,遇到异步宏任务则将异步宏任务放入宏任务队列中,遇到异步微任务则将异步微任务放入微任务队列中,当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行,微任务执行完毕后再将异步宏任务从队列中调入主线程执行,一直循环直至所有任务执行完毕。


这里容易产生一个**错误的**认识:就是微任务先于宏任务执行。实际上是先执行同步任务,异步任务有宏任务和微任务两种,先将宏任务添加到宏任务队列中,将宏任务里面的微任务添加到微任务队列中。所有同步执行完之后执行异步,再将异步微任务从队列中调入主线程执行,微任务执行完毕后再将异步宏任务从队列中调入主线程执行。之后就一直循环…


案例1:



setTimeout(function(){
console.log(‘1’);
});
new Promise(function(resolve){
console.log(‘2’);
resolve();
}).then(function(){
console.log(‘3’);
}).then(function(){
console.log(‘4’)
});
console.log(‘5’);
// 2 5 3 4 1


解析:1.遇到setTimout,异步宏任务,放入宏任务队列中  
 2.遇到new Promise,new Promise在实例化的过程中所执行的代码都是同步进行的,所以输出2  
 3.而Promise.then中注册的回调才是异步执行的,将其放入微任务队列中  
 4.遇到同步任务console.log(‘5’);输出5;主线程中同步任务执行完  
 5.从微任务队列中取出任务到主线程中,输出3、 4,微任务队列为空  
 6.从宏任务队列中取出任务到主线程中,输出1,宏任务队列为空


案例2:



setTimeout(()=>{
new Promise(resolve =>{
resolve();
}).then(()=>{
console.log(‘test’);
});

console.log(4);
});

new Promise(resolve => {
resolve();
console.log(1)
}).then( () => {
console.log(3);
Promise.resolve().then(() => {
console.log(‘before timeout’);
}).then(() => {
Promise.resolve().then(() => {
console.log(‘also before timeout’)
})
})
})
console.log(2);


解析:  
 1.遇到setTimeout,异步宏任务,将() => {console.log(4)}放入宏任务队列中;


2.遇到new Promise,new Promise在实例化的过程中所执行的代码都是同步进行的,所以输出1;


3.而Promise.then中注册的回调才是异步执行的,将其放入微任务队列中  
 4.遇到同步任务console.log(2),输出2;主线程中同步任务执行完  
 5.从微任务队列中取出任务到主线程中,输出3,此微任务中又有微任务,Promise.resolve().then(微任务a).then(微任务b),将其依次放入微任务队列中;  
 6.从微任务队列中取出任务a到主线程中,输出 before timeout;  
 7.从微任务队列中取出任务b到主线程中,任务b又注册了一个微任务c,放入微任务队列中;  
 8.从微任务队列中取出任务c到主线程中,输出 also before timeout;微任务队列为空  
 9.从宏任务队列中取出任务到主线程,此任务中注册了一个微任务d,将其放入微任务队列中,接下来遇到输出4,宏任务队列为空  
 10.从微任务队列中取出任务d到主线程 ,输出test,微任务队列为空


案例3:



console.log(‘1’);

setTimeout(function() {
console.log(‘2’);
process.nextTick(function() {
console.log(‘3’);
})
new Promise(function(resolve) {
console.log(‘4’);
resolve();
}).then(function() {
console.log(‘5’)
})
})
process.nextTick(function() {
console.log(‘6’);
})
new Promise(function(resolve) {
console.log(‘7’);
resolve();
}).then(function() {
console.log(‘8’)
})

setTimeout(function() {
console.log(‘9’);
process.nextTick(function() {
console.log(‘10’);
})
new Promise(function(resolve) {
console.log(‘11’);
resolve();
}).then(function() {
console.log(‘12’)
})
})
// 1 7 6 8 2 4 3 5 9 11 10 12


#### 13、简述 面向对象编程


面向对象编程(Object-Oriented Programming,OOP)是一种程序设计范式,它以对象为中心,将数据和方法封装在对象内部,通过对象之间的交互来实现程序逻辑。面向对象编程强调在程序设计中对现实世界中的对象进行建模,从而使得程序结构更加清晰、易于扩展和维护。


面向对象编程的核心概念包括以下几个方面:


**类和对象:**  
 类(Class)是面向对象编程的基本概念,它是一种抽象数据类型的表示,描述了对象的属性和行为。对象(Object)是类的实例,具体化了类中定义的属性和行为。


**封装:**  
 封装(Encapsulation)是指将数据和对数据的操作封装在一个对象中,对象对外部提供接口来访问和操作数据,同时隐藏了内部细节。这样可以保护数据不受外部直接访问和修改,提高了安全性和可靠性。


**继承:**  
 继承(Inheritance)是一种可以复用已有类的属性和行为的机制,子类可以继承父类的属性和方法,并且可以对其进行扩展或修改。继承可以减少重复代码,提高代码的可维护性和扩展性。


**多态:**  
 多态(Polymorphism)是指同一个方法在不同的对象上可以有不同的实现,通过多态可以实现方法的动态绑定,使得程序更灵活、可扩展性更强。


面向对象编程的优点包括代码重用性高、可维护性好、易于扩展和理解等。它能够更好地反映现实世界中的问题,使得程序设计更加直观和自然。因此,面向对象编程已经成为当前主流的程序设计范式之一,在众多编程语言中得到了广泛的应用。


#### 14、面向对象的特点?


JavaScript中的面向对象编程具有以下特点:


\*\*封装:\*\*通过将数据和操作封装在对象中,实现了数据的隐藏和保护。对象的内部状态和行为对外部是不可见的,只能通过对象提供的接口进行访问和操作。



class Circle {
constructor(radius) {
this.radius = radius;
}

// Getter method to access radius
getRadius() {
return this.radius;
}

// Method to calculate area
calculateArea() {
return Math.PI * this.radius ** 2;
}
}

// Create an instance of Circle
let myCircle = new Circle(5);

// Access radius using getter method
console.log(“Radius:”, myCircle.getRadius());

// Calculate and print area
console.log(“Area:”, myCircle.calculateArea());


\*\*继承:\*\*通过继承机制,一个对象可以从另一个对象继承属性和方法。继承可以减少代码的重复,提高代码的复用性和可维护性。



class Shape {
constructor(color) {
this.color = color;
}

getColor() {
return this.color;
}
}

class Circle extends Shape {
constructor(radius, color) {
super(color);
this.radius = radius;
}

calculateArea() {
return Math.PI * this.radius ** 2;
}
}

// Create an instance of Circle
let myCircle = new Circle(5, “red”);

// Access color using inherited method
console.log(“Color:”, myCircle.getColor());

// Calculate and print area
console.log(“Area:”, myCircle.calculateArea());


\*\*多态:\*\*多态性允许一个对象可以以多种不同的方式工作。同一个方法可以根据不同的对象调用产生不同的行为。这种灵活性使得代码更加可扩展和可变。



class Animal {
speak() {
console.log(“Animal makes a sound”);
}
}

class Dog extends Animal {
speak() {
console.log(“Dog barks”);
}
}

class Cat extends Animal {
speak() {
console.log(“Cat meows”);
}
}

// Create instances of Dog and Cat
let dog = new Dog();
let cat = new Cat();

// Call the speak method for Dog and Cat
dog.speak(); // Output: Dog barks
cat.speak(); // Output: Cat meows


**原型链**:JavaScript中的对象通过原型链来实现继承。每个对象都有一个原型对象,它定义了对象的属性和方法。当访问一个对象的属性或方法时,如果对象本身没有,则会沿着原型链向上查找。


**动态性**:JavaScript是一门动态语言,允许在运行时动态地添加、修改和删除对象的属性和方法。这种灵活性使得对象的结构和行为可以根据需要进行动态调整。


### ES6高频面试题


#### 1、 let, const 和 var


**var**  
 var 是在 ES5 中引入的变量声明关键字。  
 var 声明的变量具有函数作用域,而不是块级作用域。  
 可以重复声明同一个变量,并且不会报错。  
 变量提升(hoisting):var 声明的变量会被提升到其作用域的顶部,在变量声明之前就可以访问该变量,但其值为 undefined。  
 示例:



function example() {
var x = 10;
if (true) {
var x = 20;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)

交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-5HMveCo7-1712859080808)]

[外链图片转存中…(img-Q6Dozqy3-1712859080809)]

[外链图片转存中…(img-54wIUwHj-1712859080810)]

[外链图片转存中…(img-1za1FYSF-1712859080810)]

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)

img
  • 28
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值