JS 作用域链

JavaScript的作用域链是指在JavaScript中,每个函数都有一个自己的作用域,当访问一个变量时,JavaScript引擎会先在当前函数的作用域中查找该变量,如果找不到,就会到该函数的父级函数的作用域中查找,直到找到该变量或者到全局作用域中仍未找到。

举个例子来说,假设有如下代码:

javascript 复制代码
function foo() {
  var a = 1;
  function bar() {
    var b = 2;
    console.log(a + b);
  }
  bar();
}
foo();

在这个例子中,当执行bar()函数时,JavaScript引擎会先在bar()函数的作用域中查找变量b,如果找到了就直接使用;如果没找到,就会到bar()函数的父级函数foo()的作用域中查找,这时会找到变量a,所以最终输出结果为3。

如果在bar()函数中使用了一个变量c,而在foo()函数中并没有定义该变量,那么JavaScript引擎会一直向上查找到全局作用域,如果全局作用域中也没有定义该变量,那么程序就会抛出一个ReferenceError异常。


补充一下关于作用域链的一些特点:

  1. 作用域链的::顶端是全局作用域,底端是当前函数的作用域::。
  2. 当::函数执行完毕后,它的作用域链会被销毁,其中的变量也会随之被销毁::。这也是为什么在函数外部无法访问函数内部定义的变量。
  3. 在ES6之前,JavaScript中只有函数作用域和全局作用域,没有块级作用域。因此在使用for循环等语句时需要特别注意变量的作用域问题。而在::ES6中引入了letconst关键字,使得JavaScript也具有了块级作用域::。
  4. ::作用域链是在函数定义时就已经确定的,与函数的调用位置无关::。这也是为什么在JavaScript中可以使用闭包来实现一些高级的功能,比如保存一个函数的内部状态等。

补充一下关于作用域链的一些应用场景:

  1. ::闭包:::通过在一个函数内部定义另一个函数,并返回该函数的引用,可以创建一个闭包,使得::内部函数可以访问外部函数的变量::。由于JavaScript中的::作用域链是基于函数定义时的作用域::,而不是函数调用时的作用域,因此内部函数可以在外部函数执行完毕后仍然访问到外部函数的变量。
  2. ::模块化:通过使用IIFE(立即调用函数表达式)来创建一个独立的作用域::,可以将一些变量和函数封装起来,避免与其他代码产生冲突。这种模式被广泛应用于现代JavaScript开发中,比如使用Webpack等工具打包代码时就会自动将每个模块放在一个独立的作用域中。
  3. 防止变量污染:由于JavaScript中只有函数作用域和全局作用域,因此在编写大型应用程序时需要特别注意避免变量名冲突。通过::使用IIFE等方式来创建独立的作用域,可以有效地避免变量名冲突::,从而提高代码的可维护性和可重用性。

IIFE(Immediately Invoked Function Expression)是JavaScript中的一种函数表达式,它立即执行函数并返回结果。IIFE常用于创建私有作用域,避免全局命名冲突,并且可以实现模块化的代码结构。

以下是IIFE的示例代码:

javascript 复制代码
(function() {
	// 在这里编写代码
})();

在上述代码中,

  1. 函数被包含在一对圆括号中,
  2. 并紧接着使用另一对圆括号调用函数。

这样就可以立即执行函数,并且函数内部的代码在定义后立即执行。

示例1:使用IIFE创建私有作用域并避免全局命名冲突

javascript 复制代码
(function() {

var name = 'John';

function sayHello() {  
console.log('Hello, ' + name + '!');

}

sayHello();

})();

// 在这个作用域外部,无法访问name和sayHello

console.log(name); // 报错:name is not defined

sayHello(); // 报错:sayHello is not defined

在上述代码中,变量name和函数sayHello都被定义在IIFE的作用域内部,因此在IIFE外部无法访问它们。这样可以避免全局命名冲突。

示例2:使用IIFE实现模块化的代码结构

javascript 复制代码
var myModule = (function() {

var privateVariable = 'Private Variable';

function privateMethod() {  
console.log('Private Method');

}

return {  
publicMethod: function() {  
console.log('Public Method');  
},  
publicVariable: 'Public Variable'

};

})();

myModule.publicMethod(); // 输出:Public Method

console.log(myModule.publicVariable); // 输出:Public Variable

console.log(myModule.privateVariable); // 输出:undefined

myModule.privateMethod(); // 报错:myModule.privateMethod is not a function

在上述代码中,IIFE返回一个包含公共方法和公共变量的对象。这样,通过myModule对象可以访问公共方法和公共变量,但无法访问私有变量和私有方法。

通过使用IIFE,可以创建私有作用域并避免全局命名冲突,同时实现模块化的代码结构。这在编写复杂的JavaScript应用程序时非常有用。

相关推荐
奔跑吧邓邓子20 分钟前
npm包管理深度探索:从基础到进阶全面教程!
前端·npm·node.js
前端李易安40 分钟前
ajax的原理,使用场景以及如何实现
前端·ajax·okhttp
杰哥在此1 小时前
Python知识点:如何使用Multiprocessing进行并行任务管理
linux·开发语言·python·面试·编程
汪子熙1 小时前
Angular 服务器端应用 ng-state tag 的作用介绍
前端·javascript·angular.js
Envyᥫᩣ1 小时前
《ASP.NET Web Forms 实现视频点赞功能的完整示例》
前端·asp.net·音视频·视频点赞
Мартин.5 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
昨天;明天。今天。7 小时前
案例-表白墙简单实现
前端·javascript·css
数云界7 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd7 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome
安冬的码畜日常7 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine