You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
function test(){
foo(); //TypeError:'foo is not a function'
bar(); //'this will run'
var foo = function(){
alert('this won't run!');
}
function bar(){
alert('this will run!');
}
}
test();
//在TDZ内部,如果获取或设置变量将抛出异常if(true){//enter new scope, TDZ starts//Uninitialized binding for `tmp` is createdtmp='abc';console.log(tmp);//ReferenceErrorlettmp;//TDZ ends, `tmp` is initialized with `undefined`console.log(tmp);//undefinedtmp=123;console.log(tmp);//123}//死区是真正短暂的和不受位置制约的if(true){constfunc=function(){console.log(myVar);//OK};//Here we are within the TDZ and accessing `myVar` would cause a `ReferenceError`letmyVar=3;//TDZ endsfunc();//called outside TDZ}
constfoo={};foo.prop=123;foo.prop//123foo={};// TypeError: "foo" is read-only//foo存储的是一个地址,这个地址指向一个对象,不可变的知识这个地址,所以不能把foo指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性。//常量a是一个数组,这个数组本身是可写的,但是如果把另一个数组赋值给a,就会报错。consta=[];a.push('Hello');//可执行a.length=0;//可执行a=['dave'];//报错
// 方法一(typeofwindow!=='undefined'
? window
: (typeofprocess==='object'&&typeofrequire==='function'&&typeofglobal==='object')
? global
: this);// 方法二vargetGlobal=function(){if(typeofself!=='undefined'){returnself;}if(typeofwindow!=='undefined'){returnwindow;}if(typeofglobal!=='undefined'){returnglobal;}thrownewError('unable to locate global object');};
The text was updated successfully, but these errors were encountered:
ECMAScript6
简介
ES6中比较常用的10个特性为:
这些改变将给javascript开发者带来更酷的开发体验。
但是尽管很多的浏览器对ES6支持性都很好,但还是免不了要对ES6进行转码。
这就需要用到Babel——一个广泛使用的ES6转码器,可以将ES6代码转为ES5代码,从而在现有环境执行。这意味着,你可以用ES6的方式编写程序,又不用担心现有环境是否支持。
例如:
Babel的使用说明可以点击 Babel用户手册,喜欢看英文文档的可以直接点击 这里。
let和const
let、const命令的用途与var类似,都是用来声明变量的,但是现实运用中还是有差别的,请看下面例子:
因为ES5中只有全局作用域和函数作用域,没有块级作用域,所以使用var两次输出都是aaaaaa,这就会带来很多不方便的地方了:
第一种情况是:内层变量覆盖外层变量:
第二种情况是:用于计数的循环变量泄漏为全局变量。
当然我们也可以利用闭包来解决“计数循环变量泄漏为全局变量”的问题,例如:
也可利用属性方式:
let
从上面的例子可知,let命令是用来声明变量的,用法和var类似,但是let所声明的变量,只在let命令所在代码块内有效。
所以for循环的计数器就很适合使用let命令。
let命令不存在变量提升
let声明的变量存在块级作用域,函数本身的作用域,只存在其所在的块级作用域之内。
什么是变量提升呢?
上述例子中,foo()函数调用时候出错了,但是bar却能够正常调用。这是因为var foo 首先会上升到函数顶部,然而此时的foo为undefined。所以执行报错。
而对于函数bar,函数本身也是一种变量,所以能够存在变量提升现象,但是它上升了整个函数,所以bar()才能顺利执行。
上面的代码如果再ES5中运行输出的结果会是'I am outside!',因为f被条件语句中的f上升覆盖了,在ES6中输出的是'I am inside!',块级作用域中定义的函数不会影响外部。
暂时性死区
什么是暂时性死区?let和const声明的变量都拥有暂时性死区(TDZ)——当进入它的作用域,它不能被访问(获取或者设置)直到执行到达声明。
和var有何区别呢?
而通过let声明的变量拥有暂时性死区,生命周期为:
不允许重复声明
let不可以在相同作用域内重复声明同一个变量,包括不能和var、const变量名重复的变量,例如:
同样,不能在函数内部重新声明参数。
块级作用域
let为javascript新增了块级作用域。
上面函数的两个代码块都声明了变量n,运行后输出5.这表明外层代码块不受内层代码块的影响。但是如果使用var声明,那么最终输出的就是10.
块级作用域的出现,使得立即执行匿名函数不再必要了。
ES6中引入了块级作用域,允许在块级作用域之中声明函数。
ES6中规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
但是考虑到浏览器的支持情况,使用应该避免在块级作用域内声明函数,如果确实需要,也应该写成函数表达式,而不是函数声明语句。
另外,ES6的块级作用域允许声明函数的规则,只在大括号的情况下成立,如果没有使用大括号,就会报错。
const
const声明的是一个常量,也就是说const一旦声明,就必须初始化,不能留到以后赋值。
const的作用域与let相同:只在声明所在的块级作用域内有效;
const命令声明的常量也是不提升的,同样存在暂时性死区,只能在声明的位置后面使用;
const声明的常量也与let一样不可重复声明。
对于复合类型的变量,变量名不指向数据,而是指向数据所在的地址,const命令只是保证变量名指向的地址不变,并不保证该地址的数据不变。
冻结对象——Object.freeze方法
除了将对象本身冻结,还可以对对象的属性进行冻结。
顶层对象
顶层对象,在浏览器环境中指的是window,但是在Node中指的却是global对象。
在ES5中,顶层对象的属性和全局变量的属性是等价的。
ES6中规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;
let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。
同一段代码为了能够在各种环境下都能读取到顶层对象,一般使用this,但也有其局限性。
很难找到一种方法,可以在所有情况下都能读取到顶层对象,下面是两种勉强可以使用的方法:
The text was updated successfully, but these errors were encountered: