认识Javascript中的作用域和作用域链
作用域
只要写过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中的作用域和作用域链的更多相关文章
- 深入理解javascript中执行环境(作用域)与作用域链
深入理解javascript中执行环境(作用域)与作用域链 相信很多初学者对与javascript中的执行环境与作用域链不能很好的理解,这里,我会按照自己的理解同大家一起分享. 一般情况下,我们把执行 ...
- JavaScript中的原型、原型链、原型模式
今天,咱来聊聊JavaScript中的原型跟原型链 原型跟原型模式 这一块的知识,主要是设计模式方面的. 首先,我们知道JavaScript是面向对象的.既然是面向对象,那它自然也有相应的类跟对象等概 ...
- JavaScript 中的闭包和作用域链(读书笔记)
要想理解闭包,应当先理解JavaScript的作用域和作用域链. JavaScript有一个特性被称之为“声明提前(hoisting)”,即JavaScript函数里声明的所有变量(但不涉及赋值)都被 ...
- JavaScript中的闭包和作用域链
这部分几乎是JavaScript中最难的部分,也是面试官最爱问的地方. 下面的内容是我以前写的<JavaScript学习手册>中被客户删除的部分,理由听起来有点诡异:太难.
- Javascript中没有块级作用域(模仿)
在C/C++中,由花括号封闭的代码块都有自己的作用域,也就是块级作用域(私有作用域).而在javascript中则没有块级作用域,首先来看一段代码: function test(){ for(var ...
- javascript中执行环境和作用域(js高程)
执行环境(execution context,为简单起见,有时也成为“环境”)是javascript中最为重要的一个概念.执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为.每个执行环境 ...
- 一篇文章带你了解JavaScript中的变量,作用域和内存问题
1 在JavaScript中的变量分别区分为两种: 一种为基本类型值,一种为应用类型值. 基本类型值指的是简单的数据段 引用类型值为可能由多个值组成的对象 引用类型的值是保存在内存中的对象,JavaS ...
- javascript中模仿块级作用域
学过 javascript 的都知道 javascript 里面没有块级作用域的概念,这就意味着在块语句中定义的变量,实际上是在包含函数中而非语句中创建的,看下面的例子: function outPu ...
- JavaScript中的继承(原型链)
一.原型链 ECMAScript中将原型链作为实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 实例1: function SupType() { this.pro ...
- JavaScript中的继承与原型链
先看一个例子 function User(){} var u1 = new User(); console.log(u1.prototype);// undefined 使用对象实例无法访问到prot ...
随机推荐
- golang xpath解析网页
https://github.com/antchfx/htmlquery package main import ( "fmt" "github.com/antchfx/ ...
- Flink on Yarn三部曲之一:准备工作
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- 【计算几何 05】Pick定理
什么是Pick定理(皮克定理) 来自wiki的介绍: 给定顶点座标均是整点(或正方形格子点)的简单多边形,皮克定理说明了其面积 \(A\)和内部格点数目 \(i\) .边上格点数目 \(b\) 的关系 ...
- JS的各种数据类型
Number js与其他编程不一样,不管是整数还是浮点,都称为数字类型(Number) 例:123,1.11111,-960 当该类型结果不存在时,即表示为 NaN (Not a Number) In ...
- 几道php反序列化题目
[极客大挑战 2019]PHP 提示源码泄漏,来用扫描器扫一下 扫出来www.zip,然后下载下来 有五个文件,代码审计一下 这个地方有一个可以反序列化的点,找到类 逻辑很简单,username=ad ...
- CentOS7 安装telnet-0.17-64.el7.x86_64
1.安装客服端,服务端,xinetd yum -y install telnet telnet-server xinetd 以上要想完成telnet安装,telnet服务端和xinetd必须安装,至于 ...
- Cocos2d-x extensions库使用问题解决方法
需要在加入头文件#include "cocos-ext.h" 1>e:\cocos\cocos2d-x\cocos2d-x-3.10\extensions\gui\cccon ...
- 详解MapReduce(Spark和MapReduce对比铺垫篇)
本来笔者是不打算写MapReduce的,但是考虑到目前很多公司还都在用这个计算引擎,以及后续要讲的Hive原生支持的计算引擎也是MapReduce,并且为Spark和MapReduce的对比做铺垫,笔 ...
- viewpage轮播图
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com ...
- 05 . Go+Vue开发一个线上外卖应用(Session集成及修改用户头像到Fastdfs)
用户头像上传 功能介绍 在用户中心中,允许用户更换自己的头像.因此,我们开发上传一张图片到服务器,并保存成为用户的头像. 接口解析 在用户模块的控制器MemberController中,解析头像上传的 ...