一、認識函數的上下文
- 什么是上下文
垃圾分類,`這`是非常好的習慣,值得表揚隨手關燈,`這`是非常好的習慣,值得表揚遛狗栓繩,`這`是非常好的習慣,值得表揚課后復習,`這`是非常好的習慣,值得表揚 早睡早起,`這`是非常好的習慣,值得表揚
- 函數的上下文
- 函數中可以使用
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 | 任意指定 |