js作用域理解 function(){} var

在coding过程中遇到过下面的情况:

 1 var test1 = function(){
 2     var c=4;
 3     test2();
 4 };
 5
 6 var test2 = function(){
 7     console.log(c);
 8 };
 9
10 test1();

思考一下,7行会conasole出什么?4 吗?实际上却是 c is not defined。

而当代码如下的时候,

 1 var test1 = function(){
 2     var c=4
 3     var test2 = function(){
 4         console.log(c);
 5     };
 6
 7     test2();
 8 };
 9
10
11 test1();

或者代码如下

 1 var test1 = function(){
 2     c=4
 3     test2();
 4 };
 5
 6 var test2 = function(){
 7     console.log(c);
 8 };
 9
10 test1();

console 出的就是4。

这是为什么呢?

首先,让我们明白两个知识点:

1、js作用域:作用域就作用范围分为全局作用域和局部作用域。

A、全局作用域:从定义变量的位置开始到本源文件结束。其中 a 就是一个全局变量,作用范围全局,所以在 4 和 6 都可以 console 出 3.

 1 var a = 3;
 2
 3 var test3 = function(){
 4     console.log(a);
 5     var test4 = function (){
 6         console.log(a);
 7     };
 8     test4();
 9 };
10
11 test3();

B、局部作用域。在本函数范围内。通俗一点说,局部变量只能在定义它的函数内部使用,而不能在其它函数内使用这个变量。

 1 var test3 = function(){
 2     console.log(a);
 3     var test4 = function (){
 4         var a = 3;
 5
 6         console.log(a);
 7     };
 8     test4();
 9 };
10
11 test3();

我们把上一个代码中的 var a = 3;移到第四行,就会出现 2 行的console 中的 a 没有定义的报错,这是因为 a 是在 test4 这个函数中定义的,所以外部的函数test3不能访问包裹在里面的 test4 定义的 a。

这就又出现了一个概念:内部函数可以访问外部函数的变量,外部不能访问内部函数的变量。

 1 var test3 = function(){
 2     var a = 3;
 3     console.log(a);
 4     var test4 = function (){
 5         console.log(a);
 6     };
 7     test4();
 8 };
 9
10 test3();

我们再把 var a = 3; 移到第2行,那么就可以正常打出 3 行和 5 行的console。说明 test4 可以访问外部的 test3 的定义的变量 a。

2、 var 与不 var 的区别。有var声明的是局部变量,没var的声明的是全局变量。

 

好了 ,现在回到最开始的问题上,再贴一次代码,方便瞅。

 1 var test1 = function(){
 2     var c=4;
 3     test2();
 4 };
 5
 6 var test2 = function(){
 7     console.log(c);
 8 };
 9
10 test1();

这个是console不出来的,原因是什么呢?

总共有两个函数 test 1 和 test 2 ,各有各的局部作用域,其中 var c = 4 在 test 1 中,而非在 test 2 中,所以 test 2 不能够调用在 test 1 中的变量 c。那你会说我再第三行调用了 test 2  这个函数啊?那是因为 test2();是个指针,指向位于下方的 test 2 函数,但是指针只能调用对象的内存地址,你可以使用它的值,但你不能改变或调用其内部实现时的任何变量。简单来说,就是你只可以调用这个函数的值,但不能改变它,不能影响它。

而当没有 var 声明的时候,也就是第三段代码:

 1 var test1 = function(){
 2     c=4
 3     test2();
 4 };
 5
 6 var test2 = function(){
 7     console.log(c);
 8 };
 9
10 test1();

虽然没有 var 的字样,但并不代表它没有声明,只不过这个时候声明了一个全局变量,他的作用域是全局。所以下方的 test 2 函数可以调用 c = 4。

再或者代码如第二段:

 1 var test1 = function(){
 2     var c=4
 3     var test2 = function(){
 4         console.log(c);
 5     };
 6
 7     test2();
 8 };
 9
10
11 test1();

同理,不看 test 1 那么 就相当于

1 var c=4;
2 var test2 = function(){
3     console.log(c);
4 };
5
6 test2(); 

c 就是 全局变量,test 2 当然可以使用 c 啦~ 加上 test 1 之后,也就是对于 test 2 来说 test 1 函数内声明的变量 是个全局变量,在整个 test 1 中都可以调用。

完。

时间: 2024-12-19 00:08:33

js作用域理解 function(){} var的相关文章

谈谈我对JS作用域的理解

Javascript语言在设计之初,就将函数设计成一种包含可执行代码逻辑的特殊对象.作为对象,函数可以像普通对象变量一样拥有可以编程读写的属性,也可以像普通变量一样传递.被引用.但是问题也来了,当函数执行时,解释器如何对代码内部的标示符进行解析呢?JS是这样做的,当函数对象被创建时,或者说函数被定义时,函数对象内部不仅包含了代码逻辑,还定义了一个内部属性[[Scope]]引用了一条作用域链(可以理解成为一个对象列表).如果这个函数在全局环境下被定义,那这个作用域链里就只有全局作用域. 这样说比较

我之理解js作用域,作用域链与变量提升

function test4(){ console.log("test4:"+a) } test4(); var a=1; function test(){ var test1=function () { var test2=function () { console.log("test>test1>test2:"+a) } test2(); } test1(); } function test3(){ console.log("test3:&

js——作用域和闭包

1. js是编译语言,但是它不是提前编译,编译结果不能在分布式系统中移植.大部分情况下,js的编译发生在代码执行前的几微秒(甚至更短) 2. 一般的编译步骤 分词/词法分析:把字符串分解成词法单元 解析/语法分析:将词法单元转换成一个由元素组成的语法结构树,抽象语法树AST 代码生成:将AST转换成一组机器指令 3. 三个工具 引擎:控制整个程序的编译及执行过程 编译器:负责语法分析及代码生成等 作用域:收集并维护所有声明的标识符的访问权限 4. var a = 2 的编译过程 var a=2;

js深入理解"闭包"

一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量. Js代码 var n=999; function f1(){ alert(n); } f1(); // 999 另一方面,在函数外部自然无法读取函数内的局部变量. Js代码 function f1(){ var n=999; } alert(n); // error 这里有一个地方需要注意,函数

Js 作用域与作用域链与执行上下文不得不说的故事 ?(? ???ω??? ?)?

最近在研究Js,发现自己对作用域,作用域链,活动对象这几个概念,理解得不是很清楚,所以拜读了@田小计划大神的博客与其他文章,受益匪浅,写这篇随笔算是自己的读书笔记吧~. 作用域 首先明确一个概念,js只有函数作用域(function-based),没有块级作用域,也就是只有函数会有自己的作用域,其他都没有. 接着,作用域分为全局作用域与局部作用域. 全局作用域中的对象可以在代码的任何地方访问,一般来说,下面情况的对象会在全局作用域中: 最外层函数和在最外层函数外面定义的变量 没有通过关键字"va

Js作用域链及变量作用域

要理解变量的作用域范围就得先理解作用域链 用var关键字声明一个变量时,就是为该变量所在的对象添加了一个属性. 作用域链:由于js的变量都是对象的属性,而该对象可能又是其它对象的属性,而所有的对象都是window对象的属性,所以这些对象的关系可以看作是一条链 链头就是变量所处的对象,链尾就是window对象 看下面的代码: function t() { var a; function t2() { var b; } } js中函数也是对象,所以变量a所在的对象是t,t又在window对象中,所以

了解 JS 作用域与作用域链

(1)作用域 一个变量的作用域(scope)是程序源代码中定义的这个变量的区域. 1. 在JS中使用的是词法作用域(lexical scope) 不在任何函数内声明的变量(函数内省略var的也算全局)称作全局变量(global scope) 在函数内声明的变量具有函数作用域(function scope),属于局部变量 局部变量优先级高于全局变量 var name="one"; function test(){ var name="two"; console.log

基础知识回顾——js作用域

1.对js作用域的理解. 作用域 作用域分为全局作用域和函数作用域,我们可以理解为变量的生存环境(空间).全局作用域包含函数作用域,函数作用域里的变量可以访问到全局作用域中的变量,但是反之则不行. 变量提升 在js作用域中还有变量提升的现象(只有var 声明的变量才会有变量提升,window声明的不会),赋值语句最后生效.当我定义一个变量,如果它没有被赋值,它是属于undefined: 变量提升的优先级 函数声明 > 函数形参(函数的形参属于函数作用域:) > 自定义变量 延长作用域,闭包(r

关于js作用域

我们知道在编程语言中,作用域的作用就是控制变量.参数的可见范围和生命周期. js中提供了函数作用域的功效,比如在函数中定义的变量外部是无法访问到的: function jsFunc(){ var a = 5; } alert(a); // undefined 但是js中却没有提供块作用域的功效,比如我们在java代码中如果些如下代码: public static Boolean b = false; public static void main(String[] args) { if(!b){