时间:2021-07-01 10:21:17 帮助过:34人阅读
输出10
(function () {
for (var i = 0; i < 10; i++) {
//Do Nothing
}
alert(i); //
输出Private Function
(function () {
(function () {
for (var i = 0; i < 10; i++) {
//Do Nothing
}
})();
alert(i); //Error: 'i' is undefined
})();
在第8行访问变了i时,出现错误,实现了我们想要的块级作用域。
•私有属性
在JavaScript中没有块级作用域的概念,同样也没有私有属性的概念,但是存在私有变量。如果我们想把一些数据封装隐藏起来要怎么做呢?想必大家可能已经想到了,可以通过使用闭包+私有变量的方式来实现对象的私有属性。
<1>.实例私有属性
实例私有属性的特点就是每个对象都会包含独立的属性,对象和对象之间没有共享。为了实现这个目标,可以在构造函数中增加一个私有变量,然后定义公共方法来访问这个私有变量,就如同其他OO语言的setter和getter一样,下列示例就实现了实例的私有属性:
代码如下:输出gyy
//实例私有变量
function MyObject(name) {
//定义私有变量
//注意:此处没有用this.name,如果使用this.name变成公共属性了
var privateName = name;
//定义私有熟悉
var privateFunction = function () {
return "Private Function";
}
//公共方法访问私有熟悉
MyObject.prototype.getName = function () {
return privateName;
}
MyObject.prototype.getFunction = function () {
return privateFunction();
}
}
var moGyy = new MyObject("gyy");
alert(moGyy.getName()); //
alert(moGyy.getFunction()); //
输出gyycyy
//静态私有变量和实例私有变量
(function () {
//定义私有变量
var staticPrivateValue = "";
//构造函数,把构织函数赋值给一个全局的变量
MyObject = function (name) {
//定义实例变量
this.name = name;
};
//定义两个公共方法用于访问私有变量,再一次把公共方法添加到原型中
MyObject.prototype.getPrivateValue = function () {
return staticPrivateValue;
}
MyObject.prototype.setPrivateValue = function (value) {
staticPrivateValue = value;
}
})();
var mo = new MyObject("jeff-gyy");
mo.setPrivateValue("gyycyy"); //设置私有属性的值
alert(mo.getPrivateValue()); //
//自定义构造函数
var mo = new function () {
//私有变量
var privateValue = "";
//普通模块模式
return {
publicValue: "public",
//访问私有变量
getPrivateValue: function () {
return privateValue;
},
setPrivateValue: function (value) {
privateValue = value;
}
}
}();
mo.setPrivateValue("private value");
alert(mo.getPrivateValue());
alert(mo.publicFunction());
模块模式使用匿名函数来封装内部实现,就上面的示例匿名函数中包含了私有变量privateValue,返回的对象中的公共函数通过闭包的作用域链访问包含函数中的私有变量,由于定义的匿名函数被立即调用,因此变量mo引用的是返回的对象。上面的单例模式返回的是一个Object对象,可以使用增强模块模式实现自定义类型的单例模式:
代码如下:
//增强模块模式
//自定义构造函数
function MyObject(name) {
this.name = name;
};
//自定义构造函数
var mo = new function () {
//私有变量
var privateValue = "";
//增强模块模式
var o = new MyObject("gyycyy");
o.publicValue = "public";
//访问私有变量
o.getPrivateValue = function () {
return privateValue;
}
o.setPrivateValue = function (value) {
privateValue = value;
}
return o;
}();
mo.setPrivateValue("private value");
alert(mo.getPrivateValue());
alert(mo.publicFunction());
以上代码示例实现了MyObject的单例模式。
最后需要提一点的是使用闭包有利也有弊,由于闭包作用域链引用包含函数的变量对象,因此会占用额外的内存,而且进行变量查找是也需要通过作用域链,因此会消耗查找时间,闭包越深情况更严重。另外在IE(早些版本)中由于垃圾回收机制使用引用计数,因此可能会出现循环引用的情况,导致内存泄露,如下示例:
代码如下:
function assignHandler(){
var element = document.getElementById("someElement");
element.onclick = function(){
alert(element.id);
};
}
在上面的代码中创建了一个闭包作为element的事件,该闭包引用了包含函数assingHandler的变量对象,而恰恰是对变量对象的引用使得element引用计数至少为1,因此element不会被回收,导致内存泄露。修改的方法大家可以想想。