作用域

只要写过java或者c#等语言的同学来说,相信一定能理解作用域的概念,在作用域的范围中,我们可以使用这个作用域的变量,对这个变量进行各种操作。可是,当使用Javascript的时候,相信很多的同学都会遇到迷惑的时候。

例如,我们看一个常用并经典的案例。

var name = '张三';

function fun() {
console.log(name);
var name = '李四';
}
fun()

对于初识javascript的同学来说可能会认为打印的是“张三”,不过我们惊奇的发现打印的是“undefined”,下面我们来分析分析为什么会出现这样的情况。

首先,我们需要认识三个概念:全局变量、局部变量以及变量提升

全局变量

在全局定义的变量为全局变量,在这个作用环境中的所有函数对象都是可以调用到全部变量。

局部变量

顾名思义,局部变量即定义在函数内部的变量。他的作用环境局限在变量所在的局部环境中。

变量提升

在javascript中,函数和变量声明都会被提升到函数的顶部。通俗的来说就是我们可以先使用变量,然后再声明函数。

接下来,我们看看下面几个例子:

例1:

var name = "张三"
function fun() {
console.log(name);
}
fun()

显而易见,这次我们的打印结果是  “张三”。

现在我们看第二个例子:

例2:

var name = "张三"
function fun() {
console.log(name);
}
fun()

这次的结果同样是显而易见的,打印了 “张三”。

上面两个例子我们认识了全局变量和局部变量,现在我们再看看第三个例子。

例3:

function fun() {
console.log(name)
var name = "李四";
console.log(name);
}
fun()

这里就需要我们用到变量提升的概念,上面我们提到,javascript对函数和变量声明提升到函数头部,所以在执行第一次打印之前,name这个变量已经被环境帮我们声明了,但是环境并不会帮我们赋值,所以,第一次会打印undefined,然后,第二次打印“李四”。

上面的程序我们换一种写法或许更好理解。

function fun() {
var name = undefined;
console.log(name)
name = "李四";
console.log(name);
}
fun()

现在我们就可以来理解下最开始说的这个例子了。

var name = '张三';

function fun() {
console.log(name);
var name = '李四';
}
fun()

1. 在全部环境中定义了全局变量 name="张三";

2. 在局部环境中定义了name=“李四”,所以局部变量和全局变量名字相同的时候,会优先获取局部变量的值;

3. 由于我们打印name变量是在定义name之前,所以,根据变量提升的特性,所以这里我们会打印 undefined。

相信通过前面几个例子,我们对作用域已经有了一些了解,下面就对作用域进行一下总结。

概念:作用域是一种规则,是 javascript中所有可访问的变量的集合(函数,对象都是变量)。

作用:我们通过作用域可以访问权限内的所有变量,并进行相应操作。

作用域链

对于理解了javascript中的作用域之后,作用域链就是一个比较容易理解的概念。同样,我们也通过一个例子来看。

var age = 18;

function a() {
var sex = 'sex'; b();
function b() {
var color = 'green'; console.log({age, sex, color})
}
} a();

相信大家都能一样看出这段程序的输出结果是{age: 18, sex: "sex", color: "green"},虽然程序简单,不过却是我们理解作用域链的一个好例子。

我们再输出的时候会打印age,sex,color三个变量。

对于color变量来说,本来就在当前执行函数b的作用域内,所以color变量的寻找路径是b.color;

对于sex变量来说,在执行函数b的作用域中找不到sex变量,所以,他会沿着b函数的作用域链找到函数a的作用域,所以sex变量的寻找路径是 b > a.sex;

对于age变量来说,执行函数b中找不到,沿着作用域链找到a函数的作用域依然没找到,就会一直沿着作用域链找到window环境,在这里找到了变量age,所以age变量的寻找路径是b>a>window.age

通过上一个例子,我们应该可以清楚的认识作用域链是什么样的存在,同样我们也总结一下。

概念:作用域链是作用域的具体实现,通过作用域链可以确定变量被访问的权限。

作用:可以通过作用域链,了解我们在当前执行环境可以访问哪些变量。

浅陋见识,不足之处,请大神指正。

认识Javascript中的作用域和作用域链的更多相关文章

  1. 深入理解javascript中执行环境(作用域)与作用域链

    深入理解javascript中执行环境(作用域)与作用域链 相信很多初学者对与javascript中的执行环境与作用域链不能很好的理解,这里,我会按照自己的理解同大家一起分享. 一般情况下,我们把执行 ...

  2. JavaScript中的原型、原型链、原型模式

    今天,咱来聊聊JavaScript中的原型跟原型链 原型跟原型模式 这一块的知识,主要是设计模式方面的. 首先,我们知道JavaScript是面向对象的.既然是面向对象,那它自然也有相应的类跟对象等概 ...

  3. JavaScript 中的闭包和作用域链(读书笔记)

    要想理解闭包,应当先理解JavaScript的作用域和作用域链. JavaScript有一个特性被称之为“声明提前(hoisting)”,即JavaScript函数里声明的所有变量(但不涉及赋值)都被 ...

  4. JavaScript中的闭包和作用域链

    这部分几乎是JavaScript中最难的部分,也是面试官最爱问的地方. 下面的内容是我以前写的<JavaScript学习手册>中被客户删除的部分,理由听起来有点诡异:太难.

  5. Javascript中没有块级作用域(模仿)

    在C/C++中,由花括号封闭的代码块都有自己的作用域,也就是块级作用域(私有作用域).而在javascript中则没有块级作用域,首先来看一段代码: function test(){ for(var ...

  6. javascript中执行环境和作用域(js高程)

    执行环境(execution context,为简单起见,有时也成为“环境”)是javascript中最为重要的一个概念.执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为.每个执行环境 ...

  7. 一篇文章带你了解JavaScript中的变量,作用域和内存问题

    1 在JavaScript中的变量分别区分为两种: 一种为基本类型值,一种为应用类型值. 基本类型值指的是简单的数据段 引用类型值为可能由多个值组成的对象 引用类型的值是保存在内存中的对象,JavaS ...

  8. javascript中模仿块级作用域

    学过 javascript 的都知道 javascript 里面没有块级作用域的概念,这就意味着在块语句中定义的变量,实际上是在包含函数中而非语句中创建的,看下面的例子: function outPu ...

  9. JavaScript中的继承(原型链)

    一.原型链 ECMAScript中将原型链作为实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 实例1: function SupType() { this.pro ...

  10. JavaScript中的继承与原型链

    先看一个例子 function User(){} var u1 = new User(); console.log(u1.prototype);// undefined 使用对象实例无法访问到prot ...

随机推荐

  1. Spring中的一些面试题

    谈谈你对spring IOC和DI的理解,它们有什么区别? IoC [Inverse of Control] 控制反转的概念,就是将原本在程序中手动创建UserService对象的控制权,交由Spri ...

  2. 安装JDK及环境变量配置

    1.下载JDK: 下载地址:https://www.oracle.com/technetwork/java/javase/overview/index.html 2.解压,运行安装包,下一步,选择安装 ...

  3. swoft 切面AOP尝试

    官网文档 https://www.swoft.org/documents/v2/basic-components/aop/ 视频教程 https://www.bilibili.com/video/BV ...

  4. go 不停模拟 写日志

    package main import ( "os" "errors" "math/rand" "time" " ...

  5. spring boot:spring security用mysql数据库实现RBAC权限管理(spring boot 2.3.1)

    一,用数据库实现权限管理要注意哪些环节? 1,需要生成spring security中user类的派生类,用来保存用户id和昵称等信息, 避免页面上显示用户昵称时需要查数据库 2,如果需要在页面上显示 ...

  6. CentOS8平台nginx日志的定时切分

    一,编写bash脚本: [root@yjweb crontab]# vi split_nginx_logs.sh 代码: #!/bin/bash # 备份nginx的日志 # 昨天的日期 file_d ...

  7. python爬虫获取下一页

    from time import sleep import faker import requests from lxml import etree fake = faker.Faker() base ...

  8. mac 解决安卓模拟器链接不上网络

    方法1.临时方法,每次启动都要加114.114.114.114 1.进入到下面的目录 /Users/anxiaodong/Library/Android/sdk/emulator 2.执行以下命令 e ...

  9. solr之functionQuery(函数查询)【转】

    函数查询 让我们可以利用 numeric域的值 或者 与域相关的的某个特定的值的函数,来对文档进行评分. 怎样使用函数查询 这里主要有两种方法可以使用函数查询,这两种方法都是通过solr http 接 ...

  10. JAVA中Object类方法详解

    一.引言 Object是java所有类的基类,是整个类继承结构的顶端,也是最抽象的一个类.大家天天都在使用toString().equals().hashCode().waite().notify() ...