第三次----------javascript面向对象技术,

在《javascript高级程序设计》这本书里对javascript的面向对象做了很详细的解析,

1: javascript的对象创建

javascript的对象创建方式大概有工厂模式,构造函数模式,原型模式,构造函数和原型模式的混合模式,以及动态原型模式

工厂模式

构造函数模式

原型模式

构造函数和原型模式的混合模式

动态原型模式

 

2: javascript原型链

 

3: javascript的闭包

闭包:是指有权访问另外一个函数作用域中的变量的函数。创建闭包的常见方式就是在一个函数内部创建另外一个函数。

简单的说,Javascript允许使用内部函数---即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。

 

闭包在使用的时候有优点也有缺点,

缺点(占用内存量比交大)

      在调用函数的时候会在内存中生成如下图的结构:
 

\

 

(单击图片查看大图)

 

  但是闭包的情况就有点特殊了,由于闭包函数可以访问外层函数中的变量,所以外层函数在执行结束后,其作用域活动对象并不会被释放(注意,外层函数执行结束后执行环境和对应的作用域链就会被销毁),而是被闭包函数的作用域链所引用,直到闭包函数被销毁后,外层函数的作用域活动对象才会被销毁。这也正是闭包要占用内存的原因。


       所以使用闭包有好处,也有坏处,滥用闭包会造成内存的大量消耗。
 
       使用闭包还有其他的副作用,可以说是bug,也可以说不是,相对不同的业务可能就会有不同的看法。
 
       这个副作用是闭包函数只能取到外层函数变量的最终值。
 
       测试代码如下:(这里使用了jquery对象)
 
/*闭包缺陷*/
(function($){
var result = new Array(),
i = 0;
for(;i<10;i++){
result[i] = function(){
return i;
};
}
$.RES1 = result;
})(jQuery);
// 执行数组中的函数
$.RES1[0]();

       上面的代码先通过匿名函数表达式开辟了一块私有作用域,这个匿名函数就是我们上面所说的外层函数,该外层函数有一个参数$,同时还定义了变量result和 I , 通过for循环给数组result赋值一个匿名函数,这个匿名函数就是闭包,他访问了外层函数的变量I , 理论上数组result[i]() 会返回相应的数组下标值,实际情况却不如所愿。
 
       如上代码 $.RES1[0]() 的执行结果是10. 
 
       为什么会这样呢,因为i的最终值就是10.
 
       下面我们通过下图来详细说明下,上面的那段代码执行时在内存中到底发生了什么:
 

\
(单击图片查看大图)

  
       那么这个副作用有没有办法可以修复呢?当然可以!
 
       我们可以通过下面的代码来达到我们的预期。
 
/*修复闭包缺陷*/
(function($){
var result = new Array(),
i = 0;
for(;i<10;i++){
result[i] = function(num){
return function(){
return num;
}
}(i);
}
$.RES2 = result;
})(jQuery);
//调用闭包函数
console.log($.RES2[0]());

       上面的代码又在内存中发生了什么?我们同样用下面的一幅图来详细解释。看懂了上面的图,我们也就不难理解下面的图。
 

\
(单击图片查看大图)

 
       只要看懂上面的三张图,我们也就可以深入的理解清楚javascript中闭包的原理,以及闭包的好处和弊端,在我们的代码中合理的使用闭包,达到代码的整洁和高效。

 

posted @ 2016-09-24 20:44 奋斗,坚持 阅读(...) 评论(...)  编辑 收藏