이 글에서는 주로 JavaScript 변수 범위를 소개합니다. 편집자가 꽤 좋다고 생각해서 이제 공유하고 참고용으로 제공하겠습니다. 편집기를 따라 살펴보겠습니다
JavaScript에서 var
로 선언된 변수에는 실제로 범위가 있습니다. var
申明的变量实际上是有作用域的。
如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量:
'use strict'; function foo() { var x = 1; x = x + 1; } x = x + 2; // ReferenceError! 无法在函数体外引用变量x
如果两个不同的函数各自申明了同一个变量,那么该变量只在各自的函数体内起作用。换句话说,不同函数内部的同名变量互相独立,互不影响:
'use strict'; function foo() { var x = 1; x = x + 1; } function bar() { var x = 'A'; x = x + 'B'; }
由于JavaScript的函数可以嵌套,此时,内部函数可以访问外部函数定义的变量,反过来则不行:
'use strict'; function foo() { var x = 1; function bar() { var y = x + 1; // bar可以访问foo的变量x! } var z = y + 1; // ReferenceError! foo不可以访问bar的变量y! }
如果内部函数和外部函数的变量名重名怎么办?
'use strict'; function foo() { var x = 1; function bar() { var x = 'A'; alert('x in bar() = ' + x); // 'A' } alert('x in foo() = ' + x); // 1 bar(); }
这说明JavaScript的函数在查找变量时从自身函数定义开始,从“内”向“外”查找。如果内部函数定义了与外部函数重名的变量,则内部函数的变量将“屏蔽”外部函数的变量。
变量提升
JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部:
'use strict'; function foo() { var x = 'Hello, ' + y; alert(x); var y = 'Bob'; } foo();
虽然是strict模式,但语句var x = 'Hello, ' + y;
并不报错,原因是变量y
在稍后申明了。但是alert
显示Hello, undefined
,说明变量y
的值为undefined
。这正是因为JavaScript引擎自动提升了变量y
的声明,但不会提升变量y
的赋值。
对于上述foo()
函数,JavaScript引擎看到的代码相当于:
function foo() { var y; // 提升变量y的申明 var x = 'Hello, ' + y; alert(x); y = 'Bob'; }
由于JavaScript的这一怪异的“特性”,我们在函数内部定义变量时,请严格遵守“在函数内部首先申明所有变量”这一规则。最常见的做法是用一个var
申明函数内部用到的所有变量:
function foo() { var x = 1, // x初始化为1 y = x + 1, // y初始化为2 z, i; // z和i为undefined // 其他语句: for (i=0; i<100; i++) { ... } }
全局作用域
不在任何函数内定义的变量就具有全局作用域。实际上,JavaScript默认有一个全局对象window
,全局作用域的变量实际上被绑定到window
的一个属性:
'use strict'; var course = 'Learn JavaScript'; alert(course); // 'Learn JavaScript' alert(window.course); // 'Learn JavaScript'
因此,直接访问全局变量course
和访问window.course
是完全一样的。
你可能猜到了,由于函数定义有两种方式,以变量方式var foo = function () {}
定义的函数实际上也是一个全局变量,因此,顶层函数的定义也被视为一个全局变量,并绑定到window
对象:
'use strict'; function foo() { alert('foo'); } foo(); // 直接调用foo() window.foo(); // 通过window.foo()调用
进一步大胆地猜测,我们每次直接调用的alert()函数其实也是window的一个变量:
'use strict'; window.alert('调用window.alert()'); // 把alert保存到另一个变量: var old_alert = window.alert; // 给alert赋一个新函数: window.alert = function () {} // 恢复alert: window.alert = old_alert; alert('又可以用alert()了!');
这说明JavaScript实际上只有一个全局作用域。任何变量(函数也视为变量),如果没有在当前函数作用域中找到,就会继续往上查找,最后如果在全局作用域中也没有找到,则报ReferenceError错误。
名字空间
全局变量会绑定到window
上,不同的JavaScript文件如果使用了相同的全局变量,或者定义了相同名字的顶层函数,都会造成命名冲突,并且很难被发现。
减少冲突的一个方法是把自己的所有变量和函数全部绑定到一个全局变量中。例如:
// 唯一的全局变量MYAPP: var MYAPP = {}; // 其他变量: MYAPP.name = 'myapp'; MYAPP.version = 1.0; // 其他函数: MYAPP.foo = function () { return 'foo'; };
把自己的代码全部放入唯一的名字空间MYAPP
中,会大大减少全局变量冲突的可能。
许多著名的JavaScript库都是这么干的:jQuery,YUI,underscore等等。
局部作用域
由于JavaScript的变量作用域实际上是函数内部,我们在for
의 범위는 함수 전체입니다. body , 변수는 함수 본문 외부에서 참조될 수 없습니다.
'use strict'; function foo() { for (var i=0; i<100; i++) { // } i += 100; // 仍然可以引用变量i }
두 개의 서로 다른 함수가 동일한 변수를 선언하는 경우 변수는 해당 함수의 본문 내에서만 작동합니다. 즉, 서로 다른 함수 내에서 같은 이름을 가진 변수는 서로 독립되어 서로 영향을 주지 않습니다.
'use strict'; function foo() { var sum = 0; for (let i=0; i<100; i++) { sum += i; } i += 1; // SyntaxError }
var PI = 3.14;
'use strict'; const PI = 3.14; PI = 3; // 某些浏览器不报错,但是无效果! PI; // 3.14
y
변수가 나중에 선언되므로 var x = 'Hello, ' + y;
문은 오류를 보고하지 않습니다. 그러나 alert
에는 Hello, unundefined
가 표시되어 y
변수의 값이 정의되지 않음
임을 나타냅니다. 이는 JavaScript 엔진이 변수 y
의 선언을 자동으로 승격하지만 변수 y
의 할당은 승격하지 않기 때문입니다. 🎜🎜🎜위 foo()
함수의 경우 JavaScript 엔진에 표시되는 코드는 다음과 동일합니다. 🎜🎜🎜🎜🎜rrreee🎜이 이상한 JavaScript "기능"으로 인해 함수 내부에서 변수를 정의할 때🎜, "함수 내에서 모든 변수를 먼저 선언하라"는 규칙을 엄격히 준수하시기 바랍니다. 가장 일반적인 접근 방식은 var
를 사용하여 함수 내부에 사용되는 모든 변수를 선언하는 것입니다. 🎜🎜🎜🎜🎜rrreee🎜🎜Global 범위🎜🎜🎜🎜함수 내에서 정의되지 않은 변수는 전역 효과를 갖습니다. 도메인. 실제로 JavaScript에는 기본적으로 전역 개체 window
가 있으며 전역 범위의 변수는 실제로 window
의 속성에 바인딩됩니다. 🎜🎜🎜🎜🎜rrreee🎜따라서, 전역 변수 course
에 직접 액세스하는 것은 window.course
에 액세스하는 것과 똑같습니다. 🎜🎜🎜함수를 정의하는 방법이 두 가지가 있으므로 변수 모드 var foo = function () {}
에서 정의된 함수는 실제로 전역 변수라고 짐작하셨을 것입니다. 최상위 함수 이는 전역 변수로 간주되며 window
개체에 바인딩됩니다. 🎜🎜🎜🎜🎜rrreee🎜더 대담하게 추측하자면, 우리가 매번 직접 호출하는 Alert() 함수는 실제로는 window 변수 :🎜🎜🎜🎜🎜rrreee🎜이는 JavaScript에 실제로 하나의 전역 범위만 있음을 보여줍니다. 현재 함수 범위 🎜에 없는 모든 변수(함수도 변수로 간주됨)는 계속됩니다. 위쪽으로 검색하여 마지막으로 전역 범위에서 찾을 수 없으면 ReferenceError 오류가 보고됩니다. 🎜🎜🎜🎜Namespace🎜🎜🎜🎜전역 변수는 window
에 바인딩됩니다. 서로 다른 JavaScript 파일이 동일한 전역 변수를 사용하거나 동일한 이름으로 최상위 함수를 정의하면 이름 지정 문제가 발생합니다. 충돌이 발생하여 감지하기 어렵습니다. 🎜🎜🎜충돌을 줄이는 한 가지 방법은 모든 변수와 함수를 전역 변수에 바인딩하는 것입니다. 예: 🎜🎜🎜🎜🎜rrreee🎜모든 코드를 고유한 네임스페이스 MYAPP
에 넣으세요. 이렇게 하면 전역 변수 충돌 가능성이 크게 줄어듭니다. 🎜🎜🎜jQuery, YUI, 밑줄 등 많은 유명한 JavaScript 라이브러리가 이를 수행합니다. 🎜🎜🎜🎜로컬 범위🎜🎜🎜🎜JavaScript의 변수 범위는 실제로 함수 내부에 있으므로 for
루프와 같은 명령문 블록에서는 로컬 범위의 변수를 정의할 수 없습니다. 🎜 🎜🎜🎜🎜rrreee 🎜블록 수준 범위 문제를 해결하기 위해 ES6에서는 블록 수준 범위 변수를 선언하기 위해 var 대신 let을 사용하는 새로운 키워드를 도입했습니다. 🎜🎜🎜🎜🎜rrreee🎜🎜Constant🎜🎜🎜由于var
和let
申明的是变量,如果要申明一个常量,在ES6之前是不行的,我们通常用全部大写的变量来表示“这是一个常量,不要修改它的值”:
var PI = 3.14;
ES6标准引入了新的关键字const来定义常量,const与let都具有块级作用域:
'use strict'; const PI = 3.14; PI = 3; // 某些浏览器不报错,但是无效果! PI; // 3.14
위 내용은 JavaScript 변수 범위 예시 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!