块级作用域和私有变量

块级作用域

(function(){
    //这里是块级作用域
})()

例如:

(function(){
    for(var i=0;i<5;i++){
        alert(i);//0,1,2,3,4
    }
})();
alert(i);//error

上例中,定义了一个块级作用域,变量i在块级作用域中可见的,但是在块级作用域外部则无法访问。

这种技术经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数。

私有变量

任何在函数中定义的变量,都可以认为是私有变量。因为不能在函数的外部访问这些变量。私有变量包括函数的参数、局部变量和在函数内部定义的其他函数。

我们把有权访问私有变量和私有函数的公有方法称为特权方法:

function MyObject(){
//私有变量和私有函数
    var privateVariable = 10;
    function privateFunction(){
        return false;
    }
    //特权方法,特权方法作为闭包有权访问在构造函数中定义的所有变量和函数
    this.publicMethod = function (){
        privateVariable++;
        return privateFunction();
    };
}
var obj = new MyObject();
obj.publicMethod();//

原型模式定义共有方法:

(function(){
    //私有变量和私有函数
    var privateVariable = 10;
    function privateFunction(){
        return false;
    }
    //构造函数
    MyObject = function(){
    };
    //公有/特权方法
    MyObject.prototype.publicMethod = function(){
        privateVariable++;
        return privateFunction();
    };
})();

模块模式:

var singleton = function(){
//私有变量和私有函数
    var privateVariable = 10;
    function privateFunction(){
        return false;
    }
    //特权/公有方法和属性
    return {
        publicProperty: true,
        publicMethod : function(){
            privateVariable++;
            return privateFunction();
        }
    };
}();
<think>我们使用ES5的方法模拟块级作用域,通常有两种主要方式: 1. 使用立即执行函数表达式(IIFE)来创建函数作用域,从而模拟块级作用域。 2. 使用try-catch语句中的catch子句,因为catch子句会创建一个作用域(在ES3中就有)。 但是需要注意的是,catch子句的方式并不常用,而且有局限性(通常只用于错误处理),所以IIFE是更常见的方法。 下面我们分别给出示例: 方法一:IIFE 在ES5中,我们可以通过将代码包裹在一个立即执行的函数中,来创建独立的作用域,从而避免变量污染部作用域。 方法二:catch子句(较少使用) 利用catch子句会创建一个作用域的特性,可以将代码放在try中,然后抛出一个无用的错误(或使用一个空错误),在catch中捕获,从而创建一个块级作用域。但这种方法并不推荐,因为会影响性能且代码可读性差。 我们主要展示IIFE的方式。</think>### 在 ES5 中实现块级作用域的解决方案 #### 核心实现方法(使用立即执行函数表达式 IIFE) ```javascript // 使用 IIFE 创建闭包作用域 (function() { var blockScopedVar = "内部变量"; console.log(blockScopedVar); // 正常访问 })(); // 部无法访问 console.log(typeof blockScopedVar); // "undefined" ``` #### 方法对比表 | **实现方式** | **原理** | **优点** | **缺点** | |--------------------|-----------------------------|-----------------------|-------------------------| | **IIFE** | 创建函数作用域 | 简单通用,兼容性好 | 需要额函数包装 | | **try/catch** | 利用 catch 的作用域 | 无需函数包装 | 语义不清晰,性能较差 | | **with 语句** | 临时创建作用域 | 语法简单 | 已被废弃,严格模式禁用 | | **对象作用域** | 使用对象属性 | 避免变量泄漏 | 访问需要对象前缀 | --- ### 详细实现方案与代码示例 #### 1. IIFE(立即执行函数表达式) - 推荐方案 ```javascript // 基础用法 (function() { var privateVar = "私有变量"; console.log(privateVar); // "私有变量" })(); // 带参数版本 var external = "部值"; (function(inner) { console.log(inner); // "部值" var newVar = "新变量"; })(external); // 部访问测试 console.log(typeof privateVar); // "undefined" console.log(typeof newVar); // "undefined" ``` #### 2. try/catch 方案 - 利用 catch 作用域 ```javascript try { throw undefined; // 触发 catch } catch (block) { // catch 内是独立作用域 var scopedVar = "变量"; console.log(scopedVar); // "变量" } // 部访问测试 console.log(typeof scopedVar); // "undefined" (在标准实现中) ``` #### 3. 对象作用域方案 ```javascript // 使用对象封装变量 var scope = new function() { this.internal = "内部值"; this.logValue = function() { console.log(this.internal); }; }(); scope.logValue(); // "内部值" console.log(typeof internal); // "undefined" ``` #### 4. with 语句方案(不推荐) ```javascript // 注意:严格模式下禁用 var pseudoScope = {}; with (pseudoScope) { var scoped = "临时值"; console.log(scoped); // "临时值" } console.log(typeof scoped); // "undefined" (行为不一致) ``` --- ### 实际应用场景 #### 1. 循环中的块级作用域 ```javascript // 问题:ES5 中 var 会导致变量提升 for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); // 输出 5 五次 }, 100); } // 解决方案:使用 IIFE for (var i = 0; i < 5; i++) { (function(j) { setTimeout(function() { console.log(j); // 输出 0,1,2,3,4 }, 100); })(i); } ``` #### 2. 模模式封装私有变量 ```javascript var counterModule = (function() { var count = 0; // 私有变量 return { increment: function() { return ++count; }, reset: function() { count = 0; return count; } }; })(); console.log(counterModule.increment()); // 1 console.log(counterModule.count); // undefined ``` #### 3. 避免全局污染 ```javascript // 全局命名空间保护 (function(global) { var libraryName = "MyLib"; global.myLibrary = { version: "1.0", getName: function() { return libraryName; } }; })(window); console.log(window.myLibrary.getName()); // "MyLib" console.log(typeof libraryName); // "undefined" ``` --- ### 最佳实践与注意事项 1. **首选方案**:始终使用 IIFE 实现块级作用域 2. **性能优化**: ```javascript // 使用一元运算符简化 IIFE !function() { // 块级作用域代码 }(); // 或使用 void 运算符 void function() { // 块级作用域代码 }(); ``` 3. **作用域继承**: ```javascript var outer = "部值"; (function(inner) { console.log(inner); // "部值" }(outer)); // 通过参数传递值 ``` 4. **严格模式增强**: ```javascript "use strict"; (function() { // 严格模式下的块级作用域更安全 undeclaredVar = "错误"; // 会抛出 ReferenceError })(); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员青戈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值