JavaScript中this关键字指向规则详解与测试
本文通过四道测试题深入解析JavaScript中this关键字的指向规则。详细讲解了四种核心场景:普通函数调用指向window、匿名函数自执行指向window、new构造函数指向实例对象,以及apply/call强制绑定this。通过代码示例对比不同调用方式下的this差异,帮助开发者准确理解并控制this指向。
前言
JavaScript this关键字指向规则测试
JavaScript是一种基于对象的动态语言,这意味着在JS中万物皆对象,函数也不例外,它们也是普通的对象类型。JavaScript支持多种设计模式来实现面向对象编程,其中this关键字是实现这一特性的关键机制。为了帮助读者更好地理解,我们先通过一组测试题来检验对this指向的掌握程度。如果全部答对,说明你已经掌握了基础,无需继续阅读后续解析。
测试题目
第一题
<script>
var str = 'zhangsan';
function demo() {
var str = 'lisi';
alert(this.str);
}
window.demo(); // ??
var obj = {
str: "wangwu",
say: function() {
alert(this.str);
}
}
obj.say(); // ??
var fun = obj.say;
window.fun(); // ??
</script>
第二题
<script>
var username = 'zhangsan';
(function() {
var username = 'lisi';
alert(this.username); // ??
})()
function demo() {
var username = 'wangwu';
function test() {
alert(this.username);
}
test(); // ??
}
demo();
</script>
第三题
<script>
function Person() {
this.username = 'zhangsan';
this.say = function() {
alert('我叫' + this.username);
}
}
var p = new Person();
p.say(); // ??
var p1 = new Person();
p1.say(); // ??
</script>
第四题
<script>
var username = 'zhangsan';
function demo() {
alert(this.username)
}
var obj1 = {
username: "lisi"
};
var obj2 = {
username: "wangwu"
};
demo(); // ??
demo(obj1); // ??
demo(obj2); // ??
demo.call(obj1); // ??
demo.apply(obj2); // ??
</script>
答案
- 第一题:zhangsan wangwu zhangsan
- 第二题:zhangsan zhangsan
- 第三题:我叫zhangsan 我叫zhangsan
- 第四题:zhangsan zhangsan zhangsan lisi wangwu
(往下看,下面有详细解析哦)
this关键字的四种指向场景
this
- 指向调用函数的对象
- 无对象调用函数/匿名函数自调用(this指向window)
- 通过new产生的对象
- apply/call调用
场景一:指向调用函数的对象
一、指向调用函数的对象
<script>
// this:指向调用函数的对象
var str = 'zhangsan';
function demo() {
var str = 'lisi';
//this->window
console.log(this);
alert(this.str);
}
window.demo(); // zhangsan
var obj = {
str: "wangwu",
say: function() {
// this->obj
alert(this.str);
}
}
obj.say(); // wangwu
var fun = obj.say;
window.fun(); // zhangsan
</script>
- 当全局函数(如demo)作为window对象的方法被调用时,this指向window。
- 当通过对象调用其方法(如obj.say)时,this指向该对象(obj)。
- 如果将对象的方法赋值给一个普通变量(如var fun = obj.say),然后直接调用该变量(fun()),此时fun只是一个函数引用,并未通过对象调用。因此,this指向全局对象window。注意,只有obj.say()才是通过对象调用函数。
- 核心原则:谁调用了函数,this就指向谁。
场景二:无对象调用与匿名函数自执行
二、无对象调用函数/匿名函数自调用->this指向window
<script>
// 2.匿名函数自执行|匿名函数|无主函数 this->window
var username = 'zhangsan';
// 匿名函数自执行 this->window
(function() {
var username = 'lisi';
console.log(this); // window
alert(this.username); // zhangsan
})()
function demo() {
var username = 'wangwu';
// 无主函数 this->window
function test() {
// this->window
alert(this.username);
}
test(); // zhangsan
}
demo();
</script>
- 匿名函数没有名称,在浏览器环境中默认挂载到window对象上。
- 对于内部定义的函数test(),如果它没有被任何对象显式调用(既不是window也不是demo直接调用),它就像一个“无主”函数。在这种情况下,非严格模式下,this默认指向全局对象window。
场景三:通过new关键字产生对象
三、通过new产生的对象
<script>
// 3.通过new的对象:this指向产生的对象
// 函数
function Person() {
// 属性
this.username = 'zhangsan';
// 方法
this.say = function() {
// this->p
console.log(this); // Person对象
alert('我叫' + this.username);
}
}
// 实例化出一个对象:p就具有了username属性和say方法
var p = new Person();
console.log(p); // Person对象
console.log(p.username); // zhangsan
p.say(); // 我叫zhangsan
// this->p1
var p1 = new Person();
p1.say(); // Person对象 我叫zhangsan
</script>
- 当构造函数内部使用this定义属性和方法时,必须通过new关键字来实例化对象。new操作会创建一个新的对象,并将构造函数内部的this绑定到这个新对象上,从而使属性和方法具有实际价值。
场景四:apply与call方法调用
四、apply/call调用
首先我们需要了解apply()和call()方法的作用。
apply()和call()的本质都是调用函数,但它们允许你指定函数内部this的指向,即thisObj。
function.call([thisObj[,arg1[, arg2[, [,.argN]]]]])
function.apply([thisObj[,argArray]])
注意:
1. 虽然调用的是原函数,但函数内部的this会被强制指向传入的thisObj(即更改了对象内部的指针指向)。
2. 如果调用apply或call时没有传入第一个参数(thisObj),则默认this指向全局对象(浏览器中为window)。
3. call()与apply()的联系与区别
联系:两者的功能完全一致,第一个参数都是用于指定this指向的对象(thisObj)。
区别:主要在于传递后续参数的方式不同,当参数较多时体现明显。
call()要求将实参一一列出,作为独立的参数传递。
apply()要求将所有实参放置在一个数组中,作为第二个参数传递。
一个理解apply()/call()的实例:
<script>
// apply()/call()
function demo() {
console.log(123);
}
// 调用函数的时候,demo.call()/demo.apply()最终调用的还是demo()
demo(); // 123
demo.call(); //123
demo.apply(); // 123
</script>
<script>
// call()/apply()的区别:
// call()参数单独再call中罗列
// apply()的参数通过数组表示
function demo(m, n, a, b) {
alert(m + n + a + b);
}
demo(1, 5, 3, 4); // 13
demo.call(null, 1, 5, 3, 4); // 13
demo.apply(null, [1, 5, 3, 4]); // 13
</script>
this的第四个用法实例
<script>
// this的第四个用法:call(obj)/apply(obj):强制性的将this指向了obj
var username = 'zhangsan';
function demo() {
alert(this.username)
}
var obj1 = {
username: "lisi"
};
var obj2 = {
username: "wangwu"
};
// call()/apply():打劫式的改变了this的指向
demo(); // zhangsan
demo(obj1); //zhangsan
demo(obj2); //zhangsan
demo.call(obj1); // lisi
demo.apply(obj2); // wangwu
</script>
- 如果直接调用demo函数,无论是否传入obj1或obj2作为参数,demo依然属于window调用,this指向window。
- 无论使用call还是apply,最终执行的仍然是demo函数,但它们会强制将this指向第一个参数指定的对象(obj1或obj2)。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对本站的支持。
JavaScript闭包与类(Class)的区别及适用场景对比
2026-11-05 15:48:57
JavaScript入门要学ES6吗?let与箭头函数等新特性解析
2026-11-05 14:49:16
JavaScript 8种数据类型详解:基本类型与引用类型的区别
2026-11-05 14:25:15
怎么在JavaScript中使用async/await优化Ajax异步流程
2026-11-05 13:56:15
JavaScript replace回调函数实现动态正则替换逻辑
2026-11-05 13:52:13
