摘要:返回的遍历器对象,可以依次遍历函数内部的每一个状态。以后,每次调用遍历器对象的方法,就会返回一个有着和两个属性的对象。由于函数就是遍历器生成函数,因此可以把赋值给对象的属性,从而使得该对象具有接口。
let 和 const 作用域的概念
全局作用域
函数作用域
块作用域
如何使用let和const
1、形成块级作用域
2、es6下强制开启严格模式,而在es5下,需要"use strice"才能开启严格模式;
1、声明的常量不能修改;但是对象可以修改,因为对象是对地址的引用,我们可以在内存空间中更改对象
function last() { const k={ a:1 }; k.a=123; console.log(k) }
2、声明的时候,必须赋值;
3、const也有块作用域的概念;
Symbol的作用:避免属性名相同的问题
注意:对象中,有用到symbol做key值的话,是取不到的;即let...of只能拿到非Symbol对象的值;
let a1=Symbol.for("abc"); let obj={ [a1]:"123", "abc":345, "c":456 }; console.log(obj) for(let [key,value] of Object.entries(obj) ){ console.log("let of",key,value) }
解决办法:通过以下代码可以取到Symbol的值;Object.getOwnPropertySymbols可以拿到Symbol对象的值;
Object.getOwnPropertySymbols(obj).forEach(function (item) { console.log(obj[item]) })
返回了所有key和value值;通过es6最增的Reflect.ownKeys(obj)
Reflect.ownKeys(obj).forEach(function (item) { console.log(item,obj[item]) });//返回了所有key和value值;Set的用法
Set的用法:set数据类型的元素,必须是唯一的;添加重复的元素不会报错,只是不会生效;
他在转换元素的时候,不会进行数据类型的隐式转换;
可以用它来去重;
let arr=[1,2,3,4,2,1,2,3,2]; let list=new Set(arr); console.log(list)Set()实例的方法:
1、add() 添加元素
2、delete() 移出
3、clear() 清空
4、has() 判断元素中是否有某个内容
let arr=["add","delete","clear","has"]; let list=new Set(arr); console.log(list.has("add")) console.log(list.delete("add"),list) console.log(list.clear(),list)Set实例的遍历
//1:遍历属性名
for(let key of list.keys()){ console.log(key) }
//2:遍历属性值 for(let value of list.values()){ console.log(value) } //3:遍历属性名和属性值 for(let [key,value] of list.entries()){ console.log(key,value) }Set实例的 forEach
list.forEach(function (item) { console.log(item) })WeakSet的用法
let weakList=new WeakSet()
WeakSet和set的区别:1、WeakSet和set支持的数据类型不一样;
2、WeakSet中的对象都是若引用;不会检测地址是否被垃圾回收掉;
3、他的属性,没有size属性,没有clear方法,不能遍历;
map的属性名可以是任意数据类型;
map增加值,用set,获取值用get
map的两种写法
//第一种写法:
let map=new Map();
let arr=["123"];
map.set(arr,456);
console.log("map",map,map.get(arr))
//第二种写法
let map=new Map([["a",123],["b",456]])
console.log(map)
map常用的属性值和方法
map.size 长度
set设置,get获取
delete() 删除; clear()清空
WeakMap的用法
前者接收的值只能是对象
他没有set属性,不能使用clear()
不能遍历; 跟weakSet和set的区别一样;
//数据结构横向对比,增,查,改,删 let map=new Map(); let ary=[]; //增 map.set("t",1); ary.push({t:1}); //console.info("map-array",map,ary) //查 let map_exits=map.has("t"); let ary_exites=ary.find(item=>item.t); /*console.log(map_exits) //返回true,表示存在 console.log(ary_exites) //返回当前对象*/ //改 map.set("t",2); ary.forEach(item=>item.t?item.t=2:""); console.log(map,ary) //删除 map.delete("t"); let index=ary.findIndex(item=>item.t); ary.splice(index,1); console.log(map,ary)
Set与Array的对比
let set=new Set(); let ary=[]; let item={t:1}; //增加 set.add(item); ary.push({t:1}) console.log(set,ary) //查 let set_exist=set.has(item); let ary_exist=ary.find(item=>item.t) console.log(set_exist,ary_exist) //改 set.forEach(item=>item.t?item.t=2:""); ary.forEach(item=>item.t?item.t=2:""); //删 set.forEach(item=>item.t?set.delete(item):""); let index=ary.findIndex(item=>item.t) ary.splice(index,1) console.log(set,ary)数据结构- 和对象Object的对比
###Map,Set与Object的对比 //map,set,object对比 let item={t:1}; let set=new Set(); let map=new Map(); let obj={}; //增 map.set("t",1); set.add(item); obj["t"]=1; console.log("map-set-obj",map,set,obj) //查 console.info({ map_exist:map.has("t"), set_exist:set.has(item), obj_exist:"t" in obj }) //改 map.set("t",2); item.t=2; obj["t"]=2; console.log("map-set-obj",map,set,obj) //删 map.delete("t") set.delete(item) delete obj["t"]; console.log("map-set-obj",map,set,obj)
小总结:数据开发中,涉及数据结构,能使用map,不使用数组;如果对数据要求比较高,比如数据唯一性,考虑使用
类 类的基本定义和生成实例: classclass Parent{ constructor(name="leilei"){ this.name=name; } } let v_parent=new Parent("ymy"); console.log(v_parent.name)类的继承: extends
class Parent{ constructor(name="leilei"){ this.name=name; } } class Child extends Parent{ //继承:子类怎么在自己的构造函数中传递参数 constructor(name="child"){ super(name);//如果不传参,子类使用的是父类默认的参数;super一定放在构造函数的第一行; this.type="child"; } } console.dir(new Child("hello"))
类中的getter和setter
分别用来获取属性和设置属性
class Parent{ constructor(name="leilei"){ this.name=name; } get longName(){ return "ymy "+this.name; } set longName(value){ this.name=value; } } // 创建实例 let p1=new Parent(); console.log(p1.longName) //获取属性 p1.longName="tangtang"; //设置属性
给类中添加静态方法 static
注意:static属性只能用来设置类的静态方法,不能用来设置类的静态属性
类的静态属性只能通过: 类.key=value;来设置
类的静态方法,只有类能使用,实例不能使用,实例只能使用原型上的属性和方法;
class Parent{ constructor(name="leilei"){ this.name=name; } //设置静态方法 static tell(){ console.log("tell"); } } Parent.sex="gril"; //设置类的静态属性 Parent.tell() //调用类的静态方法;es6 Iterator 和 for...of 循环 什么是Iterator接口
ES6中内置了一些Symbol,其中最重要的一个恐怕就是Symbol.iterator了,相当于迭代器的接口,只有对象里有这个symbol的属性,才可以认为此对象是可迭代的。
我们先看一下规范中对这个symbol的描述:
A method that returns the default Iterator for an object. Called by the semantics of the for-of statement.
js中哪些对象里实现了这个接口呢?常见的有Array,String,arguments,还有后面高级的数据结构,如Set,Map等。
for...of
for...of循环的过程,其实就是通过不断调用Iterator接口来达到这种形式;
也就是说,不同的数据结构,通过for...of这种统一的形式,来达到读取不同数据结构的目标;但是背后的Iterator接口其实不同;
数组自动帮我们带了iterator接口
let arr=["hello","world"]; let map=arr[Symbol.iterator](); console.log(map.next()); console.log(map.next()); console.log(map.next());
Object {value: "hello", done: false};done代表,是否做完了所有操作,true:代表是; false:代表无,还有其他操作;
Object对象不是一个iterator,那么如何把它变成一个iterator呢?
let obj={ start:[1,3,2], end:[7,8,9], [Symbol.iterator](){ let self=this; let index=0; let arr=self.start.concat(self.end); let len=arr.length; return { next (){ if(indexlet...of的使用
let arr=["hello","world"]; for(let value of arr){ console.log(value); }Generator 基本概念Generator函数有多种理解角度。从语法上,首先可以把它理解成,Generator函数是一个状态机,封装了多个内部状态。
执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历Generator函数内部的每一个状态。
形式上Generator函数是一个普通函数,但是有两个特征。
function关键字与函数名之间有一个星号*;
函数体内部使用yield语句,定义不同的内部状态(yield语句在英语里的意思就是“产出”)。let tell=function* () { yield "a"; yield "b"; yield "c"; }; let k=tell(); console.log(k.next()); console.log(k.next()); console.log(k.next()); console.log(k.next());上面代码定义了一个Generator函数tell,它内部有三个yield语句"a","b"和"c" ; 即该函数有三个状态:"a","b"和"c"语句(结束执行)。
总结一下,调用Generator函数,返回一个遍历器对象,代表Generator函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield语句后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。true:表示遍历结束,false:表示遍历没结束;
yield需要注意的是,yield语句后面的表达式,只有当调用next方法、内部指针指向该语句时才会执行,因此等于为JavaScript提供了手动的“惰性求值”(Lazy Evaluation)的语法功能。
function* gen() {
yield 123 + 456;
}
上面代码中,yield后面的表达式123 + 456,不会立即求值,只会在next方法将指针移到这一句时,才会求值。yield语句注意事项
yield语句不能用在普通函数中,否则会报错。
yield语句如果用在一个表达式之中,必须放在圆括号里面。
console.log("Hello" + yield); // SyntaxError
console.log("Hello" + yield 123); // SyntaxErrorconsole.log("Hello" + (yield)); // OK
console.log("Hello" + (yield 123)); // OK
yield语句用作函数参数或赋值表达式的右边,可以不加括号。
foo(yield "a", yield "b"); // OK
let input = yield; // OK
暂缓执行函数Generator函数可以不用yield语句,这时就变成了一个单纯的暂缓执行函数。
function* f() { console.log("执行了!") } var generator = f(); setTimeout(function () { generator.next() }, 2000);上面代码中,函数f如果是普通函数,在为变量generator赋值时就会执行。但是,函数f是一个Generator函数,就变成只有调用next方法时,函数f才会执行。
Generator 与 Iterator接口的关系
任意一个对象的Symbol.iterator方法,等于该对象的遍历器生成函数,调用该函数会返回该对象的一个遍历器对象。
由于Generator函数就是遍历器生成函数,因此可以把Generator赋值给对象的Symbol.iterator属性,从而使得该对象具有Iterator接口。
//generator对象的新应用:给obj对象部署Iterator;
let obj={}; obj[Symbol.iterator]=function* () { yield 1; yield 2; yield 3; }; for(let value of obj){ console.log(value); }用Generator写抽奖
let draw=function (count) { //具体抽奖逻辑 console.info(`剩余${count}抽奖次数`); }; let residue=function* (count) { while(count>0){ count--; yield draw(count); } }; let star=residue(5); let btn=document.createElement("button"); btn.innerHTML="点击抽奖"; document.body.appendChild(btn); btn.onclick=function () { star.next(); }前端定时的去接收服务端的变化
两种办法:1)websocket-兼容性不好 ; 2)常轮询-看如下代码
let ajax=function* () { yield new Promise((resolve,reject)=>{ setTimeout(function () { resolve({code:0}) },200) }) }; let pull=function () { let generator=ajax(); let step=generator.next(); //拿回后台的数据 step.value.then(function (d) { if(d.code!=0){ setTimeout(function () { console.info("wait"); pull(); },1000) }else{ console.log(d); } }) }; pull();
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/88702.html
摘要:本套课程包含两大部分,第一部分是基础部分,也是重要部分,参考官方文档结构,针对内容之间的关联性和前后顺序进行合理调整。 showImg(https://segmentfault.com/img/bVbpBA0?w=1460&h=400); 讲师简介: iview 核心开发者,iview-admin 作者,百万级虚拟渲染表格组件 vue-bigdata-table 作者。目前就职于知名互...
摘要:那么什么是基础对象组件呢,举两个例子我们再来看看属性访问器,就是括号操作符及点号操作符都做了什么属性访问器也就是说括号跟点号对解释器而言是一样的。 ES规范解读之赋值操作符&属性访问器 原文:https://github.com/kuitos/kuitos.github.io/issues/24事情起源于某天某妹子同事在看angular文档中关于Scope的说明Understandin...
摘要:所以这是一篇插队的文章,用于去理解中的装饰器和概念。因此,该的作用就是根据入参返回具体的描述符。其次局部来看,装饰器具体应用表达式是,其函数签名和是一模一样。等装饰器语法,是和直接使用是等效等价的。 ================前言=================== 初衷:以系列故事的方式展现 MobX 源码逻辑,尽可能以易懂的方式讲解源码; 本系列文章: 《【用故事解...
摘要:最近开始看源码,并将源码解读放在了我的计划中。相对于其他源码解读的文章,基本都会从整体设计开始讲起,楼主觉得这个库有点特殊,决定按照自己的思路,从用代替说起。源码没有出现注意,其实有出现一处,是为,而不是,而用代替之。 Why underscore 最近开始看 underscore源码,并将 underscore源码解读 放在了我的 2016计划 中。 阅读一些著名框架类库的源码,就好...
阅读 2366·2023-04-26 02:54
阅读 2284·2021-10-14 09:43
阅读 3300·2021-09-22 15:19
阅读 2816·2019-08-30 15:44
阅读 2684·2019-08-30 12:54
阅读 957·2019-08-29 18:43
阅读 1916·2019-08-29 17:12
阅读 1307·2019-08-29 16:40