开发环境构建
1,基础架构
2,任务自动化(gulp)
3,编译工具(babel, webpack)
4,代码
App gulp+webpake server
常规创建三个板块:
app:前端资源
server:交互代码
task:自动化构建
国内npm(淘宝镜像)
安装:命令提示符执行npm install cnpm -g --registry=https://registry.npm.taobao.org
安装express框架
1,npm install -g express
2,npm install -g express-generator
3,express -e .
(在当前文件夹中使用ejs)
4,npm install
安装npm以来环境
根目录下创建npm依赖包
package.json
自动创建package命令:npm init
创建babel自动编译环境
创建 gulpfile.babel.js(
名称固定编译ES6代码)
安装完插件后面跟上--save-dev
是添加安装包依赖关系到package.js
中
gulp gulp-if gulp-concat webpack webpack-stream vinyl-named gulp-livereload gulp-plumber gulp-plumber gulp-rename gulp-uglify gulp-util yargs --save-dev
安装babel的插件
安装你想要将es6编译成什么版本
新版本babel
:
新版本babel,拆分成babel-cli
和babel-core
,2个都要install
。
npm install browserify gulp-clean-css gulp-htmlmin gulp-inject
gulp-less gulp-load-plugins gulp-plumber gulp-rename gulp-sourcemaps gulp-uglify gulp-useref ulp.spritesmith less-plugin
-autoprefix pump require-dir rimraf stringify vinyl-source-stream --save-dev
express 默认端口3000
1,let&const
作用域
let:不能重复定义;
注意
const:初始化必须赋值,数字类型数据不允许修改,对象属于引用类型,可以修改,常量定义指针不表,但指向的对象本身可以变化
2,解构赋值
1,数组解构,
2,对象解构赋值
3,字符串解构赋值
4,布尔值解构赋值
5,函数参数解构赋值
6,数值解构赋值
3,正则
ES5:
var reg=new RegExp(/xyz/i);
字符串正则方法:match(),replace(),search(),split()
U修饰符:用来正确处理大于\uFFFF的unicode字符,可以正确处理4个字节的UTF-16编码
/^\uD83D/u.test('\uD83D\uDC2A') //false
/^\uD83DD/.test('\uD83D\uDC2A') //true
test内容是一个4字节UTF-16编码,代表一个字符,由于ES5不认识4字节UTF-16编码,会将其识别为2个字符,结果就是true, 加了一个u之后,ES6就能够识别四字符
点.字符 表示 除了换行符意外单个字符,对于码点大于0xFFFF的unicode的字符,不能识别,必须加上u修饰符
var s='吉'
/^.$/.test(s) //false
/^.$/u.test(s) //true
量词:
使用u修饰符后,所有的量词都会正确识别大于0xFFFF的unicode字符
/吉{2}/.test('吉吉') //false
/吉{2}/u.test('吉吉') //true
预定义模式
u修饰符也影响到预定义模式能否正确识别码点 大于0xFFFF的unicode字符
/^\S$/.test('?') //false
/^\S$/u.test('?') //true
i修饰符
有些Unicode字符编码不同,但是字型很接近,比如 \u004B 和 \u212A 都是大写的K,不加u修饰符,就无法识别非规范的K字符
/[a-z]/i.test('\u212A') //false
/[a-z]/iu.test('\u212A') //true
y修饰符
ES6新增加了y修饰符,叫做黏连修饰符(sticky)。
y修饰符和g修饰符类似,也是全局匹配,后一次匹配都从第一次匹配成功的下一个位置开始。不同之处在于,g修饰符只要剩余位置中存在匹配就行,而y修饰符会确保匹配必须从剩余的第一个位置开始,
这就是黏连的意思
var s = "bbb_bb_b"
var p1 = /b+/g
var p2 = /b+/y
p1.exec(s) = ["bbb"]
p2.exec(s) = ["bbb"]
p1.exec(s) = ["bb"]
p2.exec(s) = null
字符串
unicode:
es5:处理unicode
charCodeAt('string');
String.fromCharCode('code');
es6:处理unicode
codePointAt()
String.fromCodePoint('34250')
遍历接口let of:
for(let code of s1){
console.log('es6',code)
}
模板字符串:
let modelStr=`hello everybody,i am ${name},my job is ${info}`;
标签模板:
dealStr`im ${user.name},${user.info}`;
function dealStr(str,str1,str2){
console.log(str,str1,str2)
return str+str1+str2;
}
新增方法:
es6操作字符串的方法
1,字符串包含判断
str.includes('xxx')
2,字符串起始
str.startsWith('xxx')
3,字符串重复操作
str.repeat(2)
4,字符串补充
str.padStart('要求必须长度','长度不够自动补充的字符')
从前面补充:
'1'.padStart(2,'0') ----01;
从后面补充:
'1'.padEnd(2,'0') -----10;
4,字符串’/'转义api
console.log(String.raw`我他妈就来试试\n好伐?`);
console.log(`好吧我\n就试试`)
数值处理方法
1,二进制0b开头
2,八进制0o开头
Number.isFinite()
//判断非无穷大数字
Number.isNaN() /
/判断非数字
Number.isInteger()
//判断是否是整数
Number.MAX_SAFE_INTEGER/
/最大有效整数
Number.MIN_SAFE_INTEGER/
/最小有效整数
Number.isSafeInteger()/
/判断介于最大和最小之间的有效整数
Math.trunc()
//只获取整数部分
es5:Math.floor()
向下取整,Math.ceil()
向上取整
Math.round()
//四舍五入
Math.sign()
//判断正数?返回1,0返回0,负数返回-1
Math.cbrt()
//开立方根
数组扩展
Array.of(1,2,3,4,5,6...)
//将多个数据转换成array数组
注:如果不传参数,就是形成一个空数组
Array.from()
将其他对象转换成数组对象(必须有length属性的
对象,部署Iterator
(迭代器)的对象比如,array,set,map
)
Array.from([],function(item){return item*2}),
可以有两个参数,第一个数字,用第二个函数map处理…
[].fill()/
/数组元素替换
1.只有一个参数就是把数组元素全部人替换
2.三个参数[].fill(a,b,c)
,将数组从b开始的c长度的替换成a
[].keys()
;//获取数组下标
for (let index of ['a', 'b', 'c', 'd', 'e'].keys()) {
console.log('key', index)
}
[].values;
//获取数组的值
let strArr=['a', 'b', 'c', 'd', 'e'];
for (let value of strArr.values()) {
console.log('values', value)
}
[].entries()
//同时获取key和value
for(let [index,value] of strArr.entries()){
console.log(index,value)
}
[].copyWithIn(a,b,c)
?️覆盖目标,b:用来覆盖的值,c:移除目标
[].find(function(item){return item>0})/
/返回满足条件的第一个元素
[].findIndex(function(index){return index>0})
//返回满足条件的第一个下标
[].include('')
//判断数组中是否包含这个值
函数扩展
参数默认值:
function test(x,y='fuck'){
console.log(x,y);
}
test('hello')
//hello fuck;
注意:有默认值参数之后,不允许在跟无默认值的参数
rest
参数
将多个参数组成数组,放在形参最后
function (...arg){
console.log(arg)//arg是一个数组
}
注:此处将多个参数组成数组
console.log(...[1,2,3,4]) //1 2 3 4 ...[]
将一个数组拆开
注:将一个数组拆开
箭头函数:
无参:函数名,参数,处理逻辑
let test=()=>xxxx;
有参:函数名,参数,处理逻辑
let test=x=>x;
对象扩展
简洁表示法
let es5 = {
a: 11,
b: 12,
c: function () {
console.log(b)
}
}
let a = 'harry';let b = 'hello';
let es6 = {
a,
b,
helle(){
console.log('bbbb');
}
}
console.log(es5.a,es6.b)
}
属性表达式
let a='v';
let es5={
a:'b',
b:'x'
}
let es6={
//此处用的是变量,最终用的是变量的值
[a]:'bbbb'
}
console.log(es5,es6)
新增Api:
判断相等:
Object.is(a,b);
比较两个对象是否相等,类似于’===’;
浅拷贝
Object.assign()
,拷贝
遍历key ,value对
Object.entries();
let list={a:'b',b:'b',c:'c'};
for(let [index,value] of Object.entries(list)){
console.log(index,value)
}
扩展运算符
第七种数据类型
symbol:
let str=symbol();//无参
let str=symbol('xxx')//有参
声明唯一值;
let str=symbol.for('x')
声明一个Key为x的唯一值,但会全局检索一边是否已经存在,如果存在就会返回value,如果不存在,就新生成一个
let a = Symbol('abc');
let obj = {
[a]: '1234',
'abc': 234
}
//取不出symbol
for (let [key,value] of Object.entries(obj)) {
console.log(key, value)
}
取出Symbols:
Object.getOwnPropertySymbols(obj).forEach(function (item) {
{
console.log(obj[item])
}
})
通过Reflect,取出所有,包括symbol
Reflect.ownKeys(obj).forEach(function(item){
console.log('onwkey',item,obj[item])
})
数据结构
set
:类似数组的集合,但是集合元素不能重复,或自动过滤掉
数据类型不进行转换:
let list=new set();
console.log(‘length’,list.size)
let arr=[1,2,3,4,5,6];
let list=new set(arr);
自带api:
let list=new Set();
添加:list.add();
删除:list.delete();
清空:list.clear();
包含:list. ();
let arr=['a','b','c','d','e','f','g'];
let list=new Set(arr);
遍历一
for(let key of list.keys()){
console.log('key',key)
}
遍历二
for(let value of list.values()){
console.log('value',value)
}
list.forEach(function(item){
console.log(item)
})
遍历三
for(let value of list){
console.log(value)
}
weakSize
跟set很像,但是成员必须是对象,不支持遍历
let weakList=new WeakSet();
let arg={};
Map:
//第一种定义方式
let map=new Map();
map.set(key,value);/
/添加
map.size();
//元素数量
map.delete();
//删除元素
map.clear()
//清空元素
//第二种定义方式,格式固定
let map=new Map([['a','b'],['c','d']]);
console.log('mapArgs',map);
let weakmap=new WeakMap();
1,不能遍历
2,没有size
3,没有clear
Array,Map对比:
var map=new Map();
var arr=[];
map.set('a','b','c','d');
arr.push(1,2,3,4,5);
console.log(map.size)//1
console.log(arr.length)//5
(增)结论:map
:用set添加元素,每次只能添加一个
array
:用push,每次添加多个
console.log(',,,',map.delete('a'))
console.log(arr.splice(arr.findIndex(item=>item.key),1)
(删)结论:map.delete()
直接删除
需要通过findIndex()
来确定索引位置删除
map.set('a',99);
arr.forEach(item=>item.key?item.key='asdasd':'');
(改)结论:map.set(),
直接放入,key,value即可改正
arr.forEach(),
需要先循环判断存在否
console.log('has',map.has('a'));
console.log('find',arr.find(item=>item.key));
(查)结论:map.has()
;返回true/false
map.find()
;返回查找到的元素
Set和Array对比
let set = new Set();
let arr = [];
//增
var obj = {a: 1};
set.add(obj);
arr.push({a: 1});
//删
set.forEach(item=>item.a ? set.delete(item) : '');
let index = arr.findIndex(item=>item.a)
arr.splice(index, 1);
//改
set.forEach(item=>item.a ? item.a = 999 : '');
arr.forEach(item=>item.a ? item.a = 888 : '');
//查
console.log(set.has(obj));
console.log(arr.find(item=>item.a));
Set Map object对比
let map=new Map();
let set=new Set();
let obj={};
let item={a:1};
//增
map.set('a',1);
set.add(item);
obj['a']=1;
console.log('map,set,obj',map,set,obj)
//查
console.log('map,set,obj',map.has('a'),set.has(item),'a' in obj)
//改
map.set('a',999),set.a=888,obj['a']=777
console.log('map_set_obj',map,set,obj)
//删
set.delete(item);
map.delete('a');
delete obj['a'];
console.log('map_set_obj',map,set,obj)
**Proxy**
(代理操作对象避免用户直接操作源数据对象,从而对源数据进行一系列操作)
let pro=new Proxy(obj,{
//拦截属性读取
get(taget,key){
return taget[key].replace('2016','2017')
},
//设置属性读取条件
set(target,key,value){
if(key=='name'||key=='date'){
return target[key]=value
}else{
return target[key]
}
},
//拦截key in obj
has(target,key){
if(key=='name'){
return target[key]
}else{
return false
}
},
用法:name in pro
//拦截delete
deleteProperty(target,key){
if(key.indexOf('_')>-1){
delete target[key]
return true
}else{
return target[key]
}
}
用法:delete pro.name
//拦截过滤安全数据
ownKeys(target){
//将date数据过滤不显示
return Object.keys(target).filter(item=>item!='date');
}
用法:Object.keys(pro)//取出被保护以外的所有数据
Reflect
(通过映射的方式,拿到对象的成员,进行一些列操作跟proxy类似,不过此对象不用new,直接拿)
//直接操作源数据将target日换成value
Reflect.set('obj',target,value)
//查看是否有某属性成员
Reflect.has('obj',member)
Js面向对象
类:
//声明一个类
class student{
//构造器
constructor(name='harry',age=1){
this.name=name;
this.age=age
}
}
//继承
class child extends student{
constructor(name,age){
//覆盖父级的默认值
注意:super是覆盖父级默认值的关键词只能放在子类参数前面
super(name,age);
this.name=name;
this.age=age
}
}
console.log(new child('fuck',30))
set和get用法
class parent{
constructor(name,age){
this.name=name;
this.age=age;
}
get getName(){
return 'mk'+this.name
}
set getName(value){
this.name=value;
}
}
静态方法:(直接通过类调用的方法)
class parent{
constructor(){
}
static say(){
console.log('学习');
}
}
console.log(parent.say());
静态属性(只有提案暂无专门的关键词)
class parent{
constructor(){
}
static say(){
console.log('学习');
}
}
//直接给类添加属性即可
parent.name='father';
parent.age='48';
promise异步(解决异步顺序问题,使得异步逻辑化更可控)
基本Api:
Promise.resove();
//表示执行下一步
Promise.reject();/
/拒绝执行下一步
Promise.prototype.catch()
//捕捉异常
Promise.prototype.then()
//下一步操作
Promise.all([])
// 所有的完成
(数组,必须是多个promise实例)
Promise.props()
//一个失败全部失败
(数组,必须是多个promise实例)
var p = Promise.all([p1,p2,p3]);
Promise.race([])
// 竞速,完成一个即可
实例
function getNumber(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
var num = Math.ceil(Math.random()*10); //生成1-10的随机数
if(num<=5){
resolve(num);
}
else{
reject('数字太大了');
}
}, 2000);
});
return p;
}
getNumber()
.then(
function(data){
console.log('resolved');
console.log(data);
},
function(reason, data){
console.log('rejected');
console.log(reason);
}
);
let name='harry';
function protest(num) {
console.log(num);
//新建一个Promise对象,两个固定参数
return new Promise(function (resolve, reject) {
if (num > 5) {
resolve();
} else {
throw new Error('80001');
}
})
}
//用then来表示,下一步执行
protest(6).then(function () {
return new Promise(function(resolve,reject){
if(name=='harry'){
console.log('harry')
resolve();
}else{
throw new Error('80002');
}
})
//捕捉异常
}).catch(function(err){
console.log(err);
}).then(function(){
console.log('fuck');
}).catch(function(err){
console.log(err)
}).finally(funtion(){
//任何情况下都会执行的内容
})
//关于Promise.all的用法
//预加载图片实例
function loadImg(src){
return new Promise((resolve,reject)=>{
let img=document.createElement('img');
img.src=src;
img.onload=function(){
resolve(img);
}
img.onerror=function(err){
reject(err);
}
})
}
function showImg(imgs){
imgs.forEach((img)=>document.body.appendChild(img))
}
//此处loadimg已经返回promise实例形成的数组
Promise.all([
loadImg('https://michaelkors-wechat.cn/Public/MiniApps/TW/membership_02_tw.png'),
loadImg('https://uat.michaelkors-wechat.cn/Public/MiniApps/images/bg2.jpg'),
loadImg('https://uat.michaelkors-wechat.cn/Public/MiniApps/images/i4.png')
]).then(showImg)
//关于Promise.race的用法
function loadImg(src){
return new Promise((resolve,reject)=>{
let img=document.createElement('img');
img.src=src;
img.onload=function(){
resolve(img);
}
img.onerror=function(err){
reject(err);
}
})
}
function showImg(img){
document.body.appendChild(img)
}
Promise.race([
loadImg('https://michaelkors-wechat.cn/Public/MiniApps/TW/membership_02_tw.png'),
loadImg('https://uat.michaelkors-wechat.cn/Public/MiniApps/images/bg2.jpg'),
loadImg('https://uat.michaelkors-wechat.cn/Public/MiniApps/images/i4.png')
]).then(showImg)
Iterater接口(next)和for…of
//为对象部署iterator接口属性
let obj = {
start: [1, 2, 3],
end: [5, 6, 7],
[Symbol.iterator](){
let self = this;
let index = 0;
let arr = self.start.concat(self.end);
let len = arr.length;
return {
next(){
if (index < len) {
return {
value: arr[index++],
done: false
}
} else {
return {
value: arr[index++],
done: true
}
}
}
}
}
}
Generator(异步编程解决方案)
Generator函数本意是iterator接口生成器,函数运行到yield时退出,并保留上下文,在下次进入时可以继续运行
//基本定义方式
let gen=function*(){
//yield:返回并退出,跟return不同点在于保存上文状态
yield 'a';
yield 'b';
yield 'c';
return 'd'
}
//本质上是一个iterator生成器
let obj={};
obj[Symbol.iterator]=function*(){
yield 'a';
yield 'b';
yield 'c';
}
for(let value of obj){
console.log(value);
}
Generator最佳应用场景
//状态机模式
let state=function*(){
while(1){
yield 1;
yield 2;
yield 3;
}
}
let s=state();
console.log(s.next())
console.log(s.next())
console.log(s.next())
async(es7异步解决方案),和Generator用法一致
let state=async(){
while(1){
await 1;
await 2;
await3;
}
}
let s=state();
console.log(s.next())
console.log(s.next())
console.log(s.next())
Demo_01(抽奖)
let draw=function(count){
console.log(`剩余${count}次`);
}
let residue=function*(count){
while(count>0){
count--;
yield draw(count);
}
}
let start=residue(5);
let btn=document.createElement('button');
btn.id='start';
btn.textContent='抽奖';
document.body.appendChild(btn);
document.getElementById('start').addEventListener('click',function(){
start.next();
},false)
Demo_02(轮询)
{
let ajax = function*() {
yield new Promise(function (resolve, reject) {
setTimeout(function () {
resolve({code: 0})
}, 300)
})
}
let pull = function () {
let genertaor = ajax();
let set = genertaor.next();
set.value.then(function (res) {
if (res.code != 0) {
setTimeout(function () {
console.log('wait...');
pull();
}, 300)
} else {
console.log(res)
}
})
}
pull();
}
Decorator(修饰器)
1,需要额外安装npm install babel-plugin-transform-decorators-legacy --save-dev
才能解析
2,在babelrc文件中配置
'plugins':['transform-decorators-legacy']
定义只读方法
let readonly = function (target, name, descriptor) {
descriptor.writable = false;
return descriptor;
}
demo1:修饰某个成员
//修饰某个成员
class test {
//调用只读方法
@readonly
time() {
return '2016-03-14';
}
}
demo2:修饰某个成员
let typename=function(target,name,descriptor){
//此处给类添加一个静态属性
target.myname='harry'
}
//修饰整个类
@typename
class test{
}
console.log(test.myname);
第三方修饰类js库
core-decorators;
npm install core-decorators
模块化:
导出:即将本页面资源导出共享 export let a=harry, age=27
导入:将其他页面导出的共享资源导入使用 import {a,age} from ‘url’
导入所有:import * as 别名 from ‘url’
使用: 别名.模块成员
导出所有
exprt default{
要导出的成员
}
模块化规范:
AMD:require.js模块化概念推广的产出规范
CMD:sea.js模块化概念推广下得产出规范(淘宝)
项目实战:
1,业务分析复用组件抽取
如有错误,敬请留言指点,我立马改正,以免误导他人~谢谢!