码迷,mamicode.com
首页 > 其他好文 > 详细

2016-08-04

时间:2016-08-04 22:56:13      阅读:311      评论:0      收藏:0      [点我收藏+]

标签:

1. apply方法和call方法

 

1.1 apply方法:接受2个参数,第一个参数指定了函数体内this对象的指向,第二个参数为一个类似数组的集合

1 var yunxi = function(a,b){
2 
3    console.log([a,b]); // [1,2]
4 
5    console.log(this === window); // true
6 
7 };
8 
9 yunxi.apply(null,[1,2]);

如上代码,我们第一个参数传入null,函数体内默认会指向与宿主对象,即window对象。

 

1.2 call方法:第二个参数是以逗号隔开的参数

1 var yunxi = function(a,b){
2 
3    console.log([a,b]); // [1,2]
4 
5    console.log(this === window); // true
6 
7 };
8 
9 yunxi.call(null,1,2);

 

1.3 call 和 apply 最常见的用途是改变函数体内的this指向

 1 var longen = {
 2     name:‘yunxi‘
 3 };
 4 var longen2 = {
 5     name: ‘我叫涂根华‘
 6 };
 7 var name = "我是来测试的";
 8 var getName = function(){
 9     return this.name;
10 };
11 console.log(getName()); // 打印 "我是来测试的";
12 console.log(getName.call(longen)); // 打印 yunxi
13 console.log(getName.call(longen2)); // 打印 "我叫涂根华"

第一次调用 getName()方法,因为它是普通函数调用,所以它的this指向与window;

第二次调用getName.call(longen),执行这句代码后,getName这个方法的内部指针 this 指向 longen 这个对象了,因此打印 this.name 实际上是 longen.name,因此返回的是 name=”yunxi”。

 

但是 this 指针也有列外的情况,比如一个点击事件,当我们点击一个元素的时候,this指针就指向那个点击元素,但是当我们在内部再包含一个函数后,在函数内再继续调用 this 的话,此时的 this 指针就指向了 window 了,如下代码:

1 document.getElementById("longen").onclick = function(){
2     console.log(this); // this 就指向于div元素对象了
3     var func = function(){
4         console.log(this); // 打印出window对象
5     }
6     func();
7 }

 

以上代码可以看到外部 this 指向被点击的那个元素,内部普通函数调用,this 指针都是指向于 window 对象。但是我们可以使用 call 或者 apply 方法来改变 this 指针的指向,如下代码:

1 document.getElementById("longen").onclick = function(){
2     console.log(this); // this 就指向于div元素对象了
3     var func = function(){
4         console.log(this); // 就指向于div元素对象了
5     }
6     func.call(this);
7 }

 

以上代码使用 call 方法调用 func 函数,使 this 指向与 func 这个对象了。我们还可以不使用 call 或者 apply 方法来改变 this 的指针,我们可以在外部先使用一个变量来保存 this 的指针,在内部调用的时候我们可以使用此变量即可,如下代码:

1 document.getElementById("longen").onclick = function(){
2     console.log(this); // this 就指向于div元素对象了
3     var self = this;
4     var func = function(){
5         console.log(self); // 就指向于div元素对象了
6     }
7     func();
8 }  

 

 

2. 闭包

 

2.1 闭包有两个特性:

  1) 封闭性:外界无法访问闭包内部的数据,如果在闭包内声明变量,外界是无法访问的,除非闭包主动向外界提供访问接口;

  2) 持久性:一般的函数,调用完毕之后,系统自动注销函数,而对于闭包来说,在外部函数被调用之后,闭包结构依然保存在系统中,闭包中的数据依然存在,从而实现对数据的持久使用。

 

2.2 闭包的缺点:

  使用闭包会占有内存资源,过多的使用闭包会导致内存溢出等。

 

2.3 闭包的使用

 

 1 // 经典的闭包实列如下:
 2 function f(x){              //外部函数
 3     var a = x;              // 外部函数的局部变量,并传递参数
 4     var b = function(){     // 内部函数 
 5         return a;           // 访问外部函数中的局部变量
 6     };
 7     a++;                    // 访问后,动态更新外部函数的变量
 8     return b;               // 返回内部函数
 9 }
10 var c = f(5);               // 调用外部函数并且赋值
11 console.log(c());           // 调用内部函数,返回外部函数更新后的值为6

 

 

首先在 a 函数内定义了两个变量,一个是存储参数,另外一个是闭包结构,在闭包结构中保存着 b 函数内的 a 变量,默认情况下,当 a 函数调用完之后 a 变量会自动销毁的,但是由于闭包的影响,闭包中使用了外界的变量,因此 a 变量会一直保存在内存中,因此变量 a 参数没有随着 a 函数销毁而被释放,因此引申出闭包的缺点是:过多的使用闭包会占有内存资源,或内存溢出等可能性。

 

在如下代码中有2个函数,f 函数的功能是:把数组类型的参数中每个元素的值分别封装在闭包结构中,然后把闭包存储在一个数组中,并返回这个数组。但是在函数 e 中调用函数 f 并向其传递一个数组 ["a","b","c"],然后遍历函数 f 返回的数组,我们运行打印后发现都是 c undefined。那是因为在执行 f 函数中的循环的时候,值虽然保存在 temp 中,但是每次循环后 temp 值在不断的变化,当 for 循环结束后,此时 temp 值为 c,同时 i 变为 3,因此当调用的时候打印出来的 temp 为 3,arrs[3] 变为 undefined,因此打印出 c undefined。

解决闭包的缺陷我们可以再在外面包一层函数,每次循环的时候,把temp参数和i参数传递进去。如代码二:

 1 // 代码一
 2 function f(x) {
 3     var arrs = [];
 4     for(var i = 0; i < x.length; i++) {
 5         var temp = x[i];
 6         arrs.push(function(){
 7             console.log(temp + ‘ ‘ +x[i]); // c undefined
 8         });
 9     }
10     return arrs;
11 }
12 function e(){
13     var ar = f(["a","b","c"]);
14     for(var i = 0,ilen = ar.length; i < ilen; i++) {
15         ar[i]();
16     }
17 }
18 e(); 
19 // 代码二:
20 function f2(x) {
21     var arrs = [];
22     for(var i = 0; i < x.length; i++) {
23         var temp = x[i];
24         (function(temp,i){
25             arrs.push(function(){
26                 console.log(temp + ‘ ‘ +x[i]); // c undefined
27             });
28         })(temp,i);
29     }
30     return arrs;
31 }
32 function e2(){
33     var ar = f2(["a","b","c"]);
34     for(var i = 0,ilen = ar.length; i < ilen; i++) {
35         ar[i]();
36     }
37 }
38 e2(); 

 

学习自涂根华的博客 http://www.cnblogs.com/tugenhua0707/p/5046854.html

2016-08-04

标签:

原文地址:http://www.cnblogs.com/xiaochechang/p/5738634.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!