细说JavaScript中的this指向与绑定规则
本文深入解析JavaScript中this的指向机制,详细阐述默认绑定、隐式绑定、显示绑定及new绑定的4条核心规则。通过代码示例说明this在运行时的动态绑定特性,分析绑定优先级,并探讨null/undefined绑定、软绑定及箭头函数无this的特殊情况,帮助开发者准确掌握this行为。
this的指向
在浏览器环境中,全局作用域下的this通常指向window对象,且这一行为不受严格模式影响。但在实际开发中,this更多出现在函数内部。每当函数被调用时,JavaScript引擎会创建一个新的函数执行上下文,其中包含作用域链、活动对象(AO)以及当前函数的this绑定值。参考以下代码:
function foo() {
console.log(this)
}
foo()//window
var obj = {
name: 'why',
foo: foo
}
obj.foo()//obj
foo.apply("abc")//String{'abc'}上述代码定义了一个函数foo,用于输出调用时的this值。执行结果显示,分别指向window、obj以及String包装对象{'abc'}。由此可以得出以下结论:
- 函数在调用时,JavaScript引擎会默认给this绑定一个值;
- this的绑定结果与函数定义的位置(即编写代码时的位置)无关;
- this的绑定结果取决于函数的调用方式以及调用发生的位置;
- this是在代码运行时动态绑定的,而非在编译阶段固定。
判断this绑定的4条规则
规则1:默认绑定
当进行独立函数调用时,this始终绑定到window对象(非严格模式)或undefined(严格模式)。示例如下:
function foo() {
console.log(this)
}
function foo2() {
foo()
}
var obj = {
name: "xiaomin",
foo: function() {
console.log(this)
}
}
foo()//window
foo2()//window
var bar = obj.foo
bar()//window规则2:隐式绑定
若函数通过某个对象属性发起调用,则this隐式绑定到该对象上。具体表现为:
var obj1 = {
name: "obj1",
foo: function () {
console.log(this);
},
};
var obj2 = {
name: "obj2",
bar: obj1.foo,
obj1: obj1,
};
obj1.foo();//obj1
obj2.obj1.foo();//obj1
obj2.bar();//obj2规则3:显示绑定
利用函数的call、apply或bind方法,可以将this显式绑定到指定对象上。此时函数中的this将指向该对象:
function foo() {
console.log(this)
}
var obj = {
name: "obj"
}
foo.call(obj)
foo()//obj
foo.apply(obj)
foo()//obj
var newfoo = foo.bind(obj)
newfoo()//obj规则4:new绑定
参考以下代码示例:
function Person(name, age) {
this.name = name
this.age = age
console.log(this)//p
}
var p = new Person("kobe",12);此处定义了一个构造函数Person,并通过new关键字创建对象。使用new调用构造函数创建对象时,主要经历以下5个步骤:
- 在内存中创建一个空对象;
- 将该新对象的[[prototype]]属性指向构造函数的prototype属性;
- 将构造函数内部的this指向这个新创建的空对象;
- 开始执行构造函数体内的代码;
- 若构造函数没有显式返回其他对象,则将该新对象作为返回值返回。
由上述过程可知,在使用new创建对象时,第3步会将构造函数内部的this绑定到新对象上。因此,上述代码中Person函数内打印的this即为通过new关键字创建的对象p。
this绑定的优先级
当多种绑定规则同时存在时,this的指向将依据规则的优先级确定:
- 默认绑定的优先级最低;
- 显示绑定优先于隐式绑定。如下列代码所示,打印的this不再是obj,而是String包装对象{'aaa'}:
function foo() {
console.log(this);//String {'aaa'}
}
var obj = {
name: "obj",
foo: foo.bind("aaa"),
};
obj.foo();- new绑定优先于隐式绑定。如下列代码所示,打印出的this不是obj,而是新创建的对象f:
var obj = {
name: "obj",
foo: function () {
this.name = "kkk";
console.log("this:", this);//foo {name: 'kkk'}
},
};
var f = new obj.foo();- new绑定优先于bind绑定(注意:new绑定不能与call、apply同时使用)。如下代码所示,this打印的是obj对象而非String包装对象{'aaa'}:
function foo() {
console.log(this);
}
var bar = foo.bind("aaa");
var obj = new bar();
//var obj2 = new foo.apply("123");//这样写会报错除了四个this绑定规则外的特殊情况
1、在显示绑定中,若绑定的值为null或undefined,this将回退到默认绑定,即指向window对象(非严格模式);
function foo() {
console.log(this)
}
foo.call({})//{}
foo.call(null)//window
foo.call(undefined)//window2、函数间接引用:在下列代码中,赋值表达式 p.foo = o.foo 的返回值是目标函数的引用,因此实际调用位置是 foo(),而非 o.foo()。所以打印出来的this是window,而不是o或p;
function foo() {
console.log(this);
}
var o = { foo: foo };
var p = {};
o.foo(); // o
(p.foo = o.foo)(); // window3、箭头函数:箭头函数自身不绑定this。在调用箭头函数时,其执行上下文中不会生成this记录。若在箭头函数体内使用this,它将在外层作用域中查找this。参考以下代码:
var obj = {
data: [],
changeData: function () {
console.log("普通函数this:", this);
(() => {
console.log("箭头函数this:", this);
})();
setTimeout(() => {
this.data = ["1", "2", "3"];
console.log("this:", this);
}, 1000);
},
};
obj.changeData();打印结果:

可以看出,上述打印的this均指向obj。由于箭头函数自身没有this,它向外层作用域查找,找到了changeData函数。此时,由于隐式绑定规则,changeData由obj调用,其this指向obj,因此箭头函数的this也指向obj。
以上就是细说JavaScript中的this指向与绑定规则的详细内容,更多关于JavaScript this的资料请关注本站其它相关文章!
JS大数值转字符串出现科学计数法怎么办
2026-11-05 17:09:21
JS split切割后出现空字符串怎么过滤
2026-11-05 16:00:30
在 React 或 Vue 项目中封装使用 JS 节流防抖
2026-11-05 15:27:29
JavaScript中怎么将带小数的字符串转为整数?
2026-11-05 14:32:38
怎么用JavaScript策略模式重构电商促销计算逻辑?
2026-11-05 14:01:09
