ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

作用域与上下文

2022-08-08 10:30:17  阅读:188  来源: 互联网

标签:function 函数 作用域 var 上下文 变量


作用域与上下文

由于 JavaScript 语言的特性,函数可以被自由的调用,这种设计模式衍生出 作用域执行上下文(简称上下文)的概念。

  • 作用域(scope)是一系列方法内可调用到的变量,对象,方法组成的集合。此种集合的范围基于函数(function-based)。

  • 上下文(context)是当前 代码解析和执行 所在环境的一种抽象概念,是方法调用的主体,方法中的 this 所代表的值。该取值基于对象(object-based)。

全局作用域

全局作用域在页面开启时产生,页面关闭时销毁。其他局部作用域的存在可以避免与全局作用域的命名标识符冲突(局部变量和全局变量)。

函数作用域(局部作用域)

函数作用域于函数调用时生成,执行结束后销毁。

块级作用域(es6)

{} 体内的执行语句,constlet 声明的变量为块级作用域,而 var 声明的变量与 function 声明的函数依旧在其父作用域中。

  • {} 语句(非 object)
  • ifswitch{} 语句
  • forwhiledo{} 语句
  • trycatch{} 语句
  • with{} 语句

全局上下文

底层上下文,如浏览器中的 window 对象和 nodejs 中的 global

函数上下文

函数调用的主体。函数存在定义时上下文与运行时上下文,通过callapply改变。

eval 函数的上下文

  • eval函数将参数字符串转换为执行脚本
  • eval函数可以被赋值,当eval被赋值时,也会把当前eval所处的变量作用域也赋值过去。
var x = 1,
  evalg = eval;
function a() {
  var x = 3;
  eval('alert(x)'); //3
  evalg('alert(x)'); //1
}
  • IE9 之前的浏览器没有全局eval的概念, 但是可以用 execScript 来代替。
var x = 1;
(function() {
  (!-[1] ? execScript : eval)('var x = 123;');
})();
console.log(x);

执行栈

执行栈用于存储代码运行时所创建的上下文。与其他语言的调用栈相同,是先进后出的数据结构。

JavaScript 引擎第一次遇到你的脚本时它会创建一个全局上下文并且压入当前执行栈。

当执行函数时引擎为其增加一个新的局部上下文压入栈的顶。

函数执行结束时,该函数上下文从栈中弹出。

上下文的生命周期

  1. 创建阶段:

    • 创建变量对象
    • 建立作用域链
    • 确定 this 指向
  2. 执行阶段:

    • 变量赋值
    • 函数引用
    • 执行代码
  3. 执行完毕

    • 移出执行栈等待回收

变量查找

作用域中的变量查找遵循先局部后全局的规则,当前作用域的变量不存在将在父级函数的作用域查找,依次向上直至顶层作用域。该规则也称为作用域链

闭包

通过一个执行函数返回另一个的自定义函数的程序设计方式。

  • 由于 作用域链 的机制,闭包提供了让外部函数访问另个一函数内部变量的功能,从而达到内部封装外部访问的目的,不同场景下的闭包使用根据这一机制也有不同的使用方式。
const getter = (function() {
  let a = 1;
  return function() {
    return a;
  };
})();
getter(); // 1
  • 由于闭包返回的自定义函数是通过计算获取而非声明,每次获取时都会开辟新的内存地址,且该内存空间将长期占用可能导致内存泄露。

变量提升(预解析)

指变量、函数的声明被提升至作用域的顶部。

  • 同一个变量只声明一次,同标识符的声明被忽略。
  • 变量赋值不提升。
  • 函数声明优先于变量声明,且函数将连带定义一起被提升。(未声明与未定义的区别体现为:未定义的变量返回 undefined,而未声明则抛出异常,如:XX is not defined)
a = 1;
console.log(a);
var a;
//输出为1
var a = 1;
function log() {
  console.log(a);
  var a;
}
_print();
//输出为undefined print函数将变量a的声明提升,取的是函数内a的值
_print();
function _print() {
  console.log('可提升');
}
// 可提升
_print();
var _print = function() {
  console.log('不可提升');
};
//  Uncaught TypeError: _print is not a function
  • let、const 的变量提升

    在 es6 之前没有块级作用域,var 变量在声明时将自动赋值 undefined,而 let、const 仅声明不赋值但依旧存在变量提升。

let a = 1;
{
  console.log(a);
  let a;
}
//Uncaught ReferenceError: Cannot access 'a' before initialization

标签:function,函数,作用域,var,上下文,变量
来源: https://www.cnblogs.com/qingzhao/p/16560913.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有