首页 > 语言 > JavaScript > 正文

ES6所改良的javascript“缺陷”问题

2024-05-06 14:52:40
字体:
来源:转载
供稿:网友

块级作用域

ES5没有块级作用域,只有全局作用域和函数作用域,由于这一点,变量的作用域甚广,所以一进入函数就要马上将它创建出来。这就造成了所谓的变量提升。

ES5的“变量提升”这一特性往往一不小心就会造成一下错误:

1.内层变量覆盖外层变量

var tmp = new Date();function f() {console.log(tmp);if (false) { //执行则undefinedvar tmp = "hello world";}}

2.变量泄露,成为全局变量

var s = 'hello';for (var i = 0; i < s.length; i++) {console.log(s[i]);}console.log(i); // 5

往常我们往往是使用闭包来解决这一问题的(比如自执行函数)。现在,基于这一问题,ES6增加了块级作用域,所以不再需要自执行函数了。

let 和 const

ES6是是向后兼容的,而保持向后兼容性意味着永不改变JS代码在Web平台上的行为,所以var创建的变量其作用域依旧将会是全局作用域和函数作用域。这样以来,即使拥有了块级作用域,也无法解决ES5的“变量提升”问题。所以,这里ES6新增了俩个新关键词:let和const。

1.let

“let是更完美的var”,它有着更好的作用域规则。

2.const

const声明一个只读的常量。一旦声明,常量的值就不能改变,但const声明的对象可以有属性变化(对象冻结Object.freeze)

const a = [];a.push('Hello'); // 可执行a = ['Dave']; // 报错

也可以使用Object.freeze将对象冻结

const foo = Object.freeze({});// 常规模式时,下面一行不起作用;// 严格模式时,该行会报错foo.prop = 123;//

使用let和const:

•变量只在声明所在的块级作用域内有效

•变量声明后方可使用(暂时性死区)

•不能重复定义变量

•声明的全局变量,不属于全局对象的属性

var a = 1;window.a // 1let b = 1;window.b // undefined

this关键字

我们知道,ES5函数中的this指向的是运行时所在的作用域。比如

function foo() {setTimeout(function(){console.log('id:', this.id);}, 100);}var id = 21;foo.call({id:42});//id: 21

在这里,我声明了一个函数foo,其内部为一个延迟函数setTimeout,每隔100ms打印一个this.id。我们通过foo.call({id:42})来调用它,并且为这个函数设定作用域。它真正执行要等到100毫秒后,由于this指向的是运行时所在的作用域,所以这里的this就指向了全局对象window,而不是函数foo。这里:

•使用call来改变foo的执行上下文,使函数的执行上下文不再是window,从而来辨别setTimeout中的this指向

•setTimeout方法挂在window对象下,所以其this指向执行时所在的作用域——window对象。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选