php块级作用域,思维脑图+代码示例让作用域到作用域链的知识点一目了然!

46d8c5764b94df0b579b09ae7ca89e35.png

作用域作用域的篇幅不会太长,作为自己对Js总结的第三篇文章,主要是承上启下。

之后会涉及到执行上下文,闭包等相关专题,为了避免内容过多,作用域这一部分单独总结。

目录前言

一、作用域的定义

二、理解作用域

三、作用域链

四、思考与总结

五、写在最后

前言

fc1a103790af9e8c9b3ea32610919a14.png

JavaScript内功系列:this指向详解,思维脑图与代码的结合,让你一篇搞懂this、call、apply。系列(一)

从原型到原型链,修炼JavaScript内功这篇文章真的不能错过!系列(二)

本文

一、作用域的定义

一张导图概括本节内容

4fdcfc4405c11b3fc1ebcd9f50a36abf.png

注意:除了作用域,在此送大家2020最新企业级 Vue3.0/Js/ES6/TS/React/Node等实战视频教程,点击此处免费获取,小白勿进哦

1.1 常见的解释一段程序代码中所用到的名字并不总是有效,而限定它的可用性的范围就是这个名字的作用域;

作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限;

通俗的讲作用域就是一套规则,用于确定在何处以及如何查找某个变量的规则function func(){

var a = 100;

console.log(a); // 100}console.log(a) // a is not defined a变量并不是任何地方都可以被找到的

1.2 JavaScript中作用域工作模型

JavaScript 采用是词法作用域(lexical scoping),也就是静态作用域:函数的作用域在函数定义的时候就决定了

与之对应的还有一个动态作用域:函数的作用域是在函数调用的时候才决定的;

1.3 全局变量和局部变量

根据定义变量的方式又可以分为:

局部变量:只能在函数中访问,该函数外不可访问;定义在函数中的变量function fn(){

var name = '余光';

console.log(name);}console.log(name); // ?fn(); // ?

全局:任何地方都能访问到的对象拥有全局作用域。函数外定义的变量

所有末定义直接赋值的变量自动声明为拥有全局作用域var a = 100;console.log('a1-',a);function fn(){

a = 1000;

console.log('a2-',a);}console.log('a3-',a);fn();console.log('a4-',a);

注意:在ES6之后又提出了块级作用域,它们之间的区别我们之后再来讨论。

273886f7d8a4f9611b0f6442cf29574b.png

二、理解作用域

根据第一节的描述,我们一一验证一下

2.1 理解词法作用域var value = 1;function foo() {

console.log(value);}function bar() {

var value = 2;

foo();}bar();

我们结合定义去分析:执行bar函数,函数内部形成了局部作用域;

声明value变量,并赋值2

执行foo函数,函数foo的作用域内没有value这个变量,它会向外查找

根据词法作用域的规则,函数定义时,foo的外部作用域为全局作用域

打印结果是1

如果是动态作用域的话:结果就是2,不知道你是否想明白了?

2.2 全局变量var str = '全局变量';function func(){

console.log(str+1);

function childFn(){

console.log(str+2);

function fn(){

console.log(str+3);

};

fn();

};

childFn();}func();// 全局变量1// 全局变量2// 全局变量3

再来分析下面的代码:var a = 100;function fn(){

a = 1000;

console.log('a1-',a);}console.log('a2-',a);fn();console.log('a3-',a);// a2- 100 // 在当前作用域下查找变量a => 100// a1- 1000 // 函数执行时,全局变量a已经被重新赋值// a3- 1000 // 全局变量a => 1000

2.3 局部作用域

局部作用域一般只在固定的代码片段内可访问到,最常见的就是以函数为单位的:function fn(){

var name="余光";

function childFn(){

console.log(name);

}

childFn(); // 余光}console.log(name); // name is not defined

三、作用域链

3.1 当查找变量的时候都发生了什么?会先从当前上下文的变量对象中查找;

如果没有找到,就会从父级(词法层面上的父级)执行上下文的变量对象中查找;

一直找到全局上下文的变量对象,也就是全局对象;

作用域链的顶端就是全局对象;

这样由多个执行上下文的变量对象构成的链表就叫做作用域链,从某种意义上很类似原型和原型链。

3.2 作用域链和原型继承查找时的区别:查找一个普通对象的属性,但是在当前对象和其原型中都找不到时,会返回undefined

查找的属性在作用域链中不存在的话就会抛出ReferenceError。

3.3 作用域嵌套

既然每一个函数就可以形成一个作用域(词法作用域 || 块级作用域),那么当然也会存在多个作用域嵌套的情况,他们遵循这样的查询规则:内部作用域有权访问外部作用域;

外部作用域无法访问内部作用域;(真是是这样吗?)

兄弟作用域不可互相访问;

在《你不知道的Js》中,希望读者可以将作用域的嵌套和作用域链想象成这样:

cf5417aae31c31f9bf9aa87fb193a9bc.png

四、思考与总结

4.1 总结

10daded7dc5fd1828d82098178e2c8a6.png

4.2 思考

最后,让我们看一个《JavaScript权威指南》中的两段代码:var scope = "global scope";function checkscope1(){

var scope = "local scope";

function f(){

return scope;

}

return f(); // 注意}checkscope1();var scope = "global scope";function checkscope2(){

var scope = "local scope";

function f(){

return scope;

}

return f;}checkscope2()();

两段代码的结果都是"local scope",书中的回答是:JavaScript 函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数 f() 定义在这个作用域链里,其中的变量 scope 一定是局部变量,不管何时何地执行函数 f(),这种绑定在执行 f() 时依然有效。

但是它们内部经历的事情是一样的吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值