javascript变量提升和闭包理解

作者:laozhang 时间:2024-04-10 16:17:06 

我们先来看一个题目:


<script>
console.log(typeof a)//undefined
var a='littlebear';
console.log(a)//littlebear
</script>
<script>
console.log(typeof a)//string
var a=1;
console.log(a)//1
</script>

第一个script里可以看出var a 被提升到顶部,a = 'littlebear'被保留在原地。

第二个script,之所以不先打印undefined ,是因为a在上面已经被var声明过,所以var a不会再次被提升。

再看一个题目:


<script>
 console.log(a)//function a(){}
 var a=1;
 console.log(a)//1
 function a(){}
 console.log(a)//1
</script>

可以看到function a(){}被提升到最顶端。说明函数的提升变量的提升

1.变量提升

在ES6之前,JavaScript没有块级作用域(一对花括号{}即为一个块级作用域),只有全局作
用域和函数作用域。变量提升即将变量声明提升到它所在作用域的最开始的部分。
上个简历的例子如:


console.log(global); // undefined
var global = 'global';
console.log(global); // global

function fn () {
console.log(a); // undefined
var a = 'aaa';
console.log(a); // aaa
}
fn();

之所以会是以上的打印结果,是由于js的变量提升,实际上上面的代码是按照以下来执行的:


var global; // 变量提升,全局作用域范围内,此时只是声明,并没有赋值
console.log(global); // undefined
global = 'global'; // 此时才赋值
console.log(global); // 打印出global

function fn () {
var a; // 变量提升,函数作用域范围内
console.log(a);
a = 'aaa';
console.log(a);
}
fn();

2.函数提升

js中创建函数有两种方式:函数声明式和函数字面量式。只有函数声明才存在函数提升!如:


console.log(f1); // function f1() {}  
console.log(f2); // undefined
function f1() {}
var f2 = function() {}

之所以会有以上的打印结果,是由于js中的函数提升导致代码实际上是按照以下来执行的:


function f1() {} // 函数提升,整个代码块提升到文件的最开始
console.log(f1);  
console.log(f2);  
var f2 = function() {}

3.什么是闭包

闭包是有权访问另一个函数作用域的变量的函数。

简单的说,Javascript允许使用内部函数---即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。

4.变量的作用域

要理解闭包,首先要理解变量的作用域。

变量的作用域无非就是两种:全局变量和局部变量。

Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。

其中内部函数中可以访问外部函数的变量,是因为内部函数的作用域链中包含了外部函数的作用域;

也可以理解为:内部函数的作用范围辐射到了外部函数的作用范围;


var n=999;
function f1(){
alert(n);
}
f1(); // 999

另一方面,在函数外部自然无法读取函数内的局部变量。


function f1(){
var n=999;
}
alert(n); // error

这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!


function f1(){
n=999;
}
f1();
alert(n); // 999

5.闭包的写法和用法


var Circle={
 "PI":3.14159,
 "area":function(r){
   return this.PI * r * r;
 }
};
alert( Circle.area(1.0) );//3.14159

刚开始我没意识到,这样写对象也是一种闭包,今天回头想想,这就是闭包的经典用发啊!

6.使用闭包的注意点

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

标签:js,变量提升,闭包
0
投稿

猜你喜欢

  • 将mysql转换到oracle必须了解的50件事

    2024-01-17 22:08:42
  • golang判断net.Conn 是否已关闭的操作

    2024-04-30 10:07:02
  • 理解HTTP消息头

    2008-12-10 14:06:00
  • 给页面 unload 加上效果

    2009-03-12 12:32:00
  • Python版的文曲星猜数字游戏代码

    2023-08-12 16:39:19
  • python闭包与引用以及需要注意的陷阱

    2022-12-13 16:01:15
  • SqlServer编写数据库表的操作方式(建库、建表、修改语句)

    2024-01-15 11:38:57
  • python解析html提取数据,并生成word文档实例解析

    2023-10-19 13:50:38
  • nonebot插件之chatgpt使用详解

    2023-07-15 09:56:17
  • VSCode远程连接服务器报错:Could not establish connection to

    2023-10-03 03:02:17
  • Numpy 三维数组索引与切片的实现

    2021-08-17 22:19:35
  • thinkphp6如何使用中间件记录行为日志

    2023-06-13 14:43:44
  • python 线程的五个状态

    2021-05-15 10:24:33
  • 如何利用Java正则表达式校验密码规则

    2022-07-22 02:05:13
  • Python使用pyyaml模块处理yaml数据

    2023-11-29 10:08:39
  • so easy!10行代码写个"狗屁不通"文章生成器功能

    2023-03-19 06:53:30
  • Python实现桌面翻译工具【新手必学】

    2021-03-27 08:32:47
  • php获取文章内容第一张图片的方法示例

    2023-11-09 18:55:14
  • Python的string模块中的Template类字符串模板用法

    2023-02-02 10:53:05
  • Python实现拓扑算法的示例

    2023-12-09 15:06:29
  • asp之家 网络编程 m.aspxhome.com