1、作用域
var i = function(){ alert("i"); };
var j = function(){ alert("j"); };
function a1()
{
(function(){
i = function(){ alert("i2"); }; // 对外部i覆盖
var j = function(){ alert("j2"); }; // 在内部创建了一个新的j
k = function(){ alert("k2"); }; // 对window添加属性k
var l = function(){ alert("l2"); }; // 在内部创建l
i();
j();
k();
l();
})();
};
a1();
i();
j();
window.k();
l(); // 外部不能找到l
2、闭包
闭包的定义是,一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达是的一部分。 根据定义javascript中所有每个function都是一个闭包。 嵌套function所产生的闭包更为强大,也是我们通常所谓的闭包。
// 根据作用域的特点有了闭包的概念
function a1()
{
var i = 1; // 1、变量i是受到保护只有b1能访问
function b1()
{
alert(++i); // 2、因为在b1会被引用到所以i的内存不会被释
}
return b1;
};
var c = a1();
setInterval(function(){
c();
}, 1000);
// 3、类私有变量创建的基础
function a()
{
var i = 0;
function b()
{
alert(++i);
}
return b;
}
var c = a();
c();
作用和效果
闭包的作用就是在a执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量。 1、保护函数内的变量安全。以最开始的例子为例,函数a中i只有函数b才能访问,而无法通过其他途径访问到,因此保护了i的安全性。 2、在内存中维持一个变量。依然如前例,由于闭包,函数a中i的一直存在于内存中,因此每次执行c(),都会给i自加1。 3、通过保护变量的安全实现JS私有属性和私有方法(不能被外部访问)
3、内存回收
内存托管的语言,不被引用的内存将做定期销毁。 销毁条件:1、不在过程中引用;2、引用过DOM被移除
function a1()
{
var i = "";
function b1(clist)
{
i = "<div>" + clist + "</div>";
alert(i);
i = null; // 依据闭包的概念i的内存将不会被系统回收,所以要手动回收
}
return b1;
};
var c1 = a1();
<a href="javascript:;" onclick="javascript:c1();">点击</a>
4、上下文对象
ABCDEFGH
function changeColor(_color, _size)
{
alert(this==window);
this.style.color = _color;
this.style.fontSize = _size;
}
//changeColor("#000"); // 因为changeColor上下文对象是window,window没有style属性所以不能运行
changeColor.call(document.getElementById('abc'), "#666"); // 可以重新指定上下文对象,单参数形式
changeColor.apply(document.getElementById('abc'), ["#666", "55px"]); // 多参数形式
5、创建对象
var a1 = function() // 定义构造函数
{
// 定义私有属性
var _self = this;
var i = 1;
// 初始化过程
++i;
// 定义事件
this.callback = function(){};
// 定义公共方法
this.b1 = function()
{
alert(++i);
_self.callback();
}
};
var a1Obj = new a1();
6、对象继承
function extend(sub,sup)
{
var f=function(){};
f.prototype = sup.prototype;
sub.prototype = new f();
sub.prototype.constructor = sub;
};
function abc()
{
var a = "a";
this.geta = function(){
alert("get"+a);
};
this.getd = function(){
alert("get"+'abcd');
};
def.call(this, 123); // 执行父类的构造函数
}
function def(a1)
{
alert(a1);
var d = "d";
this.getd = function(){
alert("get"+d);
};
}
extend(abc,def); // 对象是引用类型所以无需返回对象
var abc_e = new abc;
abc_e.geta();
abc_e.getd(); // 子类同名属性将被父类覆盖
alert(abc_e.constructor==abc);
var def_e = new def;
def_e.getd();
//def_e.geta();
alert(def_e.constructor==def);