JavaScript 函数4种调用方式与 this 指向全解析
JavaScript 中 this 的指向常被混淆,其核心逻辑在于区分函数的定义位置与调用时机。本文将系统梳理独立调用、方法调用、构造函数调用及间接调用(call/apply/bind)四种模式下 this 的绑定规则,并解析 strict 模式下的行为差异,提供可直接运行的代码验证结论。
结果与目标
在 JavaScript 中,this 是一个动态绑定的关键字,它不取决于函数在哪里声明,而取决于函数如何被调用。掌握这四种调用模式及其对应的 this 指向,是编写健壮前端代码的基础。
准备条件
无需额外安装工具,现代浏览器控制台(Console)或 Node.js 环境即可进行以下测试。建议在开发环境中直接运行代码块以观察日志输出。
第1步:独立调用与方法调用
目的:理解全局环境与对象方法调用时 this 的默认行为。
背景知识:
- 作用域链:取决于函数声明的位置,从函数内部向外延伸至全局对象(
window),与调用位置无关。 - 独立调用:
func()形式调用时,在非严格模式下this默认指向全局对象window。 - 方法调用:
obj.func()形式调用时,this指向触发调用的对象obj。
关键现象:即使函数嵌套在方法内部,如果内部函数是独立调用,其 this 仍指向 window(非严格模式)。
<script type="text/javascript">
// 全局环境中,this 指向 window
console.log(this === window); // true
function abc(){
console.log(this === window); // true
}
abc(); // 独立调用,this 指向 window
var o = {
m: function(){
return this; // 指向对象 o
},
n: function(){
function test(){
return this; // 独立调用,指向 window
}
return test();
}
};
console.log(o.m()); // Object {m: ..., n: ...} (即对象 o)
console.log(o.n()); // Window {...} (即全局对象)
</script>
技巧提示:若需在内层函数中访问外层方法的 this,需将其保存至变量(如 that)通过作用域链引用。
<script type="text/javascript">
var o = {
n: function(){
var that = this; // 缓存 this 引用
function test(){
console.log(that); // 输出对象 o
}
test();
}
};
o.n();
</script>
第2步:构造函数调用
目的:掌握使用 new 关键字创建实例时 this 的变化及返回值处理。
操作逻辑:new 关键字会经历以下步骤:
- 创建一个空对象。
- 将新对象的
__proto__指向构造函数的prototype。 - 将构造函数内部的
this指向该空对象。 - 执行构造函数代码。
- 返回新对象(除非显式返回一个对象)。
参数规范:约定构造函数首字母大写(如 Person),以区别于普通函数。
<script type="text/javascript">
var Person = function (user, age) {
this.user = user;
this.age = age;
};
var shane = new Person('shane', 25);
console.log(shane.user); // 'shane'
</script>
返回值陷阱:
- 返回基本类型(如字符串、数字):忽略返回值,
this仍指向新实例。 - 返回对象(包括
null):new表达式的结果将是该返回的对象。
<script type="text/javascript">
var Size = function(){
this.size = 'big';
return {}; // 返回对象,新对象丢失
};
var sizeBig = new Size;
console.log(sizeBig.size); // undefined
</script>
第3步:间接调用(显式绑定)
目的:通过 call、apply、bind 强制改变函数执行时的 this 指向。
区别对比:
call(obj, arg1, arg2):立即执行,参数列表展开。apply(obj, [arg1, arg2]):立即执行,参数为数组。bind(obj, arg1, arg2):返回一个新的绑定函数,需手动调用才执行。
<script type="text/javascript">
var add = function(a, b) { return a + b; };
var arr = [2, 3];
var sum0 = add.apply(null, arr); // 5,参数为数组
var sum1 = add.call(null, arr[0], arr[1]); // 5,参数为逗号分隔
var sum2 = add.bind(null, arr[0], arr[1]); // 返回函数
console.log(sum2); // function (a,b) {return a+b;};
console.log(sum2()); // 5,必须加上括号执行
</script>
第4步:严格模式下的差异
目的:识别 'use strict' 对未指定上下文调用的影响。
变化点:在严格模式下,独立调用的函数 this 不再默认为 window,而是 undefined。
<script type="text/javascript">
'use strict';
function a() {
console.log(this); // undefined
}
a();
// 若想指向 window,需显式绑定
window.a(); // Window
</script>
注意:尽管严格模式下独立调用 this 为 undefined,但 setTimeout 回调中的 this 通常仍指向 window,因为它是作为 window 的方法被调用的。
完成判断
你可以通过在不同模式的控制台中运行上述代码块,确认 this 的输出是否符合预期。特别是构造函数返回值和 bind 的延迟执行特性,是面试和实战中常见的易错点。
简要总结
以上就是 JavaScript 函数的4种调用方式与 this 的指向的详细内容,更多关于 JavaScript 函数调用机制与上下文绑定的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













