*node下用express框架,实现一个简单的mvc
*构建工具:gulp / babel / webpack / npm
看gulp / babel 中文文档
了解 Gulp自动化,babel编译工具,webpack编译打包(文件间的依赖),webpack-stream是让webpack支持gulp
*创建项目:(es6基础彩票实战)
创建目录/命令行处理/创建js编译任务:
mkdir项目名称 (创建根目录并命名)
cd项目名称
mkdir app (放置前端代码的)
mkdir server(创建服务器文件夹)
mkdir tasks(构建工具的目录)
cd app
mkdir css/ js / views(app前端目录中创建css、js、views文件夹)
mkdir js/class (在js中创建class文件夹)
文件夹内初始化文件:
touchjs/class/test.js
touch js/index.js
touch views/error.ejs
touch views/index.ejs
(服务器代码通过node使用的模板引擎,.ejs相当于.html)
(服务器文件需要node里面的express脚手架)
cd server
(使用npm安装express框架)
express -e .(e是使用ejs模板引擎,.是指在当前目录执行)
npm install完成安装(cd .&& npm install)
sudo npm install -g express
sudo npm install -gexpress-generator
express -e脚手架自动构建
npm install
npm start(启动express服务器)
cd tasks
mkdir util放置常见的脚本
touch util/args.js
------------------------------------------------------------------------------------------------
cd ../返回项目根目录
npm init 创建package.json安装依赖包需要有它
touch .babelrc 设置b/./abel编译工具的配置文件
touch gulpfile.babel.js(用ES6编写一定要加上.babel)
创建模板、服务任务脚本:
在tasks>util>args.js(处理命令行参数的脚本)文件编写
touch tasks/scripts.js(构建处理js的脚本,构建脚本都放在tasks目录下)
npm install gulp gulp-if gulp-concat webpack
webpack-stream vinyl-named gulp-livereload gulp-plumber gulp-rename gulp-uglify
gulp-util yargs --save-dev(package.json会有所变化)
------------------------------------------------------------------------------------------------
接着在script。js文件写代码:
touch tasks/pages.js(处理模板的固定脚本)
touch tasks/css.js (处理css相关任务)
touch tasks/server.js (处理服务器的脚本,启动服务器,文件改变浏览器自动刷新)
创建模板、服务任务脚本:(如何将写好的代码任务自动编译到server下的public里面,供服务器进行反应)
touch tasks/browser.js(类似服务器监听)
touch tasks/clean.js
(复制一份给服务器,当文件变化时,需要清除server旧文件)
手动安装上述引用的包:
npm install gulp-live-server del gulp-util--save-dev
touch
tasks/build.js(写一个脚本,将所有文件串起来)
touch
tasks/default.js(写一个默认脚本,如果命令行只输入gulp就指定执行build文件)
npm install babel-loader babel-core babel-preset-env webpack–save-dev
写gulpfile.babel.js文件:将tasks文件下所有文件都引进来执行
(执行gulp首先找gulpfile.babel.js这个文件)
npm install require-dir –save-dev(对上述文件引用的包进行安装)
写.babelrc文件:
{"presets": ["es2015"]}
npm install babel-preset-es2015 - -save-dev
npm install gulp-sequence --save-dev(安装遗忘的包)
执行gulp,确定没错后执行gulp –-watch(不加这个,所有脚本只执行一次)
执行gulp –-watch后直至livereload。。。出现
*解决服务器问题:(见最顶部红色背景)
http://lib.csdn.net/article/nodejs/58567?knId=802
*解决页面无变化问题:
在index.ejs里写html代码,然后看浏览器是否有变化,如果没有变化,结束进程,npm
start重新启动,刷新页面
*解决页面不自动刷新问题:(tasks>util>args.js文件最后一行加export default args)
*修改server里XXX问题:
•在server下面的app.js中加一句话(使能接受热更新的东西)
•app.use(require('connect-livereload')()); 这行一定要放到下面这行代码行下面app.use(express.static(path.join(__dirname, 'public')));
•在命令行安装上述包(ctrl+c终止服务器)
npm install connect-livereload –-save-dev
*再执行gulp –watch , 查看浏览器是否实现自动刷新(热更新)
*在文件里写ES6 查看能否实现转码,引js脚本查看效果,千万别点刷新(?)
*安装兼容处理的库(兼容ES7):npm install babel-polyfill --save-dev
==================================================================
以后的项目都建在app>js>class文件里,然后在index.js里引进新建的文件:
例如import './class/let';然后再执行gulp –watch
复习时,根据笔记和项目es6一起
==================================================================
*ES6:javascript的标准 js实现
*兼容性查看:http://kangax.github.io/es5--compat-table/es6/
*谷歌兼容包:https://github.com/paulmillr/es6-shim
*环境支持:以下代码放到head里面s
*Script标签的type属性值:module 或者 traceur,而不再是text/javascript
*Js中虚拟多线程:setTimeout
*模板
traceur.options.experimental = true;
------------------------------------------------------------------------------------------------
•ES6中箭头函数好处:在函数内部,this所指向的是函数外部,与外层this相同,不会出现this不一致的现象。
• let命令:用于定义变量,相当于var,但与var 的作用域不同。
*Var:{ 全局,局部(函数作用域,但if代码块中不算局部)}
*Let:遇到代码块就是局部作用域,包括if,出代码块就销毁
*Let不存在变量提升(实例如下
*let暂时性死区:在块级作用域内使用let,let所声明的变量就绑定在这个区域,不再受外部的影响(在let命令声明变量之前,都属于变量的“死区”.对typeof不完全试用,这样的设计是为了让大家养成良好的编程习惯,变量一定要在声明之后使用,否则就报错。)
*let不受外界影响
var a=200;{console.log(a);let a=100;console.log(a);} //undefined 100
*let模块内部不允许重复声明let a=1;let a=2;报错
·块级作用域:
1.内层变量可能会覆盖外层变量
2.用来计数的循环变量泄露为全局变量
•const命令:用于定义常量(波尔、字符串、123, 数组)对象({})作用域与let相同
*常量定义后不能通过语句改。但对象里的属性可以更改。
*一定要给值,不能光声明。
*想改变或者添加数组的值,需要用到push。Arr.push();
*对象冻结:
*彻底冻结对象(对象及其属性)的函数:
*跨模块常量引用:
const声明的常量只在当前代码块有效,如果想设置/使用跨模块的常量?
模块:如类,一个js文件
import后的*可以改写为{ 待引入文件里的变量1,变量2 }
*全局对象属性:
var命令和function命令声明的全局变量,属于全局对象的属性;
(严格模式下)let命令、const命令、class命令声明的全局变量,不属于全局对象的属性
解构:从数组或对象中取出来后 赋值给变量。
•变量的解构赋值(数组):
值不存在,解构不成功,返回undefined。
传统数组:var arr = [1,2,3] ; ➔ arr[0], arr[1], arr[2]
传统变量:var a = 1 , b = 2 ,c = 3 ;
举例:几种情况
var [ a, b, c ] = [ 1,2,3 ] ; // a=1 , b=2 , c=3 ;
var[ a, b, c ] = [ 1,,3 ] ; // b=undefined ;
var[ a , …c ] = [ 1, 2,3]; // a=1 , c=[2,3] ;
不完全解构:等号左边的模式,只匹配一部分的等号右边的数组
指定默认值:
var[a,b,c =’default’,d=’default’]=[1, 2, 3] //a=1, b=2, c=3, d=default var[p ,q=’aaa’]=[‘bbb’,undefined] ; // p=bbb ,q=aaa
非遍历结构:(报错)
var [a] = 1/false/NaN/undefined/null //没有中括号,会报错
let/const在解构中的作用:
只要某种数据结构具有Iterator接口,都可采用数组形式的解构赋值。
•变量的解构赋值(对象):
eg:var obj={
a:1,
b:2
}
//===============================================//
let { a, b} = obj; //a=1 , b=2;
let { a:A, b} = obj ; //A=1,a=undefined报错
eg:
eg:let{ a=1,b=2} ={ a:10} //a=10,b=2
let{ a:A=1, b=2} = { a:10 } //A=10,b=2给a重命名为A
•访问后台json数据:
➔➔
•访问一个对象中的多个方法(访问Math对象内的很多方法):
•变量的解构赋值(其他:字符串,函数等):
输出字符串长度:let { length }= ‘yo.’;
解构字符串成数组:let [ a, b,c] = ’ yo. ’ ;
函数传参进行解构:
(有图片) ➔➔ (有图片)
•新增字符串方法:
•新增模板字符串:(可嵌套)
•新增数据类型Symbol:(undefined、null、Boolean、String、Number、Object)?
•新增Proxy(语言层操作对象):
·正则扩展:
ES5:
*构造正则函数:let regex=new
RegExp(‘要匹配字符串’, ’i’ ) ;
let regex2=new RegExp(/字符串/i) ;括号内只允许一个参数
*测试:regex.test(‘xyz123’) regex2.test(‘xyz123’)
*修饰符:a) i表示不区分大小写
b) g表示是否全局
* .点可以代表任何字符
ES6:
*构造正则函数: let regex3=new
RegExp(/字符串/ig,’i’) ;括号内允许两个参数
*测试:regex3.flags; //第二个参数的修饰符会覆盖第一个参数的修饰符
*.flags是获取正则的修饰符
*新增修饰符: a) y与g相比,都是全局匹配
不同的是:g可以接着上一次匹配,直到匹配到为止
y是紧接着上一次匹配的位置,匹配不上就over,匹配得上就输出。
*新增sticky检测是否用了y修饰符
a1.strick //false
a2.strick //true
b) u处理/ unicode / 例:/\u{61}/u.test(‘a’);
* .点不再代表任何字符,小于0xffff 的Unicode字符
(字符Unicode编码超过两个字节 便没法识别了,超过的可以加u修饰)
·字符串扩展:(这里需要安装并引入babel-polyfill库兼容ES7)
*Unicode编码大于0xffff时,用{}包裹编码(如:’\u{20BB7}’)
一个汉字占两个字节16位,超出部分也算两个字节
*文字转成unicode编码:
ES5:charAt(0/1/2) charCodeAt(0/1/2)
ES6:codePointAt() codePointAt().toString(16)//转换成16进制
*unicode码转化成文字:(区别在能否处理大于0xffff的unicode字符)
ES5:String.formCharCode(“0x20bb7”);
ES6:String.formCodePoint(“0x20bb7”);
*遍历unicode编码的方法:
*判断字符串中是否包含某些字符:includes()
eg:var str=“string”; str.includes(‘r’) //true
*判断字符串是否以XX为起始/结束的:startWidth()endWidth()
eg:var str=“string”;
str.startWidth(‘str’)//true
str.endWidth(‘ng’) //true
*重复字符串:repeat()
eg:let str=’abc’;str.repeat(2); //abcabc
*模板字符串:用``包裹模板,用${}包裹数据
eg:let name=’list’;
let info=’helloworld’;
let modual=`I am${name},${info}`;
*ES7草案增加:需要安装npm install babel-polyfill --save-dev并引入js文件内
·补白[从前]padStart(‘长度’,‘补白内容’)
·补白[从后]padEnd(‘长度’,‘补白内容’)常用语日期07.12
·标签模板:处理多语言转化,过滤一些前面的字符串
·转义raw()
eg:console.log(String.raw`Hi\n${1+2}`) // Hi\n3
console.log(`Hi\n${1+2}`) //Hi回车3
·数值扩展:
*输出二进制:console.log(0b111110111); //503
*输出八进制:console.log(0o767); //503
*判断数字是否为有穷:Number.isFinite(158/0) //false(NaN)
*判断是不是数组:Number.isNaN(NaN) //true
*判断是不是个整数:Number.isInteger(25.0) //true
*判断存储范围是否在(-2^53-2^53)之间:Number.isSafeInteger(a) 数字//false
*判断带小数的整数部分并返回:Math.trunc(4.1) //4
*判断数字是正数负数或0:Math.sign(5/-5/0/’50’/’foo’) //-1/1/0/1/NaN
*立方根:Math.cbrt(-1/8) //-1/2
·数组扩展:
*把一组数据变量转化成数据类型Array.of(3,4,5,6) //[3,4,5,6]
*伪数组或集合转化成数组:Array.from(一个参数)
(如.querySelectorAll(‘p’);返回的是集合)
let p = document.querySelectorAll(‘p’);
let pArr=Array.from(p); //将p集合转化成数组
pArr.forEach(function(item){ //遍历操作数组
console.log(item.textContent);
})
*映射,类似map:Array.from(多个参数)
Array.from( [1,3,5] , function(item){
returnitem*2 //2,6,10
}) //把第一个参数的数组重新遍历一遍执行函数内(映射)
*填充数组(数组内所有数据被改变):fill(‘替换内容’,起始位置,替换长度)
[1,’a’,undefined].fill(7) //7,7,7
[‘a’,‘b’,‘c’].fill(7,1,3); //a,7,7
*数组的遍历:(let XX of []是遍历数组中的XX)
·let…of…配合key() :返回所遍历数组的索引
for(letindex of [‘1’,’c’,’ks’].keys()){
console.log(index); // 0,1,2
}
·let…of…配合values() :返回所遍历数组的值
for(let index of [‘1’,’c’,’ks’].values()){
console.log(index); // 1,c,ks
}
·let…of…配合entries()
:返回所遍历数组的索引和值
for(letindex of [‘1’,’c’,’ks’].entries()){
console.log(index,value); //01,1c,2ks
}
·当前数组内部,把指定位置成员赋给其他位置上
copyWidth(开始替换d位置,开始读数据d位置,中止读数据d位置)
[1,2,3,4,5].copyWithin(0,3,4) // [4,2,3,4,5]
·数组中查找一个元素:(只找到一个元素后便返回) :find()
[1,2,3,4,5,6].find(function(item){returnitem>3}) //4
·数组中查找一个元素的索引:(只找到一个元素后便返回其索引):findIndex()
[1,2,3,4,5,6].findIndex(function(item){returnitem>3}) //3
·数组中是否包含一个元素:(只找到一个元素后便返回) :includes()
[1,2,NaN].includes(1/NaN) // true / true
·函数扩展:
*函数参数默认值:
eg:function test(x,y=’world’){console.log(x,y)}
test(‘hello’); //hello,world
test(‘hello’,’kill’); //hello, kill
注:默认值后的参数不能再用没默认值的变量(即:不能在参数y=‘world’后面加一个没有默认值的参数,可以加z=’haha…’)
*函数作用域:
let x=’haha’; let x=’haha’;
function test(x,y=x){ function test(c,y=x){
console.log(x,y); console.log(x,y);
} }
test(‘kill’) //kill kill test(‘kill’) //kill haha
*把一系列调用函数时的参数转化为数组:rest参数(…):
function test(…arg){
for(let v oforg){
console.log(v);
}
} test(1,2,3,4,’a’); //1,2,3,4,a
注:rest参数后不能有别的参数了
*扩展运算符(rest逆向:把数组拆成离散的值):
console.log(…[1,2,4]); //1 2 4
console.log(‘a’,…[1,2,4]); //a1 2 4
*箭头函数:!
等号前是函数名,箭头前是参数(无参是用()代替),箭头后是返回值
let arrow = v=> v*2
arrow(3) //6
*伪调用:(提升性能,函数嵌套时使用)
functiontail(x){console.log(x)}
function fx(x){returntail(x)}
fx(123) //123
·对象扩展:(不是类生成的,而是Object) key必须是字符串
*简洁表达:
let o=1,k=2; let o=1,k=2;
let es5={ let es6={
o:o, o,
k:k, k,
hello:function(){ hello(){
} }
} }
*属性表达式:
let a=’b’;
let es5={ letes6={
a:’c’, [a]:’c’
b:’c’
}; } //Object{b:c}
*判断字符串是否相等:Obeject.is(‘’,’’) 相当于===
数组是引用类型,引用地址不同,判断数组相等,返回false
*拷贝(浅复制):Object.assign({a:’a’},{b:’b’}) //object{a:’a’,b:’b’}
浅复制:引用类型只拷贝引用地址,不拷贝值
这个方法只拷贝自身,不会拷贝继承、不可枚举的属性
*拷贝(浅复制):entries()配合遍历(见数组扩展部分)
·运算符扩展:(不兼容)
let{a,b,…c}={a:’test’,b:’kill’,c:’ddd’,d:’ccc’}
c={
c:’ddd’,
d:’ccc’
}
·Symbol数据类型:
Symbol数据类型提供一个独一无二的值(永远不相等,独一无二)用for… in…或者let…of…都拿不到值
用法1:
let a1=Symbol(); //声明
let a2=Symbol();
用法2:有key值,能够再次使用
let a3=Symbol.for(‘a3’);
let a4=Symbol.for(‘a3’);
console.log(a3===a4) //true
用途:let a1=Symbol.for(‘abc’) //’abc’为键值对中的key
let obj={
[a1]:’123’,
‘abc’:345,
‘c’:456
} console.log(obj); //都能取到
·let…of和for…in只拿得到非Symbol变量,
·解决let…of和for…in拿不到Symbol变量问题:(只拿到Symbol变量)
Object.getOwnPropertySymbols(obj).forEach(function(item){…..})
·以上两种都拿到:
Reflect.ownKeys(obj).forEach(function(item){……})
·数据结构:(增删改查)
·Set数据结构:(用add添加)
*size表示set类型数据长度,set类似于数组,但重复的数据不算(利用set做到去重)
new Set ( )
eg:let arr = [1,2,3,1,2] ;
letlist=new Set(arr);
console.log(list); //1,2,3
letarr1 = [1,2,3,1,’2’];
letlist1=new Set(arr1);
console.log(list1) //1,2,3,”2”
*add添加 list1.add(5); //1,2,3,“2”,5
*delete删除list1.delete(5); //1,2,3,”2”
*clear清空 list1.clear(); // [ ]
*has包含 list1.has(5); // false
*读取(用let of遍历,不论遍历.key()还是.values(),都返回其value本身;或用xxx.forEach()遍历)
·WeakSet数据结构:(与set支持的数据类型不同,它只支持对象,与垃圾回收不挂钩)
*只能add对象,其他类型不支持
*不能遍历
*没有clear方法
*没有set属性
·Map数据结构:(用set添加)
*map中的key可以是任何数据类型,不单单是String
1.let map = new Map(); 2.letmap = new Map([[‘a’,123],[‘b’,456]]);
let arr=[‘123’];
map.set(arr);
*size获取map的长度
*get获取某元素eg:map.get(arr);
*delete删除元素
*clear清空元素
*遍历:与set一样
·WeakMap数据结构:(与set支持的数据类型不同,它只支持对象)
*只能add对象,其他类型不支持
*不能遍历
*没有clear方法
*没有set属性
·Map与Array的对比:
Map 数组
let map=new Map(); let array=[];
*增: map.set(‘t:1’); array.push({t:1});
*删: map.delete(‘t’); let X=array.findIndex(item=>item.t); array.spliice(index,1)
*改: map.set(‘t’,2) array.forEach(item=>item.t?item.t=2:’’);
*查: map.has(‘t’); //true或false array.find(item=>item.t);//返回存在的值
·Set 与Array的对比:
Set 数组
let set=new Set(); let array=[];
*增: set.add({t:1}); array.push({t:1});
*删: set.forEach(item=>item.t?set.delete(item):’’);
let X=array.findIndex(item=>item.t); array.spliice(index,1)
*改: set.forEach(item=>item.t?item.t=2:’’);
array.forEach(item=>item.t?item.t=2:’’);
*查: set.has(‘t:1’);//true或false array.find(item=>item.t);//返回存在的值
·Map / Set 与Object的对比:
letitem={t:1}; let map=new Map(); let set=new Set(); letobj={}
Map Set Object
*增: map.set(‘t’,1) set.add(item) obj[‘t’]=1
*删: map.delete(‘t’) set.delete(item) delete obj[‘t’]
*改: map.set(‘t’,2) item.t=2直接修改数据 obj[‘t’]=2;
*查: map.has(‘t’) set.has(item) ‘t’ in obj
*建议:优先使用map,如果对数据要求唯一性使用set,放弃使用object和Array
·Proxy与Reflect (两者的方法一模一样)
* Proxy: 代理商,连接用户和最真实的对象中间的层
* Reflect: 反射,反射的是object
方法:get / set / has /
deleteProperty / ownKeys。。。。
•Proxy实例:
[if !vml]
[endif][if !vml]
[endif]
•Reflect实例:
[if !vml]
[endif]
·Proxy与Reflect使用场景:(与业务解耦的数据校验模块)
[if !vml]
[endif] [if !vml]
[endif]
接图中实例:
person.name=48; //报错(正常ES5修改对象属性是不报错的)
这是因为Person中的构造函数返回的不是this,而是this的代理
即,validator返回的是代理
·类与对象:
·类的创建与实例化:
类里有构造函数,不再需要function(){this.XXX},只需要class关键字
class Parent{
constructor(name=’hanna’){
this.name=name;
}
} let parentHan=new Parent(‘hanliu’); //Parent{name:”hanliu”}
·继承(extends)
//继承class Parent{
constructor(name='parent'){
this.name=name;
}
}
class Child extends Parent{
}
console.log('继承',new Child());
·继承(修改)传递参数[继承修改父类属性]:super(需要传递父类的属性列表)
新定义自己属性要用this关键字,this要在super后
//继承传递参数 即是修改、新建参数class Parent{
constructor(name='parent'){
this.name=name;
}
}
class Child extends Parent{
constructor(name='child'){
super(name);
this.type='child';
}
} //new
的实例中所带的参数 会覆盖构造函数里的参数console.log('继承传递参数',new Child());
·类中的getter和setter :(定义的是属性!而不是方法,形式与方法类似)
// 类中的setter与getter
class Parent{
constructor(name='parent'){
this.name=name;
}
get longName(){
return 'Miss'+this.name;
}
set longName(value){
this.name=value;
}
}
let v=new Parent();
console.log('getter',v.longName); //Missparent
v.longName='hello';
console.log('setter',v.longName); //Misshello
静态属性和静态方法是通过类调用,而不是通过类的实例来调用
·静态方法:(static)
//静态方法class Parent{
constructor(name='parent'){
this.name=name;
}
static talk(){
console.log('静态方法:I am taking!');
}
}
Parent.talk();
·静态属性:(没有关键词)
//静态属性class Parent{
constructor(name='parent'){
this.name=name;
}
static talk(){
console.log('静态方法:I am taking!');
}
}
Parent.
type='test';
console.log('静态属性:',Parent.type);
·Promise异步编程的解决方案:
·异步:A执行完后执行B
·传统怎样实现异步:(通过回调 / 通过事件触发)
//模拟传统的ajax
let ajax=function (callback) {
console.log('执行');
setTimeout(function () {
callback && callback.
call()
},
1000);
};
ajax(
function () {
console.log('timeout1')
});
·Promise实现异步:
let ajax=function () {
console.log('执行2');
//返回 Promise 实例
return new Promise(function (resolve,reject) {
// resolve 执行下一步操作
// reject中断当前操作
setTimeout(function () {
resolve()
},
1000);
})
};
// ajax()执行后返回Promise实例,实例有.then的方法(表示执行下一步)
ajax().then(function () {
console.log('promise','timeout2');
},resolve(XXX),reject(XXX))
·Promise.all ( [ XX ] ) 把多个Promise实例当做一个实例,all里传数组,当数组内所有Promise实例完成后,新的Promise实例才会发生变化(Promise.all整体才会触发then()方法)
Promise.all([
loadImg(
'http://i4.buimg.com/567571/df1ef0720bea6832.png'),
loadImg(
'http://i4.buimg.com/567751/2b07ee25b08930ba.png'),
loadImg(
'http://i2.muimg.com/567571/5eb8190d6b2a1c9c.png')
]).
then(showImgs)
·Promise.race ( [ XX ] )
·Promise.all()与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();
}
})
}
functionshowImgs(imgs) {
imgs.
forEach(function (img) {
document.body.appendChild(img);
})
}
//所有图片加载完后再添加到页面
Promise.
all([
loadImg(
'http://i4.buimg.com/567571/df1ef0720bea6832.png'),
loadImg(
'http://i4.buimg.com/567751/2b07ee25b08930ba.png'),
loadImg(
'http://i2.muimg.com/567571/5eb8190d6b2a1c9c.png')
]).
then(showImgs)
// 只要有图片加载完就添加到页面
Promise.race([
loadImg(
'http://i4.buimg.com/567571/df1ef0720bea6832.png'),
loadImg(
'http://i4.buimg.com/567751/2b07ee25b08930ba.png'),
loadImg(
'http://i2.muimg.com/567571/5eb8190d6b2a1c9c.png')
]).
then(showImgs)
·Iterator和for…of循环(操作数据结构:数组、object、Map、Set)
·Iterator接口:读取数据集合(数组、object、Map、Set)它是Symbol的方法
arr[Symbol.iterator]( ) ; //对数组使用Iterator接口
let arr=['hello','world'];
let map=arr[Symbol.iterator]();
console.log(map.next()); //{value: "hello", done: false}
console.log(map.next()); //{value: "world", done: false}
console.log(map.next()); //{value: undefined, done: true}
·for…of循环:不同的数据结构通过for…of不断调用不同的literaor接口,达到读取数据结构集合,对象不能用for…of获取,需要部署Iterator接口
·自定义Iterator接口,使得可以使用for…of循环
Iterator方法最终要return返回一个对象,这个对象一定要有next方法
let obj={
start:[1,3,2],
end:[7,9,8],
[Symbol.
iterator](){
let self=this;
let index=0;
let arr=self.start.concat(self.end);
let len=arr.length;
return {
next(){
if (index
return {
value:arr[index++],
done:false //表示未结束
}
}
else{
return{
value:arr[index++],
done:true //表示结束
}
}
}
}
}
}
for (let key of obj){
console.log(key) }
·Generator函数:异步编程的一种解决方案(类似Promise,更高级)
需要引入babel èèè !!!import 'babel-polyfill';
·generator基本定义:
let tell=function *() {
yield 'a';
yield 'b';
return 'c'; }
对象不能用for…of获取,需要部署Iterator接口 (generator比部署接口要结简单)
let obj={};
obj[Symbol.iterator]=function* () {
yield 1;
yield 2;
yield 3;
}
for (let value of obj){
console.log('value',value);
}
·generator与Iterator接口的关系:
·generator状态积:
let state=function* () {
while (1){
yield 'A';
yield 'B';
yield 'C';
}
}
let status=state();
console.log(status.next()); //{value: "A", done: false}
console.log(status.next()); //{value: "B", done: false}
console.log(status.next()); //{value: "C", done: false}
console.log(status.next()); //{value: "A", done: false}
console.log(status.next()); //{value: "B", done: false}
·抽奖generator :
let draw=function (count) {
//具体抽奖逻辑
console.info(`剩余${count}次`)
}
//全局对象存储次数,太不安全,尽量避免把数据存储在全局变量中,用generator解决
let residue=function* (count) {
while(count>0){
count--;
yield draw(count);
}
}
let star=residue(5);
let btn=document.createElement('button');
btn.id='start';
btn.textContent='抽奖';
document.body.appendChild(btn);
document.getElementById('start').addEventListener('click',function () {
star.next();
},
false)
·长轮询generator(前端实时取得服务器端数据的变化):
//长轮询let ajax=function* () {
yield new Promise(function (resolve, reject) {
setTimeout(function () {
resolve({
code:0})
},
200);
}) }
[if !vml]
[endif]
·Decorator :(修饰器)是函数,修改类的行为(拓展类的功能)
只在类中其作用,为类拓展功能,除babel-polyfill,还需要额外安装插件
npm install babel-plugin-transform-decorators-legacy–save-dev
同时需要修改babelrc文件: 加上"plugins": ["transform-decorators-legacy"]
//限制某个属性是只读的let readonly=function (target, name, descriptor) {
descriptor.
writable=false;
return descriptor;
};
class Test{
@readonly //
为这个类添加行为
time(){
return '2017-03-11'
}
}
let test=new Test();
console.log(test.time()); //2017-03-11
test.time-function () {
console.log('reset time:');
};
//报错,只读属性不能修改
可以在类里面使用,也可以在类外部使用(但一定要在类的前面)
let typename=function (target,name,descriptor) {
target.
myname='hello';
}
@typename
class Test{
}
console.log('类修饰符',Test.myname);
本例中,target指的是类本身,所以的target.属性 都是静态属性,需要用类来访问,而不是用实例来访问。
·Decorator 修饰器的第三方库:(core-decorators)
第三方库的安装:npminstall core-decorators
安装后 直接@XXX 即可
·Decorator应用:(日志统计)
[if !vml]
[endif]
·模块化:功能单一
模块的引入和导出:import 和 export
·文件1.js(导出) 文件2.js(导入)
//导出属性 //导入属性、函数以及类
export let A=123; import {A,test,Hello} from ‘./路径’
//导出函数 import {A} from ‘./路径’
export function test(){ import * as XX from ‘./路径’
console.log(‘test’); console.log(lesson.A);//从导入的所有元素
} 中取出想要的元素
//导出类
export classHello{
test(){
console.log(‘class’);
}
}
·推荐使用方式:
//导出没有名字的对象 //引入没有名字的对象
export default{ import XX from ‘. /路径’
A, console.log(XX.A,XX.test);
test,
Hello
}
注意:类中不一定要有构造函数,类中只有方法,没有属性的时候不需要构造方法
方法声明:方法名(参数){ },且方法与方法之间没有逗号隔开
Promise:解决回调问题,解决异步处理问题
箭头函数的this指向: 需要在箭头函数外层,用变量保留this,是因为:箭头函数的this指向指的是定义时,而不是运行时。