一、认识函数的上下文
- 什么是上下文
垃圾分类,`这`是非常好的习惯,值得表扬随手关灯,`这`是非常好的习惯,值得表扬遛狗栓绳,`这`是非常好的习惯,值得表扬课后复习,`这`是非常好的习惯,值得表扬 早睡早起,`这`是非常好的习惯,值得表扬
- 函数的上下文
- 函数中可以使用
this
关键字,它表示函数的上下文
。 - 与中文中"这"类似,函数中的this具体指代什么
必须通过调用函数时的"前言后语"来判断
- 函数中可以使用
- 函数中的this
var 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); // 适用规则5
var 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 | 任意指定 |