【前端工程师手册】JavaScript之作用域

简介:

【前端工程师手册】JavaScript之作用域

什么是作用域

来一段《你不知道的JavaScript-上卷》中的原话:

几乎所有编程语言最基本的功能之一,就是能够储存变量当中的值,并且能在之后对这个 值进行访问或修改,这些变量住在哪里?换句话说,它们储存在哪里?最重要的是,程序需要时如何找到它们?这些问题说明需要一套设计良好的规则来存储变量,并且之后可以方便地找到这些变量。这套规则被称为作用域

总之就是作用域就是一套规则,这个规则规定了程序如何去找到变量

词法作用域

先看一个例子:

function func1() {
    console.log(index)
}

function func2() {
    var index = 10
    func1()
}

var index = 100
func2()    // 100

为啥是100而不是10呢???
因为JavaScript是词法作用域
词法作用域简单地说就是:函数的作用域在声明的时候就决定好了。和词法作用域相对的是动态作用域,动态作用域关注函数从何处调用
上面的代码中,声明func1时,它就处于全局作用域中,所以index就是100,即使执行func1时也是。

函数作用域和块作用域

前面讲了JavaScript是词法作用域,那么什么时候会创建作用域呢???
JavaScript主要是基于函数级别的作用域,也就是每一个函数都会创建一个作用域。为什么说主要呢?因为with和try-catch语句也实现了块作用域,当然了用的很少。

var flag = true;
if (flag) {
    var num = 10
}
console.log(num)    // 10

如果有块级作用域的话,此时打印num应该报错

function funcLevelScope() {
    var index = 10
}

console.log(index);    // ReferenceError

因为是函数级别的作用域,所以在函数外面访问不到函数内部的变量

如何模拟块作用域

当然了,第一反应就是在代码外面加上包装函数不就行了,比如这样子:

function scope() {
    var flag = true;
    if (flag) {
        var num = 10
    }
}
console.log(num)    // ReferenceError

但是此时的问题就是多了一个函数包装,且我们可以随意的去运行scope函数,这可能会造成不好的影响。
自执行函数解决了这个问题:

(function scope() {
    var flag = true;
    if (flag) {
        var num = 10
    }
})()
scope()    // ReferenceError
console.log(num)    // ReferenceError

包装函数的声明以 (function... 而不仅是以 function... 开始。尽管看上去这并不 是一个很显眼的细节,但实际上却是非常重要的区别。函数会被当作函数表达式而不是一个标准的函数声明来处理。

作用域内声明提升

变量声明提升
首先明确的是

var x = 10

像这样一句代码可以分为声明和赋值两句:

var x
x = 10

明确这个概念再继续学习

console.log(x)    // undefined
var x = 10

为什么不直接报错呢?
因为上面的代码片段等于:

var x    // 声明提前
console.log(x)
x = 10

注意到变量的声明提前到了当前作用域的最前面
函数声明提升

hoist()    // hoist!
function hoist() {
    console.log("hoist!")
}

为啥函数会成功执行了,因为上面的代码片段相当于:

function hoist() {
    console.log("hoist!")
}
hoist()

函数声明被提升到了作用域的最前面
那么函数表达式会被提升吗??

hoist()    // TypeError
var hoist = function () {
    console.log("hoist")
}

因为这个相当于:

var hoist
hoist()    // TypeError
hoist = function () {
    console.log("hoist")
}

变量声明提升和函数声明提升的优先级
先说结论:函数会首先被提升,然后才是变量
看例子:

console.log(x)
var x = 10
function x() {
    console.log('func x')
}

显然此时打印的x是一个函数
这是因为上面的代码片段相当于:

function x() {
    console.log('func x')
}
var x
console.log(x)    // f x(){...}
x = 10

所以打印的是函数

原文地址http://www.bieryun.com/3863.html

相关文章
|
15天前
|
JavaScript 前端开发
js变量的作用域、作用域链、数据类型和转换应用案例
【4月更文挑战第27天】JavaScript 中变量有全局和局部作用域,全局变量在所有地方可访问,局部变量只限其定义的代码块。作用域链允许变量在当前块未定义时向上搜索父级作用域。语言支持多种数据类型,如字符串、数字、布尔值,可通过 `typeof` 检查类型。转换数据类型用 `parseInt` 或 `parseFloat`,将字符串转为数值。
18 1
|
1月前
|
存储 JavaScript 前端开发
解释 JavaScript 中的作用域和作用域链的概念。
【4月更文挑战第4天】JavaScript作用域定义了变量和函数的可见范围,静态决定于编码时。每个函数作为对象拥有`scope`属性,关联运行期上下文集合。执行上下文在函数执行时创建,定义执行环境,每次调用函数都会生成独特上下文。作用域链是按层级组织的作用域集合,自内向外查找变量。变量查找遵循从当前执行上下文到全局上下文的顺序,若找不到则抛出异常。
21 6
|
1月前
|
JavaScript
作用域和作用域链(js的问题)
作用域和作用域链(js的问题)
|
10天前
|
JavaScript 前端开发 C++
【Web 前端】JavaScript window.onload 事件和 jQuery ready 函数有何不同?
【5月更文挑战第2天】【Web 前端】JavaScript window.onload 事件和 jQuery ready 函数有何不同?
|
12天前
|
缓存 前端开发 JavaScript
【JavaScript 技术专栏】JavaScript 前端路由实现原理
【4月更文挑战第30天】本文探讨了JavaScript前端路由在SPA中的重要性,阐述了其基本原理和实现方式,包括Hash路由和History路由。前端路由通过监听URL变化、匹配规则来动态切换内容,提升用户体验和交互性。同时,文章也提到了面临的SEO和页面缓存挑战,并通过电商应用案例分析实际应用。理解并掌握前端路由能助开发者打造更流畅的单页应用。
|
13天前
|
前端开发 JavaScript 数据安全/隐私保护
前端javascript的DOM对象操作技巧,全场景解析(二)
前端javascript的DOM对象操作技巧,全场景解析(二)
|
13天前
|
移动开发 缓存 JavaScript
前端javascript的DOM对象操作技巧,全场景解析(一)
前端javascript的DOM对象操作技巧,全场景解析(一)
|
13天前
|
缓存 编解码 自然语言处理
前端javascript的BOM对象知识精讲
前端javascript的BOM对象知识精讲
|
17天前
|
前端开发 JavaScript
前端 富文本编辑器原理——从javascript、html、css开始入门(二)
前端 富文本编辑器原理——从javascript、html、css开始入门
26 0
前端 富文本编辑器原理——从javascript、html、css开始入门(二)
|
17天前
|
前端开发 JavaScript 索引
前端 富文本编辑器原理——从javascript、html、css开始入门(一)
前端 富文本编辑器原理——从javascript、html、css开始入门
36 0