标签:rip 调用 out 而且 query 代码 执行 显示 描述
在C#中我们都基本上不讲作用域,因为一切都是自然而然的(用语言描述反而有些困难)。但JavaScript的作用域,让人非常头大!
如果一个变量在函数体内部(用var)声明,则该变量的作用域为整个函数体,在函数体外不可引用该变量。(另见:let)
不同函数内部的同名变量互相独立,互不影响。
这样被声明的变量被称之为:局部变量。
function scope() {
var sname = ‘李志博‘;
console.log(‘in function:‘ + sname);
}
scope();
console.log(‘out function:‘ + sname);
不在任何函数内定义的变量具有全局作用域,被称之为全局变量。
演示:
如果script只是在HTML页面中使用,全局变量还可以接受(而且比较方便);
但随着JavaScript规模扩大,一个项目可能引用多个(第三方/其他人写的)类库(js文件),各个文件间的名称冲突就越来越难以避免,给开发/维护带来极大的问题!这就被称之为“全局变量污染”。
词法作用域
观察以下代码:
var sname = "飞哥";
function smart() {
alert(`${sname}最帅`);
}
function reallySmart() {
var sname = ‘子祥‘;
smart();
}
reallySmart();
reallySmart()调用smart(),smart()中需要sname但又没有声明sname,怎么办?
由var声明的变量的作用范围,其作用域由是由其源代码的书写位置,(而不是在哪里执行)决定的。
JavaScript的函数中不仅可以使用全局变量,还可以使用该函数外部的函数所声明的变量:
function outFunc(sname) {
var age = 100;
function innerFunc() {
alert(age); //age定义在innerFunc()之外
}
innerFunc();
}
这样就形成了一个作用域链:JavaScript会沿着这个链条由内向外查找,直到undefined。
@想一想@:如何剪切/粘贴第一个函数,才能显示:子祥最帅?
其他成熟的工程化语言内置了名称空间(namespace)来解决这个问题,比如:
//虽然都是“源栈”,但他们显然是不一样的:
China.Chongqing.Luckystack
China.Bejin.Luckystack
US.NewYork.Luckstack
JavaScript只能模拟:
var China = {};
China.Chongqing = {};
China.Chongqing.LuckyStack = {};
China.Chongqing.LuckyStack.wpz = function () {
JQuery等类库就是这样做的。(演示)
把我们之前的代码稍作改动:
function scope() {
/*var*/ sname = ‘李志博‘; //注释掉var
@猜一猜@:会有什么结果?
如果在JavaScript的函数中声明变量,不使用var,该变量就具有全局作用域!——特性超级坑爹的一个“特性(bug)”,尤其是在代码review的时候,你根本不知道这是在:
所以从ES5开始,JavaScript就引入了所谓的“严格”模式,在代码顶部添加一行:
‘use strict‘; -- 如果浏览器不支持?
使用严格模式,就能强制JavaScript声明变量时必须使用:var;否则会报错。(以及其他约束)
演示:调试窗口报错
官方推荐总是使用严格模式。但是,如果
b.js 文件没有声明‘use strict‘且没有按照严格模式书写代码
@想一想@:会出现什么情况?
所以,更多时候,我们不得不把‘use strict‘声明在函数顶部。
体会:JavaScript在处理大型项目,进行工程化开发方面先天不足!由此诞生了很多“奇巧淫技”,以及不断进化的ES标准。
但你以为这样就结束了?too young too simple啊!作为一个“先天严重不足,后天各种补丁”的语言,这一切才刚刚开始……
使用“模拟名称空间”技术,构建一个函数函数yz.fei.get(number);
JavaScript:作用域:函数作用域/全局变量污染/命名空间
标签:rip 调用 out 而且 query 代码 执行 显示 描述
原文地址:https://www.cnblogs.com/nntisn351/p/14174958.html