美文网首页
JS之作用域与提升

JS之作用域与提升

作者: 一只记录成长的小鱼 | 来源:发表于2018-10-08 00:38 被阅读0次

Scope

  • Variable Lifetime
  • Lexical Scoping(var): from when they are declared until when their function ends
  • Block Scoping(const, let): until the next } is reached
  • const和let的区别:
const thisIsAConst = 50;
thisIsAConst ++ //Error!!!

let thisIsALet = 50;
thisIsALet = 51; // 完全可行

//But! 不能用let声明同一个变量两次
//而用var则不会出现问题
let thisIsALet = 50; //Error!!! 

!注意!const和let的区别在于前者用于声明常量,其所指向内存的位置(reference)不可改变,但后者let则用于声明变量。

用const定义对象后修改对象的属性

此例中的obj虽然是用const定义的,但是之后却可以修改其属性,因为obj是对象,修改属性并没有改变它在内存里存储的位置(reference), 因此是可行的。

那么Lexical Scoping和Block Scoping的区别在哪呢?我们再来看下一个例子,来猜猜看console运行的结果是什么:

console.log(thisIsALet); //???结果是什么
let thisIsALet = 50;
thisIsALet = 51;

很多有些JS基础的人仔细看过会认为答案是undefined,但是实际结果却显示如下:


Error

为什么?
因为let声明的拥有块级作用域(block scoping),它只作用于被声明处到下一个}之前,及时let声明的是全局变量,它也存在于一个看不见的块级作用域中,绝不可能作用于声明前的作用域。因此当JS引擎从第一行开始执行代码时,并不认识thisIsALet,所以引擎显示出错误。

但是如果用var来声明,那么我们就可以得到之前所猜想的答案:

console.log(thisIsAVar); //undefined
var thisIsAVar = 50;

之所以console的结果是undefined而不是50,是因为在声明thisIsAVar时变量的名字得到了提升(undefined),而赋值没有

  • Hoisting提升
  • Function definitions are hoisted, but not all lexically-scoped intializations.
thisIsHoisted();

function thisIsHoisted() {
  console.log('This is a function declared at the bottom of a file');
}

此处函数thisIsHoisted() 的声明得到了提升,所以即使是在声明之前安排执行此函数,也是可行的。

  • 只有声明会被提升,而任何赋值或者其他执行逻辑都会被留在原处。同理,函数声明会被提升,但是函数表达式不会。(注意!只有用var声明的变量可以被提升,用constlet声明则引擎会提示错误)。
thisIsHoisted();

var thisIsHoisted = function() {
  console.log('should this be hoisted?');
}
TypeError
注意,此处的出现的结果是TypeError,因为它所被提升的值是undefined,并不是函数,所以用函数的方式去执行它,便会出现TypeError。再来看一下如果用const或者let声明变量结果是什么:
thisIsHoisted();

const thisIsHoisted = function() {
  console.log('should this be hoisted?');
}
ReferenceError
正如前文所说到的,constlet没有提升的功能,因此当想在其被真正声明之前调用变量,这些变量是不存在的,所以出现ReferenceError。
  • 出现ReferenceError是因为作用域解析失败,而TypeError暗示着作用域解析成功了,但是试图对这个结果进行了一个非法/不可能的操作(比如将一个非函数的值作为函数运行,或者引用null或者undefined值得属性)。

相关文章

  • 作用域与变量提升

    作用域与变量提升 作用域 JS中变量的作用域有全局作用域和局部作用域两种,作用域简单来讲就是变量与函数的可访问范围...

  • js 的变量提升和函数提升

    1. 深入理解 js 的变量提升和函数提升 先了解:js没有块级作用域,只有全局作用域,和函数作用域 相同的函数名...

  • JS 提升

    变量提升即将变量声明提升到它所在作用域的最开始的部分 在 js 中只有两种作用域,全局作用域和函数作用域,在ES6...

  • 变量作用域

    变量作用域:静态作用域、动态作用域JS变量作用域:JS使用静态作用域JS没有块级作用域(全局作用域、函数作用域等)...

  • JavaScript作用域学习笔记

    @(JS技巧)[JavaScript, 作用域] JavaScript作用域学习笔记 概念: 作用域就是变量与函数...

  • JS作用域的练习

    Js作用域练习demo1 Js作用域练习demo2 JS作用域练习demo3 JS作用域练习demo4 JS作用域...

  • JS之作用域与提升

    Scope Variable Lifetime Lexical Scoping(var): from when t...

  • 老司机也翻车的闭包

    前置知识 es6之前,js中变量作用域分为两种:全局作用域、局部作用域。学习闭包之前需要先了解作用域及变量提升的概...

  • 你不知道的JS-上卷

    作用域整体理解:JS作用域分为函数作用域,全局作用域,with和try catch形成的块级作用域。 JS引擎在编...

  • JS 闭包(Closure)

    参考阮一峰老师的JS 闭包 理解闭包前需要理解变量作用域、变量提升 JS作用域 那如何让它依次打印,12345呢;...

网友评论

      本文标题:JS之作用域与提升

      本文链接:https://www.haomeiwen.com/subject/dsalaftx.html