好程序员web前端带你了解JS的作用域链

简介: 好程序员web前端带你了解JS的作用域链,我们都知道js是一个基于对象的语言,系统内置各种对象。 而window作为一个天然存在的全局对象,它承担了所有全局资源的存储。 我们使用的任何全局变量,都是window下的。

好程序员web前端带你了解JS的作用域链,我们都知道js是一个基于对象的语言,系统内置各种对象。
 
而window作为一个天然存在的全局对象,它承担了所有全局资源的存储。
 
我们使用的任何全局变量,都是window下的。也就是说,在js中,实际上没有任何对象、方法是可以独立的,它们必须依赖于某个对象才可以被访问或执行。
 
就像alert(),它的完整写法是window.alert()
parseInt(), 完整写法是window.parseInt()
 
所有放在window对象下的资源,访问时可以默认省略window
 
但有一种情况非常特殊,例如函数中的局部变量:
function Person(){
       var name = “abc”;
}
当我们试图访问这个name属性时
console.log(newPerson().name); 
结果是undefined
我们只能在函数内部访问:
function Person(){
       var name = “abc”;
       console.log(name);
}
这种属性,在构造函数中,也被称为私有属性,我们必须提供一种对外公开的方法才可以被外界访问。例如:
function Person(){
       var name = “abc”;
       this.getName = function(){
       returnname;
}
this.setName= function(_name){
       name = _name;
}
}
这是一个典型的作用域问题, 似乎我们每个人都知道。
 
但这似乎也违反了我们的一个常识:那就是在js中,所有资源都必须依赖对象才能存在,不可独立使用。比如说:
function aaa(){
       function bbb(){  }
       bbb();
}
这段代码看上去并没有错,但是请问bbb这个函数为什么可以独立存在呢?如果我们把它换成这样:
function aaa(){
       function bbb(){  }
       window.bbb();
}
结果是运行错误!
 
那如果换成这样呢?
function aaa(){
       function bbb(){  }
       this.bbb();
}
结果还是运行错误!
 
那么我们不禁要发问了,bbb这个函数到底是属于哪个对象的?
 
当我们在调用一个函数的时候,浏览器会为这个函数的执行开辟一块内存区域用来存储这个方法在执行的临时数据。而对象作为js的基本存储单位,因此,临时数据实际上都被保存到了一个对象当中,这个对象,就是我们平时所说的执行上下文环境
 
当我们调用aaa函数时,例如window.aaa()
浏览器会为这一次函数的执行,创建一个执行上下文环境对象,我们暂时给它起个名字,叫做contextAAA吧,当然它是临时的,因为函数执行完它也就消失了。
 
那我们的代码实际上会变成这样:
function aaa(){
       function bbb(){   }
       contextAAA.bbb();
}
尽管contextAAA对象是看不见的,但它确实存在。
 
而当我们执行bbb函数时,浏览器会再次为这一次函数调用创建一个临时的执行上下文环境,我们暂且叫它contextBBB
那么contextAAA 和contextBBB以及window之间会形成链条关系,
举个例子来说明吧
var num = 888;
function aaa(){
       var num = 100;
       function bbb(){
       var num= 200;
       console.log(num);
}
bbb();
}
aaa();
那么contextAAA 如下:
contextAAA = {
       num :100,
       bbb : function(){ … },
       parentContext: window//父级上下文对象
}
那么contextBBB如下:
contextBBB = {
       num : 200,
       parentContext: contextAAA //父级上下文对象
}
因此我们发现,在父级上下文对象中,我们没有办法访问到子级上下对象,这是一个单向链表,这就是全局不能访问局部的原因。
 
而bbb函数中打印出的num应该是多少呢?这取决在上下文对象中的查找顺序,顺序大概是这样的:
首先在当前上下文对象contextBBB中,找一下有没有num变量,找到就直接打印。以我们目前的代码看,结果应该是200
我们把代码改造一下:
var num= 888;
function aaa(){
       var num = 100;
       function bbb(){
       console.log(num);
}
bbb();
}
aaa();
由于这次在contextBBB对象中找不到num变量了,因此它会从父级上下文对象中查找,也就是contextAAA里面的num,因此打印的结果是100;
我们再把代码改造一下
var num= 888;
function aaa(){
       function bbb(){
       console.log(num);
}
bbb();
}
aaa();
由于这次连contextAAA对象里也找不到了,会再次向它的父级上下文对象,也就是window查找,因此打印结果是888
 
contextAAA和contextBBB的父子关系,在你写代码的一刻就决定了,这就是作用域。
function aaa(){
       var num = 10;

       function bbb(){  console.log(num);  }
}
而代码执行时,产生的上下文对象,是链表的关系。这就是我们所说的作用域链,它的原理跟原型链是一样的。
_17
理解了这一点,也能弄明白闭包的原理。
function aaa(){
       var num = 10;
       return functionbbb(){  console.log(num);  }
}
aaa( )( )
尽管bbb函数通过return在全局范围被执行了,但作用域的链表关系并没有发生改变,因此,bbb函数依然可以访问num这个局部变量。

相关文章
|
9天前
|
编解码 前端开发 JavaScript
构建高效响应式Web界面:现代前端框架的比较
【4月更文挑战第9天】在移动设备和多样屏幕尺寸盛行的时代,构建能够适应不同视口的响应式Web界面变得至关重要。本文深入探讨了几种流行的前端框架——Bootstrap、Foundation和Tailwind CSS,分析它们在创建响应式设计中的优势与局限。通过对比这些框架的栅格系统、组件库和定制化能力,开发者可以更好地理解如何选择合适的工具来优化前端开发流程,并最终实现高性能、跨平台兼容的用户界面。
|
9天前
|
前端开发 JavaScript 关系型数据库
从前端到后端:构建现代化Web应用的技术探索
在当今互联网时代,Web应用的开发已成为了各行各业不可或缺的一部分。从前端到后端,这篇文章将带你深入探索如何构建现代化的Web应用。我们将介绍多种技术,包括前端开发、后端开发以及各种编程语言(如Java、Python、C、PHP、Go)和数据库,帮助你了解如何利用这些技术构建出高效、安全和可扩展的Web应用。
|
10天前
|
编解码 前端开发 JavaScript
Web 前端开发中的最佳实践
本文将介绍 Web 前端开发中的最佳实践,包括代码组织、性能优化、响应式设计和用户体验等方面。通过遵循这些实践,开发人员可以提高开发效率,优化用户体验,并减少潜在的问题和错误。
|
13天前
|
前端开发 JavaScript 网络协议
前端最常见的JS面试题大全
【4月更文挑战第3天】前端最常见的JS面试题大全
33 5
|
14天前
|
存储 JavaScript 前端开发
解释 JavaScript 中的作用域和作用域链的概念。
【4月更文挑战第4天】JavaScript作用域定义了变量和函数的可见范围,静态决定于编码时。每个函数作为对象拥有`scope`属性,关联运行期上下文集合。执行上下文在函数执行时创建,定义执行环境,每次调用函数都会生成独特上下文。作用域链是按层级组织的作用域集合,自内向外查找变量。变量查找遵循从当前执行上下文到全局上下文的顺序,若找不到则抛出异常。
20 6
|
29天前
|
JavaScript 前端开发 Java
纯前端JS实现人脸识别眨眨眼张张嘴案例
纯前端JS实现人脸识别眨眨眼张张嘴案例
39 0
|
3天前
|
前端开发 搜索推荐 数据安全/隐私保护
HTML标签详解 HTML5+CSS3+移动web 前端开发入门笔记(四)
HTML标签详解 HTML5+CSS3+移动web 前端开发入门笔记(四)
13 1
|
3天前
|
前端开发 JavaScript vr&ar
前端新技术探索:WebAssembly、Web Components与WebVR/AR
【4月更文挑战第12天】WebAssembly、Web Components和WebVR/AR正重塑Web应用的未来。WebAssembly允许C/C++等语言在Web上高效运行,提供接近原生的性能,如游戏引擎。Web Components通过Custom Elements和Shadow DOM实现可复用的自定义UI组件,提升模块化开发。WebVR/AR(现WebXR)则让VR/AR体验无需额外应用,直接在浏览器中实现。掌握这些技术对前端开发者至关重要。
11 3
|
7天前
|
JavaScript 前端开发 API
Vue.js:构建高效且灵活的Web应用的利器
Vue.js:构建高效且灵活的Web应用的利器
|
25天前
|
机器学习/深度学习 前端开发 算法
利用机器学习优化Web前端性能的探索与实践
本文将介绍如何利用机器学习技术来优化Web前端性能,探讨机器学习在前端开发中的应用,以及通过实际案例展示机器学习算法对前端性能优化的效果。通过结合前端技术和机器学习,提升Web应用的用户体验和性能表现。