JS:函数的上下文、上下文规则、call和apply指定上下文

JS中函数的上下文和上下文规则

一、函数的上下文

  • 函数中可以使用this关键字,它表示函数的上下文
  • 函数中的this具体指代什么必须通过调用函数时的“前言后语”来判断
  • 函数的上下文由调用方式决定
    1.情形1:对象打点调用函数,函数中的this指代这个打点的对象xiaoming.sayHello()
    2. 情形2:圆括号直接调用函数,函数中的this指代window对象var sayHello = xiaoming.sayHello;
    sayHello();
    总之,函数只有被调用,它的上下文才能被决定

二、上下文规则
(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();  //构成对象.方法()的 形式,适用规则1  结果为7

(2)规则二:圆括号直接调用函数,则函数的上下文是window对象函数()

function fun() {
    return this.a + this.b;
}
var a = 1;
var b = 2;
var obj = {
    a: 3,
    b: fun(),   //适用于规则2  window对象  3
    fun: fun
};
var result = obj.fun();    //适用于规则1  结果为6
console.log(result);

(3)规则三:数组(类数组对象)枚举出函数进行调用,上下文是这个数组(类数组对象)数组[下标]()

var arr = ['A', 'B', 'C', function () {
    console.log(this[0]);
}];
arr[3]();    //A

(4)规则四:IIFE中的函数,上下文是window对象

(function() {
 })();
var a = 1;
var obj = {
    a: 2,
    fun: (function () {  //IIFE立即执行,返回内层函数
        var a = this.a;   //适用规则4,this.a是window  a属性即1
        return function () {
            console.log(a + this.a);  //前面指闭包中的a值,即1,this.a是规则1中 2
        }   //适用规则4 
    })()    //最后结果3
};
obj.fun()  //适用规则1  即2   

(5)规则五:定时器、延时器调用函数,上下文是window对象setInterval(函数, 时间); setTimeout(函数, 时间);

var obj = {
    a: 1,
    b: 2,
    fun: function () {
        console.log(this.a + this.b);
    }
}
var a = 3;
var b = 4;
setTimeout(obj.fun, 2000);   //适用规则五  7
var obj = {
    a: 1,
    b: 2,
    fun: function () {
        console.log(this.a + this.b);
    }
}
var a = 3;
var b = 4;   
setTimeout(function () {   //延时器调用的是外层的匿名函数
    obj.fun();    //适用规则1  //真正调用函数的不再是延时器,而是obj.fun调用的。
}, 2000);    

(6)规则六:事件处理函数的上下文是绑定事件的DOM元素

DOM元素.onclick = function () { };

案例1:实现效果:点击哪个盒子,哪个盒子就变红,要求使用同 一个事件处理函数实现


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{
            width: 200px;
            height: 200px;
            float: left;
            border: 1px solid #000;
            margin-right: 10px;
        }
    </style>
</head>
<body>
    <div id="box1"></div>
    <div id="box2"></div>
    <div id="box3"></div>

    <script>
        function setColorToRed() {
            this.style.backgroundColor = 'red';
            //事件处理中表示绑定事件的元素
        }

        var box1 = document.getElementById('box1');
        var box2 = document.getElementById('box2');
        var box3 = document.getElementById('box3');

        box1.onclick = setColorToRed;
        box2.onclick = setColorToRed;
        box3.onclick = setColorToRed;
    </script>
</body>
</html>

案例二:实现效果:点击哪个盒子,哪个盒子在2000毫秒后就变红,要求使用同一个事件处理函数实现


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{
            width: 200px;
            height: 200px;
            float: left;
            border: 1px solid #000;
            margin-right: 10px;
        }
    </style>
</head>
<body>
    <div id="box1"></div>
    <div id="box2"></div>
    <div id="box3"></div>

    <script>
        function setColorToRed() {
            // 备份上下文:用一个变量将外部的this备份一下,不会干扰了
            var self = this;
            setTimeout(function() {
                self.style.backgroundColor = 'red';
            }, 2000);
            //事件处理时的上下文是点击的那个盒子DOM元素 -> 符合规则六-> 存储到self
            //但是里面加了一层函数,加了延时器。函数上下文就变了  符合规则五
        }

        var box1 = document.getElementById('box1');
        var box2 = document.getElementById('box2');
        var box3 = document.getElementById('box3');

        box1.onclick = setColorToRed;
        box2.onclick = setColorToRed;
        box3.onclick = setColorToRed;
    </script>
</body>
</html>

总结:
问:什么时候需要备份?‘
答:当你的函数有内层函数,万一内层函数会改变上下文,就需要备份了

三、call和apply能指定函数的上下文
1.语法

函数.call(上下文);   //sum.call(xiaoming)
函数.apply(上下文);  //sum.apply(xiaoming)
function sum() {
    alert(this.chinese + this.math + this.english);
}
var xiaoming = {
    chinese: 80,
    math: 95,
    english: 93
}
sum.call(xiaoming)
sum.apply(xiaoming)

2.call和apply的区别

function sum(b1, b2) {
    alert(this.c + this.m + this.e + b1 + b2);
}
sum.call(xiaoming, 5, 3);   //call要用逗号罗列参数
sum.apply(xiaoming, [5, 3]);  //apply要把参数写到数组中

总结:
在这里插入图片描述
以及备份上下文
学到目前的微微一点总结,可能不太全面

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>