ii)对象的本质:无序的键值对集合;键值对当中的值可以是任意数据类型的值
iii)对象就是一个容器,这个容器当中放的是(属性和方法)
3)属性搜索
①在访问对象的某个成员的时候会先在对象中找是否存在
②如果当前对象中没有就在构造函数的原型对象中找
③如果原型对象中没有找到就到原型对象的原型上找
④知道Object的原型对象的原型是null为止
2、Function——
所有函数都是Function的实例
`①本地对象:独立于宿主环境(浏览器)的对象——包括Object、Array、Date、RegExp、 Function、Error、Number、String、Boolean
②内置对象——包括Math、Global(window,在js中就是全局变量),使用的时候不需要 new
③宿主对象——包括自定义对象、DOM、BOM
第一种: new关键字改变this指向
function Fn(){
this.user = “追梦子”;
}
var a = new Fn();
console.log(a.user); //追梦子
用变量a创建了一个Fn的实例(相当于复制了一份Fn到对象a里面),此时仅仅只是创建,并没有执行,而调用这个函数Fn的是对象a,那么this指向的自然是对象a,那么为什么对象a中会有user,因为你已经复制了一份Fn函数到对象a中,用了new关键字就等同于复制了一份第二种: call()
第二种: call()
var a = {
user:“追梦子”,
fn:function(){
console.log(this.user); //追梦子
}
}
var b = a.fn;
b.call(a); //若不用call,则b()执行后this指的是Window对象
把b添加到第一个参数的环境中,简单来说,this就会指向那个对象。
第三种:apply()
var a = {
user:“追梦子”,
fn:function(){
console.log(this.user); //追梦子
}
}
var b = a.fn;
b.apply(a);
第四种:bind()
var a = {
user:“追梦子”,
fn:function(){
console.log(this.user);
}
}
var b = a.fn;
b.bind(a); //代码没有被打印
我们发现代码没有被打印,对,这就是bind和call、apply方法的不同,实际上bind方法返回的是一个修改过后的函数。
- 变量声明
let 与 const:
可以把let看成var,只是它定义的变量被限定在了特定范围内才能使用,而离开这个范围则无效。const则很直观,用来定义常量,即无法被更改值的变量。
for (let i=0;i<2;i++)console.log(i);//输出: 0,1
console.log(i);//输出:undefined,严格模式下会报错
2.类的支持
ES6中添加了对类的支持,引入了class关键字(其实class在JavaScript中一直是保留字,目的就是考虑到可能在以后的新版本中会用到,现在终于派上用场了)。JS本身就是面向对象的,ES6中提供的类实际上只是JS原型模式的包装。现在提供原生的class支持后,对象的创建,继承更加直观了,并且父类方法的调用,实例化,静态方法和构造函数等概念都更加形象化。
//类的定义
class Animal {
//ES6中新型构造器
constructor(name) {
this.name = name;
}
//实例方法
sayName() {
console.log('My name is '+this.name);
}
}
//类的继承
class Programmer extends Animal {
constructor(name) {
//直接调用父类构造器进行初始化
super(name);
}
program() {
console.log(“I’m coding…”);
}
}
//测试我们的类
var animal=new Animal(‘dummy’),
wayou=new Programmer(‘wayou’);
animal.sayName();//输出 ‘My name is dummy’
wayou.sayName();//输出 ‘My name is wayou’
wayou.program();//输出 ‘I’m coding…’
3.字符串模板
字符串模板相对简单易懂些。ES6中允许使用反引号 ` 来创建字符串,此种方法创建的字符串里面可以包含由美元符号加花括号包裹的变量${vraible}。如果你使用过像C#等后端强类型语言的话,对此功能应该不会陌生。
//产生一个随机数
var num=Math.random();
//将这个数字输出到console
console.log(your num is ${num}
);
4.解构:
自动解析数组或对象中的值。比如若一个函数要返回多个值,常规的做法是返回一个对象,将每个值做为这个对象的属性返回。但在ES6中,利用解构这一特性,可以直接返回一个数组,然后数组中的值会自动被解析到对应接收该值的变量中。
var [x,y]=getVal(),//函数返回值的解构
[name,age]=[‘wayou’,‘male’,‘secrect’];//数组解构
function getVal() {
return [ 1, 2 ];
}
console.log(‘x:’+x+‘, y:’+y);//输出:x:1, y:2
console.log(‘name:’+name+‘, age:’+age);//输出: name:wayou, age:secrect
5.Promise:
Promises是处理异步操作的一种模式,之前在很多三方库中有实现,比如jQuery的deferred 对象。当你发起一个异步请求,并绑定了.when(), .done()等事件处理程序时,其实就是在应用promise模式。
//创建promise
var promise = new Promise(function(resolve, reject) {
// 进行一些异步或耗时操作
if ( /*如果成功 */ ) {
resolve(“Stuff worked!”);
} else {
reject(Error(“It broke”));
}
});
//绑定处理程序
promise.then(function(result) {
//promise成功的话会执行这里
console.log(result); // “Stuff worked!”
}, function(err) {
//promise失败会执行这里
console.log(err); // Error: “It broke”
});
ES6提供的解决异步处理方法
有两个优点
1.promise对象的状态不受外界影响
-pending 初始状态
-fulfilled 成功状态
-rejected 失败状态
2.promise的状态一旦改变,就不会再变,状态不可逆,只能由pending变成pending变成fulfilled或者由pending变成rejected
三个缺点
1.无法取消promise,一旦新建它就会立即执行,无法中途取消
2.如果不设置回调函数,promise内部抛出的错误,不会反映到外部
3.当处于pending状态时,无法得知目前进展到哪一个阶段
用法
const promise = new Promise(function(resolve, reject) {
// … some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。同源指的是协议,域名和端口号均相同则属于同源
使用jsonp跨域,因为script标签引入的js是不受同源策略的限制,通过script标签引入一个js或者是一个其他后缀形式(如php,jsp等)的文件,此时文件返回一个JS函数的调用
通过cors跨域,实现cors通信的关键是服务器,只要服务器实现cors接口,就可以跨域
反向代理跨域,反向代理指的是在前端的服务器环境中, 短暂的开启一个后端服务器, 由后端服务器进行数据请求, 然后在将结果返回给前端
模块化的开发方式可以提高代码复用率,方便进行代码的管理。通常一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数。目前流行的js模块化规范有CommonJS、AMD、CMD以及ES6的模块系统
1、AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块
2、CMD推崇就近依赖,只有在用到某个模块的时候再去require
这种区别各有优劣,只是语法上的差距,而且requireJS和SeaJS都支持对方的写法
AMD和CMD最大的区别是对依赖模块的执行时机处理不同,注意不是加载的时机或者方式不同
highcharts http://www.highcharts.com/
jscharts http://www.jscharts.com/
AdminLTE http://adminlte.la998.com/
库和框架都是一种有别于软件、面向程序开发者的产品形式。
库是将代码集合成的一个产品,供程序员调用。面向对象的代码组织形式而成的库也叫
类库。
框架则是为解决一个(一类)问题而开发的产品,框架用户一般只需要使用框架提供的类
或函数,即可实现全部功能。
柯里化(英语:Currying),又称为部分求值,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回一个新的函数的技术,新函数接受余下参数并返回运算结果。
具体内容见 https://juejin.im/entry/58b316d78d6d810058678579
1)意外的全局变量引起的内存泄露
function leak () {
leak=“xxx”; //leak成为一个全局变量,不会被回收 相当于 window.leak = ‘XXX’
}
-
闭包可以维持函数内局部变量,使其得不到释放。
-
没有清理的DOM元素引用
-
被遗忘的定时器或者回调
-
定义局部变量.查找局部变量比全局变量要快。
-
不滥用闭包。
-
合并js文件,减少http请求
-
避免使用for-in循环
-
尽量不用with,eval语句,try-catch的catch子句要谨慎使用
- 闭包经典使用场景一:通过循环给页面上多个dom节点绑定事件
Button0
Button1
Button2
Button3
Button4
for(var i = 0, len = btns.length; i < len; i++) {
(function(i) {
btns[i].onclick = function() {
alert(i);
}
}(i))
}
-
封装变量 闭包可以将一些不希望暴露在全局的变量封装成“私有变量”。
-
闭包使用场景三:延续局部变量的寿命
闭包工具库:???
301 redirect: 301 代表永久性转移(Permanently Moved)
302 redirect: 302 代表暂时性转移(Temporarily Moved )
详细来说,301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取(用户看到的效果就是他输入的地址A瞬间变成了另一个地址B)——这是它们的共同点。他们的不同在于。301表示旧地址A的资源已经被永久地移除(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。
举例:
console.log (a) //由于变量提升,输出undefined
var a
console.log(a) //报错 ReferenceError: a is not defined
let a
ES6规定,let/const 命令会使区块形成封闭的作用域。若在声明之前使用变量,就会报错。
总之,在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。
这在语法上,称为 “暂时性死区”( temporal dead zone,简称 TDZ)。
-
栈(stack):为自动分配的内存空间,他由系统自动释放。存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配,是直接按值存放的,所以可以直接访问。基本的数据类型放在栈中
-
堆(heap):则是动态分配的内存,大小不定也不会自动释放。引用类型(object)是存放在堆内存中的,变量实际上是一个存放在栈内存的指针,这个指针指向堆内存中的地址。每个空间大小不一样,要根据情况进行特定的分配。
- 箭头函数默认不会使用自己的this,而是会和外层的this保持一致,最外层的this就是window对象。在多层对像嵌套里箭头函数里this是和最最外层保持一致的
-
浅拷贝:只复制指向某个对象的指针,而不复制对象本身,新旧对象共享一块内存
-
深拷贝:复制并创建一个一模一样的对象,不共享内存,修改新对象,旧对象保持不变。
41.手写一个promise,采用es5的方面。promise的源码理解
var fn=function(resolve, reject){
console.log(‘begin to execute!’);
var number=Math.random();
if(number<=0.5){
resolve(‘less than 0.5’);
}else{
reject(‘greater than 0.5’);
}
}
var p=new Promise(fn);
p.then(function(data){
console.log('resolve: ', data);
}, function(data){
console.log('reject: ', data);
})
对promise源码的理解:
当我们运行 var p=new Promise(fn) 这条语句的时候,fn函数就已经执行了,然而,p.then这个方法是在后面才定义了resolve和reject,那么为何fn函数能够知道resolve和reject函数是什么呢?换句话说,resolve和reject函数是如何回到过去,出现在先执行的fn函数当中的呢?要解决这个问题,主要运用的就是setTimeout这个方法,来延迟fn当中resolve和reject的执行。我们知道js是单线程+消息队列,必须等主线程代码执行完毕才能开始执行消息队列当中的代码。因此,会首先执行then这个方法,给里面两个参数赋值。
加入状态:pending, resolved, rejected
在Promise规范当中,规定Promise只能从初始pending状态变到resolved或者rejected状态,是单向变化的,也就是说执行了resolve就不会再执行reject,反之亦然。并在必要的地方进行判断,防止重复执行。
function MyPromise(fn) {
this.value;
this.status = ‘pending’;
this.resolveFunc = function() {};
this.rejectFunc = function() {};
fn(this.resolve.bind(this), this.reject.bind(this));
}
MyPromise.prototype.resolve = function(val) {
var self = this;
if (this.status == ‘pending’) { //判断状态
this.status = ‘resolved’;
this.value=val;
setTimeout(function() {
self.resolveFunc(self.value);
}, 0);
}
}
MyPromise.prototype.reject = function(val) { //判断状态
var self = this;
if (this.status == ‘pending’) {
this.status = ‘rejected’;
this.value=val;
setTimeout(function() {
self.rejectFunc(self.value);
}, 0);
}
}
MyPromise.prototype.then = function(resolveFunc, rejectFunc) {
this.resolveFunc = resolveFunc;
this.rejectFunc = rejectFunc;
}
链式调用:
要实现链式调用,then方法的返回值也必须是一个Promise对象,这样才能再次在后面调用then。
-
在函数前有一个关键字
async
,await
关键字只能在使用async
定义的函数中使用。任何一个async
函数都会隐式返回一个promise
,并且promise resolve 的值就是 return 返回的值 -
不能在函数开头使用
await
-
Async 函数的实现最简洁,最符合语义,几乎没有语义不相关的代码。
-
Promise 的写法比回调函数的写法大大改进,但是一眼看上去,代码完全都是 Promise 的 API(
then
、catch
等等),操作本身的语义反而不容易看出来。
- async函数就是generator函数的语法糖
(1) 箭头函数与function定义函数的写法:
//function
function fn(a, b){
return a + b;
}
//arrow function
var foo = (a, b)=>{ return a + b };
(2) this的指向:
使用function定义的函数,this的指向随着调用环境的变化而变化的,而箭头函数中的this指向是固定不变的,一直指向的是定义函数的环境。
(3) 构造函数
function是可以定义构造函数的,而箭头函数是不行的。
(4) 变量提升
由于js的内存机制,function的级别最高,而用箭头函数定义函数的时候,需要var(let const定义的时候更不必说)关键词,而var所定义的变量不能得到变量提升,故箭头函数一定要定义于调用之前!
(1) 由于箭头函数不绑定this, 它会捕获其所在(即定义的位置)上下文的this值, 作为自己的this值
(2)方法的箭头函数this指向全局window对象,而普通函数则指向调用它的对象,箭头函数没有this
因为箭头函数没有自己的this,它的this其实是继承了外层执行环境中的this,且this指向永远不会随在哪里调用、被谁调用而改变,所以箭头函数不能作为构造函数使用,或者说构造函数不能定义成箭头函数,否则用new调用时会报错!
箭头函数没有自己的arguments对象。在箭头函数中访问arguments实际上获得的是外层局部(函数)执行环境中的值。可以在箭头函数中使用rest参数代替arguments对象,来访问箭头函数的参数列表
- 解构赋值,即对某种结构进行解析,然后将解析出来的值赋值给相关的变量,常见的有数组、对象、字符串的解构赋值等
- 数组解构
只要等号两边的模式相同,左边的变量就会被赋予对应的值。
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3
- 对象结构
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
let { bar, foo } = { foo: ‘aaa’, bar: ‘bbb’ };
foo // “aaa”
bar // “bbb”
- 字符串结构
字符串被转换成了一个类似数组的对象
const [a, b, c, d, e] = ‘hello’;
a // “h”
b // “e”
c // “l”
d // “l”
e // “o”
- 负载
- 概念
扩展运算符(spread)是三个点(…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。扩展运算符与正常的函数参数可以结合使用,后面也可以放置表达式,但如果后面是一个空数组,则不产生任何效果。
let arr = [];
arr.push(…[1,2,3,4,5]);
console.log(arr); //[1,2,3,4,5]
console.log(1, …[2, 3, 4], 5) //1 2 3 4 5
console.log(…(1 > 0 ? [‘a’] : [])); //a
console.log([…[], 1]); //[1]
- 应用
1 替代函数的apply方法
由于扩展运算符可以展开数组,所以不再需要apply方法,将数组转为函数的参数了。
// ES5 的写法
Math.max.apply(null, [14, 3, 77])
// ES6 的写法
Math.max(…[14, 3, 77])
2 复制数组
// ES5 的写法
const a1 = [1, 2];
const a2 = a1.concat();
// ES6 的写法
const a1 = [1, 2];
onst a2 = […a1]; //或 const […a2] = a1;
3 合并数组
// ES5 的写法
[1, 2].concat(more);
arr1.concat(arr2, arr3);
// ES6 的写法
[1, 2, …more];
[…arr1, …arr2, …arr3]
4 与结构赋值结合
// ES5 的写法
a = list[0], rest = list.slice(1)
// ES6 的写法
[a, …rest] = list
答:对数组进行深拷贝:
-
for循环
-
slice方法
-
concat方法
-
ES6扩展运算符
对对象进行深拷贝:
-
for循环
-
先转换成json在转换成对象
-
ES6扩展运算符
答:深拷贝
答:有两种方法:
方法一: Set + Array.from()
var set1 = Array.from(new Set([1,1,2,2,33,‘33’,44,‘44’
]))
方法二: …[拓展运算符] + Set
var tt = […new Set([5,5,6,6,8,])] // 5,6,8
53.es6判断是否是数组:isArray,以及其他判断数组的方法?typeof 检测数组返回值
答:
判断数组方法:
- 1.用instanceof判断
使用instanceof运算符可以分辨数组和对象,可以判断数组是数组。
- 2.用constructor判断
实例化的数组拥有一个constructor属性,这个属性指向生成这个数组的方法。
当constructor属性被修改之后,就无法用这个方法判断数组是数组了
- 3.用Object的toString方法判断
toString方法将会返回"[object type]",其中的type代表的是对象的类型,根据type的值,我们就可以判断这个疑似数组的对象到底是不是数组了
- 4.用Array对象的isArray方法判断
isArray方法返回true,当参数不为数组的时候,isArray方法返回false
typeof 检测数组返回值
typeof是javascript原生提供的判断数据类型的运算符,它会返回一个表示参数的数据类型的字符串
答:
-
利用ES6中的Set
-
利用for嵌套for,然后splice去重(ES5中最常用)
-
利用indexOf去重
-
利用sort()
-
利用includes
-
利用hasOwnProperty
-
利用filter
-
利用递归去重
-
利用Map数据结构去重
-
利用reduce+includes
思路:
//统计一个数组中有多少个不重复的单词:
// 不用reduce时:
var arr = [“apple”,“orange”,“apple”,“orange”,“pear”,“orange”];
function getWordCnt(){
var obj = {};
for(var i= 0, l = arr.length; i< l; i++){
var item = arr[i];
obj[item] = (obj[item] +1 ) || 1;
}
return obj;
}
console.log(getWordCnt());//{apple: 2, orange: 3, pear: 1}
// 用reduce时:
var arr = [“apple”,“orange”,“apple”,“orange”,“pear”,“orange”];
function getWordCnt(){
return arr.reduce(function(prev,next){
prev[next] = (prev[next] + 1) || 1;
return prev;
},{});
}
console.log(getWordCnt());//{apple: 2, orange: 3, pear: 1}
-
数组api又叫应用程序接口,函数方法
-
常见api
- arr.push():数据添加 - 在数组尾部添加元素
push方法一次可添加单个或多个元素到数组末端,也可以添加数组
数组名.push("元素1","元素2",...)
- arr.pop():数据更新 - 删除数组的最后一个元素
pop方法的作用是移除数组末尾的一个元素。把数组长度减1,并且返回它的删除值,如果数组为空,则pop()不改变数组,返回undefind
数组名.pop()
-
arr.concat():连接两个或更多的数组,并返回结果。
-
arr.join():字符连接
若不想要任何连接符,则括号中用空字符即可。
数组名.join("连接符")
-
arr.reverse():颠倒数组中元素的顺序。
-
arr.shift():删除数据 - 移除数组顶端的元素
shift方法与pop相反,移除数组的第一个元素并将其返回。该方法执行后,数组剩下的元素向前移动,下标索引号重新调整从0开始。
数组名.shift()
- arr.unshift():添加数据 - 在数组头部添加元素
nshift方法与push方法正好相反,是将元素插入数组的首部。一次可以插入单个或多个元素,所有元素按顺序插入,操作完成后返回新数组的引用
数组名.unshift("元素1","元素2",...)
- arr.slice():生成特定数据 - 获取数组中的一部分元素
slice方法的作用是抽取数组的一段元素,抽取指定下标索引区间中的元素作为新数组返回
数组名.slice(start,end)
注:splice是直接修改原数组,而slice不会修改原数组。
-
arr.sort():对数组的元素进行排序
-
arr.splice():更新移动数据 - 删除、替换或插入数组元素
splice方法的作用是,从一个数组中移除一个或多个元素。剩下的元素组成一个数组,移除的元素组成另一个数组并返回它的引用。同时,原数组可以在移除的开始位置处顺带插入一个或多个新元素,达到修改替换数组元素的目的。这个操作效果通常称为接合
数组名.splice(start,deleteCount,item1,item2,...)
参数说明:
start:必选项,表示从数组中剪切的起始位置下标索引号。
deteleCount:必选项,表示从数组中切取的元素个数。
item:可选项,表示切取时插入原数组切入点开始出的一个或多个元素。
-
arr.indexof():查找元素对应下标
-
arr.forEach():数组遍历
-
arr.filter():数组遍历,将返回的值新建成一个新数组
-
arr.map():遍历数组,直接操作数组,返回一个新数组
-
arr.reduce():数组归并
57.数组中sort的用法。sort的返回值?没有传比较函数的比较?
用法:对数组的元素进行排序
arr.sort()直接操作原有数组,返回原有数组,当没有传比较函数的话不会按大小排序,而是按顺序排序
var arr = [22,12,3,43,56,47,4];
arr.sort();
console.log(arr); // [12, 22, 3, 4, 43, 47, 56]
arr.sort(function (m, n) {
if (m < n) return -1
else if (m > n) return 1
else return 0
});
console.log(arr); // [3, 4, 12, 22, 43, 47, 56]
- 概要
Canvas 位图,是需要自己画点的白板;
WebGL 3D位图,是基于 Canvas 的 3D 框架。
- 用途
Canvas 适用于位图,高数据量高绘制频率(帧率)的场景,如动画、游戏;
WebGL 主要用来做 3D 展示、动画、游戏。
-
canvas缺点:
-
只能绘制2D图像,暂时不支持3D图像。
-canvas绘制图形出并非可以直接操作的dom对象。如果要对其进行类似dom的操作,例如添加属性等等,比较麻烦(这就是为什么必须使用类库)。
- canvas优点:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
跳槽是每个人的职业生涯中都要经历的过程,不论你是搜索到的这篇文章还是无意中浏览到的这篇文章,希望你没有白白浪费停留在这里的时间,能给你接下来或者以后的笔试面试带来一些帮助。
也许是互联网未来10年中最好的一年。WINTER IS COMING。但是如果你不真正的自己去尝试尝试,你永远不知道市面上的行情如何。这次找工作下来,我自身感觉市场并没有那么可怕,也拿到了几个大厂的offer。在此进行一个总结,给自己,也希望能帮助到需要的同学。
面试准备
面试准备根据每个人掌握的知识不同,准备的时间也不一样。现在对于前端岗位,以前也许不是很重视算法这块,但是现在很多公司也都会考。建议大家平时有空的时候多刷刷leetcode。算法的准备时间比较长,是一个长期的过程。需要在掌握了大部分前端基础知识的情况下,再有针对性的去复习算法。面试的时候算法能做出来肯定加分,但做不出来也不会一票否决,面试官也会给你提供一些思路。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
)58.canvas与webGL的区别
- 概要
Canvas 位图,是需要自己画点的白板;
WebGL 3D位图,是基于 Canvas 的 3D 框架。
- 用途
Canvas 适用于位图,高数据量高绘制频率(帧率)的场景,如动画、游戏;
WebGL 主要用来做 3D 展示、动画、游戏。
-
canvas缺点:
-
只能绘制2D图像,暂时不支持3D图像。
-canvas绘制图形出并非可以直接操作的dom对象。如果要对其进行类似dom的操作,例如添加属性等等,比较麻烦(这就是为什么必须使用类库)。
- canvas优点:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-JCOtXT6l-1712636324699)]
[外链图片转存中…(img-rx3lVUOS-1712636324700)]
[外链图片转存中…(img-ip7BpDXn-1712636324700)]
[外链图片转存中…(img-INO0Jf3t-1712636324701)]
[外链图片转存中…(img-KI4i0ylV-1712636324701)]
[外链图片转存中…(img-ZD63NUmS-1712636324702)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-K2H4g8lq-1712636324702)]
跳槽是每个人的职业生涯中都要经历的过程,不论你是搜索到的这篇文章还是无意中浏览到的这篇文章,希望你没有白白浪费停留在这里的时间,能给你接下来或者以后的笔试面试带来一些帮助。
也许是互联网未来10年中最好的一年。WINTER IS COMING。但是如果你不真正的自己去尝试尝试,你永远不知道市面上的行情如何。这次找工作下来,我自身感觉市场并没有那么可怕,也拿到了几个大厂的offer。在此进行一个总结,给自己,也希望能帮助到需要的同学。
面试准备
面试准备根据每个人掌握的知识不同,准备的时间也不一样。现在对于前端岗位,以前也许不是很重视算法这块,但是现在很多公司也都会考。建议大家平时有空的时候多刷刷leetcode。算法的准备时间比较长,是一个长期的过程。需要在掌握了大部分前端基础知识的情况下,再有针对性的去复习算法。面试的时候算法能做出来肯定加分,但做不出来也不会一票否决,面试官也会给你提供一些思路。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-W42ttoTM-1712636324702)]