【js重学系列】作用域

摘要:
作用域在JavaScript中,作用域为可访问变量,对象,函数的集合。因为局部变量只作用于函数内,所以不同的函数可以使用相同名称的变量。函数作用域是指声明在函数内部的变量,和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部。局部变量在函数执行完毕后销毁。值得注意的是,每一个子函数都会拷贝上级的作用域,形成一个作用域的链条。一个作用域下可能包含若干个上下文环境。

作用域

在 JavaScript 中, 作用域为可访问变量,对象,函数的集合。

在 Javascript 中,作用域分为 全局作用域函数作用域

什么是作用域呢,简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。

全局变量

变量在函数外定义,即为全局变量。

全局变量有 全局作用域: 网页中所有脚本和函数均可使用。

如果变量在函数内没有声明(没有使用 var 关键字),该变量为全局变量。

全局作用域

在代码中任何地方都能访问到的对象拥有全局作用域:

  • 在函数外面定义的变量拥有全局作用域

  • 所有末定义直接赋值的变量自动声明为拥有全局作用域

  • 所有window对象的属性拥有全局作用域

局部变量

变量在函数内声明,变量为局部变量。

局部变量:只能在函数内部访问。

因为局部变量只作用于函数内,所以不同的函数可以使用相同名称的变量。

局部变量在函数开始执行时创建,函数执行完后局部变量会自动销毁。

函数作用域

是指声明在函数内部的变量,和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部。

变量生命周期

  • JavaScript 变量生命周期在它声明时初始化。
  • 局部变量在函数执行完毕后销毁。
  • 全局变量在页面关闭后销毁。
  • 函数参数只在函数内起作用,是局部变量。
  • 在 HTML 中, 全局变量是 window 对象: 所有数据变量都属于 window 对象。
			var b = 1;
			function a() {
				var c=1;
				console.log('b:',++b);
				console.log('c:',++c);
			}
			a() //b: 2 c: 2
			a() //b: 3 c: 2
			a() //b: 4 c: 2
可以看出变量的生命周期,局部变量在函数执行时创建,执行完毕后销毁,所以每次调用都是开辟新的内存地址,都是新的值,全局变量在页面关闭后销毁,所以每次调用都会累加值

作用域链

当访问一个变量时,解释器会首先在当前作用域查找标示符,如果没有找到,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链。

值得注意的是,每一个子函数都会拷贝上级的作用域,形成一个作用域的链条。

var x = 1;
var y = 1;

function demo() {
    var x = 2

    function demo2() {
        var x = 3;
        console.log(x); //3
        console.log(y); //1
    }
    demo2()
}
demo()

块级作用域

for (var i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i);  //333
    },2000)
}
for (let i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i);  //012
    },2000)
}
块级作用域的理解:
var定义的没有块级作用域,循环三次结束后,才会执行定时器里的回调函数,然后找到父级作用域,由于父级作用的i没有块级作用域,所以访问父级的i的时候,i的值已经变成了3
let定义的又块级作用域,去找父级的i的时候i的值时每次循环传入的值,不会被后面的更改,所以能输出012

作用域与执行上下文的区别

作用域和执行上下文之间最大的区别是: 执行上下文在运行时确定,随时可能改变;作用域在定义时就确定,并且不会改变

一个作用域下可能包含若干个上下文环境。有可能从来没有过上下文环境(函数从来就没有被调用过);有可能有过,现在函数被调用完毕后,上下文环境被销毁了;有可能同时存在一个或多个(闭包)。同一个作用域下,不同的调用会产生不同的执行上下文环境,继而产生不同的变量的值

词法作用域与动态作用域

词法作用域就是静态作用域

因为 JavaScript 采用的是词法作用域,函数的作用域在函数定义的时候就决定了。

而与词法作用域相对的是动态作用域,函数的作用域是在函数调用的时候才决定的。动态作用域只是一个相对概念,理解即可

var value = 1;
function foo() {
    console.log(value);
}
function bar() {
    var value = 2;
    foo();
}
bar();

// 结果是 ???  1  js采用词法作用域 所以打印1

value=1
function foo () {
    echo $value;
}
function bar () {
    local value=2;
    foo;
}
bar // bash 就是动态作用域 所以会输出2

参考

https://juejin.cn/post/6844903797135769614#heading-4
https://www.zhihu.com/question/28976647?sort=created

免责声明:文章转载自《【js重学系列】作用域》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇pg gem 安装(postgresql94)通过grep,awk,sed的简单应用获取网卡信息。下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

js 清空文本框

js清空文本框: TextBox 服务器,客户端都清空   /// <summary>    /// 清空文本框    /// </summary>    /// <param name="controls"></param>    public void EmptyTextBox(ControlColle...

freemarker常见语法大全

FreeMarker的插值有如下两种类型:1,通用插值${expr};2,数字格式化插值:#{expr}或#{expr;format} ${book.name?if_exists } //用于判断如果存在,就输出这个值 ${book.name?default(‘xxx’)}//默认值xxx ${book.name!"xxx"}//默认值xxx ${book...

js获取图片信息(一)-----获取图片的原始尺寸

如何获取图片的原始尺寸大小?   如下,当给 img 设置一个固定的大小时,要怎样获取图片的原始尺寸呢? #oImg{ 100px; height: 100px; } <img src="images/test.jpg" id="oImg" alt=""> 方法一: HTML5提供了一个新属性 naturalWi...

前端模块化详解(完整版)

前言 在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可;如今CPU、浏览器性能得到了极大的提升,很多页面逻辑迁移到了客户端(表单验证等),随着web2.0时代的到来,Ajax技术得到广泛应用,jQuery等前端库层出不穷,前端代码日益膨胀,此时在JS方面就会考虑使用模块化规范去管理。本文内容主要有理解模块化,为什么要模块化,模块化...

iframe中插入代码并执行

最近有需求通过iframe插入代码。有蛮多方法,如下: 1 var iframe = document.getElementById('previewUrl'); 2 iframe.src = 'about:blank'; 3 iframe.contentWindow.document.body.innerHTML+="12312" 4 iframe.co...

【cocos2d-js官方文档】二十四、如何在android平台上使用js直接调用Java方法

在cocos2d-js 3.0beta中加入了一个新特性,在android平台上我们可以通过反射直接在js中调用java的静态方法。它的使用方法很简单: var o = jsb.reflection.callStaticMethod(className, methodName, methodSignature, parameters...) 在callS...