一、认识函数的上下文
- 什么是上下文垃圾分类,`这`是非常好的习惯,值得表扬随手关灯,`这`是非常好的习惯,值得表扬遛狗栓绳,`这`是非常好的习惯,值得表扬课后复习,`这`是非常好的习惯,值得表扬 早睡早起,`这`是非常好的习惯,值得表扬
- 函数的上下文 - 函数中可以使用this关键字,它表示函数的上下文。
- 与中文中"这"类似,函数中的this具体指代什么必须通过调用函数时的"前言后语"来判断
 
- 函数中可以使用
- 函数中的thisvar xiaoming = {nickname: '小明',age: 12,sayHello: function () {console.log('我是' + this.nickname + ',我' + this.age + '岁了'); }};xiaoming.sayHello(); // 我是小明,我12岁了var xiaoming = {nickname: '小明',age: 12, sayHello: function () {console.log('我是' + this.nickname + ',我' + this.age + '岁了'); }};var sayHello = xiaoming.sayHello; // 将函数"提"出来,单独存为变量// 直接圆括号调用这个函数,而不是对象打点调用了sayHello(); // 我是undefined,我undefined岁了
- 函数的上下文由调用方式决定 - 同一个函数,用不同的形式调用它,则函数的上下文不同 - 情形1:对象打点调用函数,函数中的this指代这个打点的对象。xiaoming.sayHello();
- 情形2:圆括号直接调用函数,函数中的this指代window对象。var sayHello = xiaoming.sayHello; sayHello();var obj = { a: 1,b: 2,fn: function () {console.log(this.a + this.b);}};var fn = obj.fn;fn();
 
- 情形1:对象打点调用函数,函数中的
 
- 同一个函数,用不同的形式调用它,则函数的上下文不同 
1. 上下文规则1
-  函数的上下文由调用函数的方式决定 - 函数的上下文(this关键字)由调用函数的方式决定, function是"运行时上下文"策略。
- 函数如果不调用,则不能确定函数的上下文。
 
- 函数的上下文(this关键字)由
-  规则1: 对象打点调用它的方法函数,则函数的上下文是这个打点的对象。
 对象.方法()function fn() {console.log(this.a + this.b);}var obj = { a: 66, b: 33, fn: fn}; obj.fn(); // 99- 构成对象.方法()的 形式,适用规则1
 var obj1 = {a: 1,b: 2,fn: function () {console.log(this.a + this.b);}};var obj2 = {a: 3,b: 4,fn: obj1.fn };obj2.fn(); // 7- 构成对象.方法()的形式,适用规则1
 function outer() { var a = 11;var b = 22;return {a: 33,b: 44,fn: function () {console.log(this.a + this.b);}}; }outer().fn(); // 77- 构成对象.方法()的 形式,适用规则1
 function fun() {console.log(this.a + this.b);}var obj = {a: 1, b: 2, c: [{a: 3, b: 4, c: fun}] };var a = 5; obj.c[0].c(); // 7- 构成对象.方法()的形式,适用规则1
 
2. 上下文规则2
-  规则2:圆括号直接调用函数,则函数的上下文是window对象 函数()var obj1 = {a: 1,b: 2,fn: function () {console.log(this.a + this.b);}};var a = 3;var b = 4;var fn = obj1.fn;fn(); // 7- 构成函数()的形式,适用规则2
 function fun() {return this.a + this.b;}var a = 1; var b = 2;var obj = {a: 3,b: fun(), // 适用规则2fun: fun};var result = obj.fun(); // 适用规则1console.log(result); // 6
3. 上下文规则3
-  规则3:数组(类数组对象)枚举出函数进行调用,上下文 是这个数组(类数组对象) 数组[下标]()var arr = ['A', 'B', 'C', function () { console.log(this[0]);}];arr[3](); // "A"- 适用规则3
 
-  什么是类数组对象:所有键名为自然数序列(从0开始),且有 length属性的对象。
-  arguments对象是最常见的类数组对象,它是函数的实参列表。 function fun() {arguments[3](); }fun('A', 'B', 'C', function () { console.log(this[1]); // 'B'});- 适用规则3
 
4. 上下文规则4
- 规则4:IIFE中的函数,上下文是window对象。(function() {})();var a = 1;var obj = {a: 2,fun: (function () {var a = this.a;return function () {console.log(a + this.a); // 3} })() // 适用规则4};obj.fun(); // 适用规则1
5. 上下文规则5
- 规则5:定时器、延时器调用函数,上下文是window对象setInterval(函数, 时间);setTimeout(函数, 时间);var obj = {a: 1,b: 2,fun: function () {console.log(this.a + this.b); // 7}}var a = 3; var b = 4;setTimeout(obj.fun, 2000); // 适用规则5var obj = {a: 1,b: 2,fun: function () {console.log(this.a + this.b); // 3}}var a = 3; var b = 4;setTimeout(function() { obj.fun(); // 适用规则1}, 2000);
6. 上下文规则6
- 规则6:事件处理函数的上下文是绑定事件的DOM元素。DOM元素.onclick = function () {};
- 请实现效果:点击哪个盒子,哪个盒子就变红,要求使用同一个事件处理函数实现。
 @code
- 请实现效果:点击哪个盒子,哪个盒子在2000毫秒后就变红,要求使用同一个事件处理函数实现。
 @code
7. call 和 apply
-  call和apply能指定函数的上下文。function sum() {alert(this.chinese + this.math + this.english);}var xiaoming = { chinese: 80,math: 95,english: 93};sum.call(xiaoming);sum.apply(xiaoming);- 函数.call(上下文);
- 函数.apply(上下文);
 
-  call和apply的区别function sum(b1, b2) {alert(this.c + this.m + this.e + b1 + b2);}sum.call(xiaoming, 5, 3); // call要用逗号罗列参数xsum.apply(xiaoming, [5, 3]); // apply要把参数写到数组中
-  到底使用call还是apply? function fun1() {fun2.apply(this, arguments);}function fun2(a, b) {alert(a + b);}fun1(33, 44);
8. 总结
| 规则 | 上下文 | 
|---|---|
| 对象.函数() | 对象 | 
| 函数() | window | 
| 数组[下标]() | 数组 | 
| IIFE | window | 
| 定时器 | window | 
| DOM事件处理函数 | 绑定DOM的元素 | 
| call和apply | 任意指定 |