用来声明变量,可是所声明的变量只在let
命令所在的代码块内有效javascript
let不像var那样会发生变量提高,因此必定要先声明后使用。java
console.log(foo); //undefined console.log(bar); //报错ReferenceError var foo = 2; let bar = 3;
ES6明确容许在块级做用域中声明函数。可是尽可能避免在块级做用域内声明函数,若是须要也要写成函数表达式,而不是函数声明语句。数组
在ES6中,块级做用域之中,函数声明的语句的行为相似let,在块级做用域以外不能被引用。浏览器
let实际上为javascript新增了块级做用域数据结构
外层做用域没法读取内层做用域的变量闭包
内层做用域能够定义外层做用域的同名变量异步
块级做用域实际上使得普遍运用的当即执行函数变得再也不必要了。函数
function f1() { let n =5; if(rue) {let n = 10;} console.log(n); //5,注意只能在f1这个做用域使用 }
javascript没有块级做用域,可是用let
声明的变量能够绑定到所在的任意做用域中,换句话说let为其声明的变量隐式的劫持了所在的块做用域{...}
学习
var foo = true; if(foo) { let bar = foo * 2; bar = something(bar); console.log(bar); //bar只在foo做用域中有效 } console.log(bar); //ReferenceError
有兴趣的能够自行搜索了解一下TDZ(暂存死区)
,记得当时仍是看到阮大神的微博知道的~~指针
function bar(x = y; y = 2) { return [x, y]; } bar(); //报错,此时至关于y未声明的状况下
let不容许在相同做用域内重复声明同一个变量,不能在函数内部从新声明参数。const也是这样。
function(arg) {let arg; //报错}
const
一样能够建立块做用域变量,一样只在声明所在的块级做用域中有效。但其值是固定的,不可更改,只读。
一旦声明变量,就必须当即初始化,不能留到之后赋值。
//只声明不赋值就会报错 const foo; //SyntaxError:
const声明的变量也是不提高,一样存在暂时性死区,只能在声明的位置后面使用。
if(true) { console.log(MAX); //ReferenceError const MAX = 5; }
对于复合类型的变量,变量名不指向数据,而是指向数据所在的地址。const只保证变量名指向的地址不变,不保证该地址的数据保持不变。不能把foo指向另外一个地址。
const foo = {}; foo.prop = 123; foo.prop; //123 foo = {}; //TypeError:"foo" is read-only
浏览器环境指的是window对象 Node中指的是global对象
ES6中,var命令和function命令声明的全局变量依旧是顶层对象的属性,可是let和const以及class声明的全局变量不属于顶层对象的属性。
var a = 1; window.a; //1 let b = 1; window.b; //undefined
严格模式下LHS查询失败时,并不会建立并返回一个全局变量,引擎会抛出同RHS查询失败时相似的
ReferenceError
异常若是RHS查询到一个变量,尝试对这个变量的值进行不合理的操做时,好比对一个非函数类型的值进行函数调用,或者引用null或undefined类型的值中的属性,引擎会抛出另一中的异常
TypeError
ReferenceError
同做用域的判别失败有关,TypeError
则表示做用域判别成功了,可是对结果的操做是非法的或者不合理的。
查找的目的是对变量进行赋值,那么就会使用LHS查询,若是目的是获取变量的值,那么就会使用RHS查询。
像var a = 2
这样的会被分解两个步骤:(1)var a 会在做用域中声明新变量,代码执行前进行(2)a = 2 会查询(LHS)变量a并对其进行赋值。
循环和闭包
每次迭代都生成一个新的做用域,使得延迟函数的回调能够将新的做用域封闭在每一个迭代内部。
for(var i = 0; i <= 5; i++) { (functiong(j) { setTimeout(function timer() { console.log(a); }, 1000); })(i); }
var的循环,每一次循环都是新的i值覆盖旧的i值,只有一个i,因此只输出最后一个。
let的循环 每次循环都是一个新的变量i,多个i,因此会每一个都输出,每次迭代都进行从新绑定,与闭包有关
异步
最大的特色就是能够交出函数的执行权(即暂停执行)
函数名以前加星号.yield表示执行到此处,执行权将交给其余协程。
function* gen(x) { var y = yield x + 2; return y; } var g = gen(1); g.next() //{value:3,done:false} //value是yield语句后面表达式的值,表示当前阶段的值,done表示函数是否执行完毕,是否还有下一个阶段。 g.next() //{value:undefined,done:true}
调用generator函数会返回一个内部指针g,执行它不会返回结果返回的是指针对象。调用指针的g的next方法,会移动内部指针,指向第一个遇到的yield语句即x+2处。
相似于数组可是成员的值都是惟一的,没有重复的值。
var s = new Set([1,2,3,4,4]); [...s] //[1,2,3,4]
Set实例的方法
操做方法和遍历方法
操做数据
(1) 操做方法
add:添加某个值,放回set结构自己
delete:删除某个值返回一个布尔值,表示删除是否成功
has(value):返回一个布尔值,表示该值是否为set的成员
clear:清除全部成员,没有返回值
s.add(2).add(3).add(2); s.size //2 s.has(1) //false s.has(2) //true s.has(3) //true s.delete(2); s.has(2) //false
(2) Array.from方法能够将set数据结构转为数组
var items = new Set([1,2,3,4,5]); var array = Array.from(items);
(3) 扩展运算符...
也能够将某些数据结构转换一个数组
function foo() { var args = [...arguments]; } [...document.querySelectorAll("div")]
(4)数组去重的另外一种方法
function dedupe(array) { return Array.from(new Set(array)); } dedupe([1,1,2,3]) //[1,2,3]
遍历操做
keys:返回键名的遍历器
values:返回键值的遍历器
entries:返回键值对的遍历器
forEach:使用回掉函数遍历每一个成员
隐式的强制转换
3 + true; //4 NaN !== NaN; //true Null == undefined; //true
浮点数
0.1 + 0.2; //0.300000004 (8).toString(2); //"1000" parseInt("1001", 2); //9
数据类型
typeof null; //"object" typeof "hello"; //"string" var s = new String("hello"); typeof s; //"object" var s1 = new String("hello"); var s2 = new String("hello"); s1 === s2; //false s1 == s2; //false NaN !==NaN