delphi 变量为空赋值为0_小白也能懂的JavaScript变量作用域讲解(上)

本文针对JavaScript初学者,探讨变量作用域的原理,包括局部变量与全局变量的区别、变量优先级(函数内变量高于全局变量)、未声明变量提升至全局以及函数作用域的声明提前现象。通过实例解析,帮助理解变量如何在不同作用域内工作,避免变量污染和混淆。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

03f270131f1cf5fed2c083fbbd677379.png

首先,关于作用域和闭包是一个很深的问题,困扰着很多初学者,包括我在内,也在初学阶段困扰不堪,此文依据《JavaScript权威指南(第六版)》进行对作用域的浅谈,分上下两部分,上部分主要说变量优先级和变量提升以及声明提前,下部分说作用域链和闭包问题。提前说明,本文面向初学者,且不涉及es6新特性,这也是个人建议,先把es5基础打好,再慢慢的去进阶。废话不多说,正文开始。

变量作用域

一个变量的作用域是指这个变量能被调用和使用的区域,在函数内声明的变量是局部变量,作用域在函数内部,函数参数也是局部变量。全局变量则是在所有函数外被声明的变量。

函数内变量优先级

函数内的变量优先级高于全局变量,如果在函数内声明的局部变量和全局变量重名,那么在函数局部范围内,局部变量的赋值和计算将顶替全局变量原有的值,但是在函数之外继续引用全局变量,全局变量原来的值不变。

970a4ffceb286dff321d0195082a5463.png

函数内变量污染

当函数内声明变量不是采用var const let 等方式声明,而是直接创建变量时,函数内的变量将会提升为全局变量,如果存在同名的全局变量,将会污染全局变量。

这种方法可以用于函数内的变量提升。

var scope = 'global'; //创建一个全局变量
var myscope = ''
function checkscope2() {
    scope= 'local'; // 全局变量scope的值被替换成local
    var  hand = scope +'hello' // 声明局部变量赋值为 local hello
    myscope= hand; // 创建了一个全局变量,并把局部变量提升。
    return [scope,myscope];
}
console.log(checkscope2()); // 返回函数结果。
console.log(scope); // 被局部变量污染的全局变量 scope
console.log(myscope) // 等于局部变量hand
$>
[ 'local', 'localhello' ]
local
localhello

可以看到,在函数内创建变量时,不用var 声明 就会变成全局函数,而利用这种方法可以做到变量的提升。

函数内变量的嵌套

因为JavaScript在编程时经常要对函数一层层嵌套,导致了变量作用域含混不清,这里特此记一下,一个简单的实例:

var scope = ' global scopr'; // 全局变量 现在值时global scope
function checkscope(){ // 第一层函数
     var scope = 'local scope'; //第二层函数,创建了一个函数内的全局变量
     function nested(){
         var scope = 'nested scope'; // 第三层函数 创建了一个第三层函数内的局部变量
         return scope; 这里放回 socope 的结果,是netsed scope 
     }
     return nested(); 返回netstd的值 也是 netsed scope

}
console.log(checkscope())// 所以这里的值是 nested scope 

同样 如果在函数嵌套中定义了全局变量,也是会影响原有的全局变量的值。

函数作用域的声明提前

声明提前,当函数内要调用一个全局变量的变量名,并打算赋值时,由于作用域的限制,函数内的局部变量其实类似于重新创建了一个变量,仅仅时和函数外部的全局变量重名,所有的操作不影响函数外的全局变量的值(那些不采用var const let等声明方式直接进行进行创建变量并赋值的除外)而基于此原理,JavaScript有一个声明提前的特性,即

  1. 。当试图在函数内直接调用一个全局变量的时候,如果函数内有全局变量和局部变量重名,就会发生声明提前。
  2. JavaScript首先会自动创建一个为空的局部变量而非调用全局变量的值,因为是空值,所以会发生undefined

看一段代码:

var scope ="global";
function f(){
    var test = scope +"test"; // 声明一个变量,变量时test 他的值时 scope+'test'
    var scope = 'local';
    console.log(scope,test);
}
f();
$>  local undefinedtest

可以看到以上代码中,有一个全局函数 scope 他的值是global,而在第三行代码中,在函数内创建了一个变量test ,他的值理应是globaltest。但是实际上他的结果是undefinedtest。这里就是声明提前,以上代码在执行时候其实是这样的。

var scope = "global";
function f(){
    var scope;
    var test = scope+"test";
    var  scope = 'local';
    console.log(scope,test);
}
f();
$>  local undefinedtest

和上边说的一样 首先会创建一个局部变量,这就是代码执行时候的声明提前,如果换一种写法,把第五行和第四行互换一下。

var scope ="global";
function f(){
    var scope = 'local';
    var test = scope +"test";
    var scope = 'local';
    console.log(scope,test);
}
f();
$> local localtest

就会变成这样子,第四行 test变量值里的scope 已经变成了被赋值的局部函数了。

如果要实现在函数内调用全局函数的值,那就在函数内不要使用同名的全局变量,声明提前会覆盖掉全局变量的值。可以用以下方法接受全局变量的参数值。

var scope = "global";
function f(){
   var handle = scope
    var test = handle+"test";
    console.log(handle,test);
}
f();
$>global globaltest

这里就完全接受全局函数的值,如果你试图向下面那样做。

var scope = "global";
function f(){
   var handle = scope
    var test = handle+"test";
    var scope;
    scope ="local"
    console.log(handle,test);
}
f();
$>undefined undefinedtest

毫无意外的undefined。所以 在函数内如果要接受全局变量的值,不要再函数体内创建和全局变量重名的变量。

总结:

  1. 函数内局部变量优先级高,如果和全局变量重名,将会替换全局变量的值。
  2. 再函数内不用声明语句声明变量,变量将会从局部变量提升为全局变量。
  3. 函数内局部变量具有声明提前特性,如果要接收全局变量的值,局部变量不要和全局变量重名。

参考文献:

[1] 弗拉纳根(David Flanagan,美).JavaScript权威指南(第六版) 北京:机械工业出版社 , 2012.3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值