前端知识点总结 --JS 基础
1.JavaScript 概述(了解)
1. 什么是 JavaScript
JavaScript 简称为 JS, 是一种运行于 JS 解释器 / 引擎中的脚本语言
JS 的运行环境:
1. 独立安装的 JS 解释器(node)
2. 嵌入在浏览器内核中的 JS 解释器
2.JS 的发展史
1992 年 Nombas 公司为自己开发了一款脚本语言 SciptEase
1995 年 Netscape(网景)开发了一款脚本语言 LiveScrpt, 后来更名 JavaScript
1996 年 Microsoft 在 IE3.0 版本中克隆 JavaScript,JScript
1997 年, JavaScript 提交给 ECMA(欧洲计算机制造商联合会). 定义 ECMAScript, 简称 ES5,ES6
3.JS 组成部分
核心(ECMAScript)
DOM (Document object model)文档对象模型
BOM (Browser object model)浏览器对象模型
4.JS 的特点
语法类似于 c,java
无需编译, 由 JS 解释器直接运行
弱类型语言
面向对象的
2.JavaScript 的基础语法
1. 使用 JavaScript
1. 搭建运行环境
1. 独立安装的 JS 解释器 - Node.JS
1. 在命令行界面: 输入 node
console.log("你好, 世界");
在控制台打印输出
说明: JS 是可以独立在 JS 解释器中运行
2. 使用浏览器内核中嵌的 JS 解释器
浏览器内核负责页面内容的渲染, 由两部分组成:
脚本解释引擎 - 解析: JavaScript
1. 直接在 Console(控制台)中输入脚本并运行
2. 将 JS 脚本嵌入在 HTML 页面中执行
1.HTML 元素的事件中执行 JS 脚本
事件 - onclick - 鼠标单击时要执行的操作
2. 在 < script > 中编写脚本并执行
网页的任何位置处, 嵌入一对 < script > 标记, 并且将脚本编写在 < script > 标记中.
3. 使用外部脚本文件(.JS 为后缀)
1. 创建脚本文件 (.JS) 并在文件中编写脚本
2. 在使用的网页中引用脚本文件
<script src="脚本文件的 url"></script>
3.JS 调试, F12 查看错误, 出错时不影响其它代码块, 后续代码继续执行.
- <script>
- /* 这个脚本错误 */
- document.writ("<h3 > 周芷若</h3>");
- </script>
- <script>
- /* 继续执行 */
- console.log("*** 婆婆");
- </script>
3. 通过语法规范
1. 语句: 可执行的最小单元
必须以; 结束
严格区分大小
所有的符号必须是英文
2. 注释:
// : 单行注释
/**/: 多行注释
3. 变量和常量
1. 变量声明
1. 声明变量
var 变量名;
2. 为变量赋值
变量名 = 值;
3. 声明变量是直接赋值
var 变量名 = 值;
- ex:
- var uname="张无忌";
- var age=20;
注意:
1. 允许在一条语句中声明多个变量, 用逗号隔开变量名.
var uname="韩梅梅",uage=20;
2. 如果声明变量, 但未赋值, 则值默认为 undefined
3. 声明变量时可以不适用 var, 但不推荐
uname="tom";
2. 变量名的规范
1. 不允许以数字开头
2. 不允许使用关键词和保留关键字
3. 最好见名知意
var uname; var uage;
4. 允许包含字母, 数字, 下划线(_),$
var $name="Tom";
5. 尽量使用小驼峰命名法
- var userName;
- var uname;
- var _uname;// 下划线
- var user_name;// 下划线
- var UserName;// 大驼峰命名法
4. 变量的使用
1. 声明变量未赋值, 值默认为 undefined
2. 使用未声明过的变量 报错
3. 赋值操作
变量名出现在 = 的左边, 一律是赋值操作
var uname="林妹妹";
4. 取值操作
变量只要没出现在 = 的左边, 一律是取值操作
- var uage=30;
- console.log(uage);
- var num1=uage;
5. 常量
1. 什么是常量
在程序中, 一经声明就不允许被修改的数据就是常量.
2. 语法
const 常量名 = 值;
常量名在程序中, 通常采用大写形式.
const PI=3.1415926;
5.1 数据类型
1. 数据类型的作用
规定了数据在内存中所占的空间
10.1 64 位 8 个字节
bit: 位
8bit=1byte 字节
- 1024byte=1KB
- 1024KB=1MB
- 1024MB=1G
- 1024G=1T
2. 数据类型详解
1. 数据类型分两大类
原始类型(基本类型)
引用类型
1. 原始类型
1.Number 类型
数字类型
作用: 可以表示 32 位的整数, 也可以表示 64 位的浮点数(小数)
整数:
1. 十进制
10
2. 八进制
由 0-7 八个数字组成, 逢八进一
八进制中以 0 开始
var num=010;
3. 十六进制
由 0-9 和 A-f 组成, 逢十六进一
- A:10
- B:11
- C:12
- D:13
- E:14
- F:15
十六进制中以 0X 开始
浮点数: 又称小数
小数点计数法: 12.58
指数计数法: 3.4e3(3.4*10 的 3 次方)
2.String 类型
字符串类型
作用: 表示一系列的文本字符数据, 如: 姓名, 性别, 住址...
字符串中的每个字符, 都是由 Unicode 码的字符, 标点和数字组成.
Unicode 码: 每个字符在计算机中都有一个唯一的编码表示该字符,
该码就是 unicode 码(他是十六进制)
1. 查找一个字符的 unicode 码:
- "李".charCodeAt();
- //10 进制输出
- "李".charCodeAt().toString(2);
- // 二进制输出
- "李".charCodeAt().toString(16);
- // 十六进制
李的 unicode 码是: 674e
2. 如何将 674e 转换为汉字?
用 \ u
- ex:
- var str="\u674e";
- console.log(str);// 结果是 "李"
汉字的 Unicode 码的范围:
\u4e00~\u9fa5
3. 特殊字符需要转义字符
\n: 换行
\t: 制表符(缩进)
- \":"
- \':'
\\: 3.Boolean 类型
布尔类型
作用: 在程序中表示真或假的结果
取值:
true 或 false
- var isBig=true;
- var isRun=false;
在参与到数学运算时, true 可以当成 1 做运算, false 可以当做 0 做运算.
var res=25+true; // 结果为 26
4.Undefined 类型
作用: 表示使用的数据不存在
Undefined 类型只有一个值, 即 undefined 当声明的变量未赋值 (未初始化) 时,
该变量的默认值就是 undefined.
5.Null 类型
null 用于表示不存在的对象.
Null 类型只有一个值, 即 null, 如果函数或方法要返回的是对象,
找不到该对象, 返回的就是 null.
5.2 数据类型的转换
1. 隐式 (自动) 转换
不同类型的数据在计算过程中自动进行转换
1. 数字 + 字符串: 数字转换为字符串
- var num=15;
- var str="Hello";
- var res=num+str; // 结果: 15Hello
2. 数字 + 布尔: 将布尔转换为数字 true=1,false=0
- var num1=10;
- var isSun=true;
- var res1=num1+isSun;// 结果: 11
3. 字符串 + 布尔: 将布尔转换为字符串
- var str1="Hello";
- var isSun1=true;
- var res2=str1+isSun1;// 结果: Hellotrue
4. 布尔 + 布尔: 将布尔转换为数字
- true=1,false=0;
- var isSun2=true;
- var isSun3=flase;
- var res=isSun2+isSun3;// 结果 1
2. 强制转换 - 转换函数
1.toString()
将任意类型的数据转换为字符串
语法:
var num = 变量. toString();
- ex:
- var num=15;
- var str=num.toString();
- console.log(typeof(str));
- 2.parseInt()
将任意类型的数据转换为整数
如果转换不成功, 结果为 NaN(Not a Number)
语法: var result=parseInt(数据);
3.parseFloat()
将任意类型的数据转换为小数
如果转换不成功, 结果为 NaN
语法: var result=parseFloat(数据);
4.Number()
将任意类型数据转为 Number 类型
注意: 如果包含非法字符, 则返回 NaN
语法: var result=Number(数据);
6. 运行符和表达式
1. 什么是表达式
由运算符连接操作数所组成的式子就是表达式.
- ex:
- 15+20
- var x=y=40
任何一个表达式都会有结果.
2. 运算符
1. 算术运算符
- +,-,*,/,%, +,--
- 5%2=1;
++: 自增运算, 只做 + 1 操作
++ 在前: 先自增, 再运算;
++ 在后: 先运算, 再自增;
- ex:
- var num=5;
- console.log(num++);// 打印 5, 变为 6
- console.log(++num);// 变为 7, 打印 7
- ex:
- var num=5;
- 5 (6)6 6(7) (8)8
- var res=num+ ++num +num++ + ++num +num++ +num;
- 8(9) 9
结果: 42
2. 关系运算符(比较)
>,<,>=,<=,==,===(全等),!=,!==(不全等)
关系运算的结果: boolean 类型(true,false)
问题:
1. 5> "10" 结果: false
关系运算符两端, 只要有一个是 number 的话, 另外一个会隐式转换为 number 类型, 再进行比较.
2."5">"1 0" 结果: true
- "5".charCodeAt(); //53
- "1".charCodeAt(); //49
"张三丰"> "张无忌" 结果: false
19977> 26080
3."3a"> 10 结果: false
Number("3a")--->NaN
注意:
NaN 与任何一个数据做比较运算时, 结果都是 false.
- console.log("3a">10); false
- console.log("3a"==10); false
- console.log("3a"<10); false
isNaN()函数:
语法: isNaN(数据);
作用: 判断指定数据是否为非数字, 如果不是数字, 返回值为 true, 是数字的话返回的值为 false
- console.log(isNaN("3")); //false
- console.log(isNaN("3a")); //ture
- console.log("3a"!=10);//true
3. 逻辑运算符
!,&&,||
!: 取反
&&: 并且, 关联的两个条件都为 true, 整个表达式的结果为 true
||: 或者, 关联的两个条件, 只要有一个条件为 true, 整个表达式的结果就为 true
短路逻辑:
短路逻辑 &&:
当第一个条件为 false 时, 整体表达式的结果就为 false, 不需要判断第二个条件
如果第一个条件为 true, 会继续判断或执行第二个条件
短路逻辑 ||:
当第一个条件为 true 时, 就不再执行后续表达式, 整体结果为 true.
当第一个条件为 false 时, 继续执行第二个条件或操作.
4. 位运算符
<<,>>,&,|,^
右移是把数变小, 左移是把数变大
&: 按位与, 判断奇偶性
任意数字与 1 做按位与, 结果为 1, 则为奇数, 结果为 0, 则为偶数.
- var num=323;
- var result=num & 1
- console.log(result); // 结果为 1
|: 按位或, 对小数取整
将任意小数与 0 做按位或, 结果则取整数部分.
^: 按位异或, 用于交换两个数字
二进制位数, 逐位比较, 不同则为 1, 相同则为 0
- a=a^b;
- b=b^a;
- a=a^b;
5. 赋值运算符和扩展赋值运算符
1. 赋值运算 =
var uname="TOM";
2. 扩展赋值运算符
- +=,-=,*=,/=,%=,^=...
- a=a+1 a+=1;a++;++a
- a=a^b
- a^=b
6. 条件 (三目) 运算符
单目 (一目) 运算符, 只需要一个操作数或表达式
ex: a++,b--,!isRun
双目 (二元) 运算符, 需要两个操作数或表达式
+,-,*,/,%,>,<,>=,<=,==,!=,===,!==,&&,||,&,|,^
三目 (三元) 运算符, 需要三个操作数或表达式
条件表达式? 表达式 1: 表达式 2;
先判断条件表达式的值,
如果条件为 true, 则执行表达式 1 的操作
如果条件为 false, 则执行表达式 2 的操作
ex: 成绩大于 60 及格, 否则, 输出不及格
7. 函数 - function
1. 什么是函数
函数, function, 也称为方法(method)
函数是一段预定义好, 并可以被反复执行的代码块.
预定义: 提前定义好, 并非马上执行.
代码块: 可以包含多条可执行的语句
反复执行: 允许被多次调用
函数 - 功能
- parseInt();
- parseFloat();
- Number();
- console.log();
- alert();
- document.write();
2. 定义和使用函数
1. 普通函数的声明和调用(无参数无返回值)
1. 声明
function 函数名(){
// 函数体
若干可执行的语句
}
2. 调用函数
在任意 JavaScript 合法的位置处通过 函数名(); 对函数进行调用.
2. 带参函数的声明和调用
1. 声明
function 函数名(参数列表){
- // 函数体
- }
参数列表: 可以声明 0 或多个参数, 多个参数间用逗号隔开
声明函数时, 声明的参数, 称之为 "形参"
2. 调用
函数名(参数值列表);
注意: 调用函数时, 传递的参数数值, 称之为 "实参".
尽量按照声明函数的格式进行调用
3. 带返回值函数声明和调用
1. 声明
function 函数名(参数){
// 函数体
return 值;
- //return 关键字, 程序碰到 return 关键词, 就立马跳出并且把值带出去
- }
注意: 最多只能返回一个值
2. 调用
允许使用一个变量接收函数的返回值
var result = 函数名(实参);
8. 作用域
1. 什么是作用域
作用域表示的是变量或函数的可访问范围.
JS 中的作用域分两种:
1. 函数作用域
只在函数范围内有效
2. 全局作用域
代码的任何位置都有效
2. 函数作用域中变量
又称为局部变量, 只在声明的函数中有效
- ex:
- function test(){
- var num=10;
- }
3. 全局作用域中的变量
又称为全局变量, 一经声明, 任何位置都能用
1. 不在 function 中声明的变量, 为全局变量
2. 声明变量不使用 var, 无论任何位置声明, 都是全局变量(不推荐)
注意:
全局变量和局部变量冲突时, 优先使用局部变量.
3. 变量的声明提前
1. 什么是声明提前
在 JS 程序正式执行之前, function 声明的函数,
会将所有 var 声明的变量, 都预读 (声明) 到所在作用域的顶部, 但赋值还是保留在原位.
9. 按值传递
1. 什么是按值传递
原始 (基本) 类型的数据(number,string,bool), 在做参数传递时,
都是按照 "值传递" 的方式进行传参的.
值传递: 真正传递参数时, 实际上传递的是值的副本(复制出来一个值),
而不是原始值.
2. 函数的作用域
1. 分为两种
1. 局部函数
在某个 function 中声明的函数.
2. 全局函数
在最外层 (<script > 中) 定义的函数就是全局函数, 全局函数一经定义,
任何位置处都能调用.
10.ECMAScript 提供一组全局函数
- parseInt()
- parseFloat()
- isNaN()
- encodeURI()
URL:uniform resource locator 路径
URI:uniform resource Identifier
作用: 对统一资源标识符进行编码, 并返回编码后的字符串
所谓的进行编码, 就是将地址中的多字节文字编成单字节的文字
- (英文数字: 单字节, 汉字 2-3 字节不等)
- 5.decodeURI()
作用: 对已经编码的 URI 进行解码, 并返回解码后的字符串.
6.encodeURIComponent()
在 encodeURI 的基础上, 允许对特殊符号进行编码.
7.decodeURIComponent()
解码特殊符号
8.eval()
作用: 执行以字符串表示的 JS 代码
11. 递归调用
递归: 在一个函数的内部再一次调用自己
问题:
- 1*2*3*4*5
- 5*4*3*2*1
求 5!(5*4*3*2*1) 4!(4*3*2*1) 3!(3*2*1)
- 2!(2*1) 1!(1*1)
- 5!=5*4!
- 4!=4*3!
- 3!=3*2!
- 2!=2*1!
- 1!=1
通过一个函数, 求数字 n 的阶乘
10!=10*(10-1)!
效率:
在本次调用还未结束时, 就开始下次的调用, 本次调用就会被挂起,
直到所有的调用都完成之后, 才会依次返回, 调用的次数越多, 效率越低.
12. 分支结构
1.if 结构
if(条件){
语句块;
}
注意:
条件尽量是 boolean 的, 如果不是 boolean, 以下情况会当做 false 处理
- if(0){...}
- if(0.0){...}
- if(""){...}
- if(undefined){...}
- if(null){...}
- if(NaN){...}
注意: if 后的 {} 可以省略, 但是不推荐, 只控制 if 后的第一句话.
2.if...else... 结构
语法:
if(条件){
语句块
}else{
语句块
- }
- 3.if....else if...else...
语法:
if(条件 1){
语句块 1
}else if(条件 2){
语句块 2
}else if(条件 3){
语句块 3
}else{
语句块 n
- }
- 4.switch...case
1. 作用:(使用场合)
等值判断
2. 语法
1.switch(值 / 表达式){
case 值 1:
语句块 1;
break;// 结束 switch 结构, 可选的
case 值 2:
语句块 2;
- break;
- ...
- default:
语句块 n;
break;
}
2. 特殊用法
执行相同操作时:
switch(值 / 表达式){
case 值 1:
case 值 2:
case 值 3:
语句块;
}
12. 循环结构
1. 特点
循环条件: 循环的开始和结束
循环操作: 要执行的相同或相似的语句
2. 循环 - while
语法:
- while(条件){
- // 循环体 - 循环操作
- // 更新循环条件
- }
3. 循环的流程控制
1.break
作用: 终止整个循环的运行
2.continue
作用: 终止本次循环的运行, 继续执行下一次循环
ex:
循环从弹出框中录入信息, 并且打印, 直到输入 exit 为止.
4. 循环 - do...while
1. 语法
- do{
- // 循环体
- }while(条件);
执行流程:
1. 先执行循环体
2. 再判断循环条件
如果条件为真, 则继续执行循环体
如果条件为假, 则跳出循环操作
5. 循环 - for
语法:
- for(表达式 1; 表达式 2; 表达式 3){
- // 循环操作
- }
表达式 1: 循环条件的声明
表达式 2: 循环条件的判断
表达式 3: 更新循环变量
执行流程:
1. 先执行表达式 1
2. 判断表达式 2 的结果(boolean 类型)
3. 如果 2 条件为真, 则执行循环体, 否则退出
4. 执行完循环体后, 再执行表达式 3
5. 判断表达式 2 的结果
- ex: for(var i=1;i<=10;i++){
- console.log(i);
- }
13.for 的特殊用法
1.for(表达式 1; 表达式 2; 表达式 3;){}
1. 省略表达式
三个表达式可以任意省略, 分号不能省
但一定在循环的内部或外部将表达式补充完整
2. 表达式 1 和表达式 3 允许写多个表达式, 用逗号隔开表达式
14. 循环嵌套
1. 循环嵌套
在一个循环的内部, 又出现一个循环
- for(var i=1;i<100;i++){ // 外层循环
- for(var j=1;j<=10;j++){
- // 内层循环
- }
- }
外层循环走一次, 内层循环走一轮
15. 数组
1. 什么是数组
在一个变量中保存多个数据.
数组是按照线型顺序来排列的 - 线型结构
数组中: 除了第一个元素外, 每个元素都有一个直接的 "前驱元素".
数组中: 除了最后一个元素外, 每个元素都有一个会直接的 "后继元素".
2. 声明数组
1. 语法
1.var 数组名 =[];
var names=[];
2.var 数组名 =[元素 1, 元素 2, 元素 3...];
var names=["孙悟空","猪八戒","沙和尚"];
3.var 数组名 = new Array();
var names=new Array();
4.var 数组名 = new Array(元素 1, 元素 2...);
var names=new Array("林黛玉","贾宝玉","王熙凤");
3. 数组的使用
1. 取值和赋值操作
取值:
数组名[下标]
- var newArr=["tom","lilei"];
- newArr[0]
赋值:
数组名[下标]= 值;
newArr[2]="韩梅梅";
2. 获取数组的长度
数组长度: 数组中元素的个数
属性: length
语法: 数组名. length
3. 配合循环, 遍历数组中的每个元素
for(var i=0;i<names.length;i++){
i: 表示数组中每个元素的下标
names[i]: 每个元素
}
length 表示数组中即将要插入的元素的下标
- var names=["tom","lili","lucy"];
- names[names.length]="lilei";
16. 关联数组
1. 关联数组
以字符串作为元素的下标的数组, 就是关联数组.
以数字作为下标的数组, 就是索引数组.
$array=["name"=>"tom"]
2.JS 中的关联数组
var array=[];
array["字符串下标"]= 值;
注意:
1. 关联数组中, 字符串下标的内容是不记录到 length 中的
2. 只能通过 字符串 做下标取值
3.for...in
遍历出任意数组中的字符串下标 以及 索引下标
语法: for(var 变量 in 数组名){
- // 变量: 字符串下标 或 索引下标
- }
17. 冒泡排序
1. 什么是冒泡
排序算法之一, 将一组数据进行排序, 小的数字往前排, 大的数字往后排.
两两比较, 小的靠前.
var arr=[9,23,6,78,45]; 5 个数 比 4 轮
第一轮: 比较了 4 次
第二轮: 比较了 3 次
第三轮: 比较了 2 次
第四轮: 比较了 1 次
1.n 个数字, 则比较 n-1 轮
for(var i=1;i<arr.length;i++)
2. 轮数增加, 比较的次数较少
for(var j=0;j<arr.length-i;j++)
第一轮 5 -1=4 次
第二轮 5 -2=3 次
第三轮 5 -3=2 次
第四轮 5 -4=1 次
两两比较 小的靠前
- if(arr[j]>arr[j+1])
- arr[j]^=arr[j+1];
- arr[j+1]^=arr[j];
- arr[j]^=arr[j+1]
18. 数组的常用方法
1.toString();
作用: 将数组转换为字符串, 并返回转换后的结果.
语法: var str = 数组对象. toString();
2.join()
作用: 将数组的元素通过指定的字符连接到一起, 并返回连接后字符串
语法: var str = 数组对象. join("字符");
3.concat()
作用: 拼接两个或更多的数组, 并返回拼接后的结果
语法: var res = 数组对象. concat(数组 1, 数组 2,...);
19. 数组的函数
1.slice()
作用: 截取子数组, 从指定的数组中, 截取几个连续的元素组成一个新的数组
语法: var arr = 数组名. slice(start,[end]);
start: 从哪个下标位置处开始截取, 取值为正, 从前向后算;
取值为负, 从后向前算 0 1 2
- var arr=["中国","美国","俄罗斯"];
- -3 -2 -1
end: 指定结束位置处的下标(不包含自己), 该参数可以省略,
如果省略的话, 就是从 strat 开始一直截取到尾.
2.splice()
作用: 允许从指定数组中, 删除一部分元素, 同时再添加一部分元素
语法: arr.splice(start,count,e1,e2...);
start: 指定添加或删除元素的起始下标
count: 指定要删除元素的个数, 取值为 0 表示不删除
e1: 要增加的新元素, 可以多个
返回值: 返回一个由删除元素所组成的数组
3.reverse()
作用: 将一个数组反转
语法: 数组名. reverse();
注意: 该函数会改变当前数组的内容
4.sort()
作用: 排序, 默认情况下按照数组元素们的 Unicode 码进行升序排序.
语法: 数组名. sort();
特殊:
允许自定义排序函数, 从而实现对数字的升序或降序的排序
- ex:
- var arr=[12,6,4,115,78];
- // 排序函数(升序)
- function sortAsc(a,b){
- return a-b;
- }
- arr.sort(sortAsc);
原理:
1. 指定排序行数 sortAsc, 定义两个参数 a 和 b, 表示数组中相邻的两个数字
2. 将排序函数指定给数组 sort()函数, 数组会自动传递数据到 sortAsc()中,
如果 sortAsc()的返回值 > 0, 则交互两个数字的位置, 否则不变.
使用函数完成升序排序:
- arr.sort(
- function(a,b){ // 匿名函数
- return a-b;
- }
- )
20. 进出栈操作
JS 是按照标准的 "栈式操作" 来访问数组
所有的 "栈式操作" 的特点就是 "后进先出"
1.push()
入栈, 在栈顶添加指定的元素, 并返回新数组的长度
- var arr=[10,20,30];
- // 向栈顶增加新的数据 40
- var len=arr.push(40); //4
- 2.pop()
出栈, 删除 (删除栈顶数据) 并返回删除元素
注意: 改变原来数组
3.shift()
删除数组头部 (第一个) 的元素并返回删除元素
语法: 数组名. shift();
4.unshift()
在数组的头部 (第一个) 元素的位置处, 增加元素, 返回的是数组的长度.
语法: 数组名. unshift(增加的数据);
3. 二维数组
1. 什么是二维数组
在一个数组中的元素又是一个数组, 也可以称为: 数组的数组.
2. 二维数组的使用
- var names=[
- ["孙悟空","猪八戒","沙和尚"],
- ["大乔","小乔","曹操"],
- ["林黛玉","贾宝玉","薛宝钗"]
- ];
- // 打印输出 "小乔"
- console.log(names[1][1]);
自己是个从事多年开发的前端工程师, 如果你对软件开发感兴趣
这里推荐一下我的前端学习资源分享 qun:767273102 , 里面都是学习前端的从最基础的 HTML+CSS+JS[炫酷特效, 游戏, 插件封装, 设计模式] 到移动端 HTML5 的项目实战的学习资料都有整理, 送给每一位前端小伙伴. 2019 最新技术, 与企业需求同步. 好友都在里面学习交流, 每天都会有大牛定时讲解前端技术!
持续学习, 提升自我, 前端资源分享 http://u6.gg/srMpX
来源: http://www.bubuko.com/infodetail-3099997.html