视频加载失败

JavaScript面向对象之上下文规则

1583 字
8 分钟
JavaScript面向对象之上下文规则

本文主要学习面向对象中的上下文规则,以及怎么改变上下文

认识上下文#

函数的上下文

  • 函数中可以使用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,
function () {
console.log(this.a + this.b);//不知道,因为没有调用,函数只有被调用,它的上下文才能被确定
}
};

例子1:

var obj = {
a: 1,
b: 2,
fn: function () {
console.log(this.a + this.b);
}
};
obj.fn();//this指向obj

例子2:

var obj = {
a: 1,
b: 2,
fn: function () {
console.log(this.a + this.b);
}
};
var fn = obj.fn;
fn();this指向window

上下文规则#

函数的上下文由调用函数的方式决定

  • 函数的上下文(this关键字)由调用函数的方式决定, function是“运行时上下文”策略
  • 函数如果不调用,则不能确定函数的上下文

规则1

  • 规则1:对象打点调用它的方法函数,则函数的上下文是这 个打点的对象

    对象.方法()
    function fn() {
    console.log(this.a + this.b);
    }
    var obj = {
    a: 66,
    b: 33,
    fn: fn,
    };
    obj.fn(); //99
    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
    function outer() {
    var a = 11;
    var b = 22;
    return {
    a: 33,
    b: 44,
    fn: function () {
    console.log(this.a + this.b);
    },
    };
    }
    outer().fn(); //77
    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

规则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
    function fun() {
    return this.a + this.b;
    }
    var a = 1;
    var b = 2;
    var obj = {
    a: 3,
    b: fun(),//3
    fun: fun,//obj.fun === window.fun true
    };
    var result = obj.fun();//6,一个铁律:函数只有在调用的时候才能确定上下文 obj.a + obj.b 3+3
    console.log(result);//6

规则3

  • 数组(类数组对象)枚举出函数进行调用,上下文 是这个数组(类数组对象)

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

类数组对象

  • 什么是类数组对象:所有键名为自然数序列(从0开始), 且有length属性的对象

  • arguments对象是最常见的类数组对象,它是函数的实参列 表

    function fun() {
    arguments[3]();
    }
    fun('A', 'B', 'C', function () {
    console.log(this[1]);
    });//’B‘

规则4

  • IIFE中的函数,上下文是window对象

    (function() {
    })();
    var a = 1;
    var obj = {
    a: 2,
    fun: (function () {
    var a = this.a;//1 IIFE中的函数,上下文是window对象所以这里this指向全局a 即1
    return function () {
    console.log(a + this.a);//这里的this取决于调用,obj.fun(),所以this是obj,即a等于2 ,1+2=3
    };
    })(),
    };
    obj.fun();//3

规则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);//定时器、延时器调用函数,上下文是window对象,所以这里指向的不是obj,虽然是obj调用,但是是setTimeout里面调用所以是window对象,所以是7,注意这里obj.fun并没有执行,而是2秒后执行
    var obj = {
    a: 1,
    b: 2,
    fun: function () {
    console.log(this.a + this.b);
    },
    };
    var a = 3;
    var b = 4;
    setTimeout(function () {
    obj.fun();//这里已经执行,函数这里指向obj,所以是3,2秒后也是3
    }, 2000);

规则6

  • 事件处理函数的上下文是绑定事件的DOM元素

    DOM元素.onclick = function () {
    };
  • 请实现效果:点击哪个盒子,哪个盒子就变红,要求使用同 一个事件处理函数实现

<style>
.box {
width: 100px;
height: 100px;
border: 1px solid #000;
margin: 10px;
display: inline-block;
}
</style>
</head>
<body>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<script>
var boxes = document.querySelectorAll('.box');
for (var i = 0; i < boxes.length; i++) {
boxes[i].onclick = changeColor;
}
function changeColor() {
this.style.backgroundColor = 'red';
}
</script>
</body>
  • 请实现效果:点击哪个盒子,哪个盒子在2000毫秒后就变红 ,要求使用同一个事件处理函数实现

    var boxes = document.querySelectorAll('.box');
    for (var i = 0; i < boxes.length; i++) {
    boxes[i].onclick = changeColor;
    }
    function changeColor() {
    var that = this; // 保存当前点击的盒子
    setTimeout(function () {
    that.style.backgroundColor = 'red';
    }, 2000);
    }

call和apply#

call和apply能指定函数的上下文

先来看个例子:

function sum() {
alert(this.chinese + this.math + this.english);
}
var xiaoming = {
chinese: 80,
math: 95,
english: 93,
};
//想用xiaoming调用sum,就需要sum成为xiaomin的上下文也就是下面
var xiaoming = {
chinese: 80,
math: 95,
english: 93,
sum:sum
};

但是现在有更简单的方式:

sum.call(xiaoming);
sum.apply(xiaoming);

就可以让sum的上下文成为xiaomin对象的上下文

function sum() {
// alert(this.chinese + this.math + this.english);
console.log(this.chinese + this.math + this.english);
}
var xiaoming = {
chinese: 80,
math: 95,
english: 93,
};
sum.call(xiaoming);
sum.apply(xiaoming);

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要把参数写到数组中

到底使用call还是apply?

function fun1() {
fun2.apply(this, arguments);//arguments是类数组,所以只能使用apply
}
function fun2(a, b) {
console.log(a + b);
}
fun1(33, 44);//77

上下文规则总结

规则上下文
对象.函数()对象
函数()window
数组[ 下标 ] ()数组
IIFEwindow
定时器window
DOM事件处理函数绑定DOM的元素
call和apply任意指定

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

JavaScript面向对象之上下文规则
https://f.youzi177.cn/posts/2026102006javascript-mian-xiang-dui-xiang-zhi-shang-xia-wen-gui-ze/
作者
小封鸭
发布于
2026-10-20
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
小封鸭
小楼一夜听春雨,深巷明朝卖杏花
公告
欢迎来到我的博客。这里主要记录前端全栈和日常内容
分类
标签
最新动态
站点统计
文章
60
分类
3
标签
12
总字数
107,734
运行时长
0 天
最后活动
0 天前
站点信息
构建平台
EdgeOne Pages
博客版本
Firefly v6.16.8
文章许可
CC BY-NC-SA 4.0
文章目录