浅谈JavaScript闭包、this指针、作用域(一)

认识闭包:

闭包,是指有权限访问到其他函数作用域的变量的函数

给一个例子:

function outer () {
    var name = ‘HelloTF‘;
    return function () {
        console.log (name);
    }
}
var getName = outer();
getName();
//HelloTF

函数outer执行后返回一个内部的匿名函数,并把返回的结果赋值给全局变量result,在全局环境中在此执行result,得到了outer函数内部的变量name。

仅从闭包的定义来看并没有什么感觉,不妨从中摘出几个关键词,结合JavaScript的原理:作用域,作用链,活动对象,变量对象

作用域

在ES6之前,JavaScript没有块级作用域,经常会遇到变量提升了或者使用闭包的时候出错的问题。ES6为了解决这些问题,添加了块级作用域,此处稍后再谈。ES5中它的作用域只有两个——全局作用域和函数作用域。

全局作用域,是在全局都可以访问的,对前端开发者而言,一般指window;

函数作用域,即仅在函数{}内的代码区域,在函数内部声明的变量,在函数外是不可访问的。

这样就可以保证函数和变量的有序访问。在上述例子中,函数内部的name变量在函数体外无法直接访问,若我们必须要访问name,就得使用闭包,即返回一个匿名函数,输出name。

JavaScript保证当前执行环境下变量和函数的有序访问的原理——作用域链

不论代码是在全局还是函数的执行环境中,都会在自己的执行环境中创建一个变量对象,这个变量对象包含了当前执行环境中声明的一切变量。

比如有这么一个例子:

var outer = ‘TTF‘;
function outerFun () {
    var inner = ‘老汤‘;
    function innerFun () {
        var finaler = ‘汤瓜皮‘;
    }
}
outerFun()

以上代码有三个执行环境——全局执行环境、函数outerFun和函数innerFun的执行环境。

在全局环境中,有一个全局执行环境的变量对象(设为Q),它包含了全局执行环境下声明的一切变量。即Q:{outer,outerFun},作用域链的第一位就是Q,且Q始终存在,直到浏览器关闭的那一时刻才销毁。

在函数的执行环境中,也存在着自己的变量对象(称之为活动对象),它包含了一切在该函数的执行环境中声明的变量。如:函数outerFun,H1:{inner,innerFun};函数innerFun,H2:{finaler}。

分析函数的执行过程:

第一步,在函数创建时,就存在了一个函数的作用域链。

第二步,在函数执行时,函数创建活动对象,在函数执行的过程中,活动对象被推入到作用域链的第一位。

(函数的执行过程参考博客:https://www.cnblogs.com/bobo-site/p/9831554.html

作用域链在函数创建的那一刻就创建了,活动对象在函数执行的那一刻起才存在(执行完毕立刻销毁)

结合上述例子做一个草图:

当函数执行时,自身的活动对象被推入到函数的作用域链的第一位,而后是这个函数的外层函数的活动对象占据第二位,再然后这个函数的外层函数的外层函数的活动对象占据第三位,以此类推,直到最后作用域链的最后一位是全局变量对象。

修改之前的代码,将变量打印出来

function outerFun () {
    var inner = ‘老汤‘;
    console.log(inner)
    function innerFun () {
        var finaler = ‘汤瓜皮‘;
        console.log(finaler)
    }
}
outerFun()//老汤

最终结果不会打印“汤瓜皮”。

结合上述逻辑,函数outerFun执行时,自身活动变量推至第一位,第二位则是全局变量,因此它无法访问内部函数innerFun的变量函数innerFun只是定义而未执行。

通过这个例子可以总结:

1、函数执行时,自身的活动变量会在作用域链中占据第一位;

2、函数将按照由内至外的顺序,将外层的变量对象或者活动对象依次推入作用域链中吗。直到最后一位是全局变量对象;

3、在调用函数的变量时,JavaScript会顺着作用域链从第一位开始查找,直到在某一位找到该变量或者因为找不到而报错。

这也正是要使用闭包的原因——由于不能“从外到内”地访问作用域链上的变量对象或者活动对象,我们必须使用闭包这样的方法让一个函数可以去访问内部函数的变量并赋给外部以便外部可以访问

以上为个人理解,如有不对,请指出!

原文地址:https://www.cnblogs.com/linktodream/p/11210777.html

时间: 2024-11-08 00:23:49

浅谈JavaScript闭包、this指针、作用域(一)的相关文章

浅谈JavaScript闭包

一.背景知识 在介绍闭包之前,我觉得有必要先简单的介绍一些背景知识,如变量的作用域.嵌套函数.垃圾回收机制等概念. 1.作用域 作用域是程序运行时变量可被访问的范围,定义在函数内的的变量是局部变量,局部变量的作用域只能是函数内部范围内,它不能在函数外引用.定义在模块最外层的的变量是全局变量,它是全局范围内可见的,当然在函数里面也可以读取到全局变量的. var a = 123; //全局变量 function fun(){ var b = 456; //局部变量 } 2.嵌套函数 函数不仅可以定义

《浅谈JavaScript系列》系列技术文章整理收藏

<浅谈JavaScript系列>系列技术文章整理收藏 1浅谈JavaScript中面向对象技术的模拟 2浅谈javascript函数劫持[转自xfocus]第1/3页 3浅谈javascript 面向对象编程 4老鱼 浅谈javascript面向对象编程 5浅谈javascript的数据类型检测 6浅谈Javascript嵌套函数及闭包 7根据一段代码浅谈Javascript闭包 8浅谈JavaScript编程语言的编码规范 9浅谈Javascript面向对象编程 10浅谈JavaScript

浅谈 JavaScript 编程语言的编码规范

对于熟悉 C/C++ 或 Java 语言的工程师来说,JavaScript 显得灵活,简单易懂,对代码的格式的要求也相对松散.很容易学习,并运用到自己的代码中.也正因为这样,JavaScript 的编码规范也往往被轻视,开发过程中修修补补,最终也就演变成为后续维护人员的恶梦.软件存在的长期价值直接与编码的质量成比例.编码规范能帮助我们降低编程中不必要的麻烦.而 JavaScript 代码是直接发送给客户浏览器的,直接与客户见面,编码的质量更应该受到关注. 本文浅谈 JavaScript 编程中关

浅谈javascript单体【读javascript设计模式第五章节单体有感】

单体,整个运行环境就独有一份,最简单的一种单体就是一个把所有属性和方法都集中在一起的对象,区别于一般的字面量对象,一般字面量对象是对一个物体的描述,集合该物体所具有的一些属性和方法,而单体则包含更多的些逻辑在里面,单体的好处有,划分命名空间,如果用来作为网页包装器,可以使得页面所有变量都封装在一个对象里,大幅度减小网页里的全局变量, 代码如: common.js (function(wz){ $.extend({ init:function(){ var self = this; this.bi

浅谈javascript继承【读javascript设计模式第四章节继承有感】

javascript继承,无任是类式继承,原型式继承还是渗元式继承都是通过不同方法去围绕着prototype转,简单分析下三种不同继承方法是如何围绕prototype转的 一:类似继承,先上关键代码 function extend(subClass,supClass){ var fn = function(){}; fn.prototype = supClass.prototype; subClass.prototype = new fn(); subClass.prototype.constr

浅谈JavaScript中的原型模式

在JavaScript中创建对象由很多种方式,如工厂模式.构造函数模式.原型模式等: <pre name="code" class="html">//工厂模式 function createPerson(name,age,job) { var o = new Object; o.name = name; o.age = age; o.job = job; o.sayName = function() { alert(this.name); } retur

浅谈javascript的原型及原型链

浅谈javascript的原型及原型链 这里,我们列出原型的几个概念,如下: prototype属性 [[prototype]] __proto__ prototype属性 只要创建了一个函数,就会为该函数创建一个prototype属性,指向该函数的原型对象.实例对象是不会拥有该属性的.默认情况下,该原型对象也会获得一个constructor属性,该属性包含一个指针,指向prototype属性所在的函数. Person.prototype.constructor===Person [[proto

浅谈 “空指针、野指针、void*”

        Author: JW. Zhou Date: 2014/7/2 一.空指针(0/NULL) 返回NULL和返回0是完全等价的,因为NULL和0都表示空指针,换句话说:空指针是什么,就是一个被赋值为0的指针,在没有被具体初始化前,其值为0:NULL 是一个标准规定的宏定义,用来表示空指针常量. #define NULL 0   或者 #define NULL ((void*)0) 判断一个指针是否为空指针: f(!p) 和 if(p == NULL) ,if(NULL == p)

浅谈javascript函数劫持

http://www.xfocus.net/articles/200712/963.html 浅谈javascript函数劫持 文章提交:hkluoluo (luoluonet_at_hotmail.com) by luoluo on 2007-11-30 luoluonet_at_yahoo.cn http://www.ph4nt0m.org 一.概述 javascript函数劫持,也就是老外提到的javascript hijacking技术.最早还是和剑心同学讨论问题时偶然看到的一段代码,大