JavaScript this 绑定规则与指向详解
本文详细解析 JavaScript 中 this 的四种绑定规则:默认、隐式、显式及 new 绑定,并阐述其优先级顺序。同时对比 call、apply、bind 三个改变 this 指向方法的区别,结合代码示例说明箭头函数对 this 的影响及实际应用场景。
一、this 绑定
怎么理解 this?
实际上,this 是一个指针,指向当前的执行环境,用于对该环境进行操作。
MDN 指出:通常,函数的调用方式决定 this 的值(运行时绑定)。this 在执行期间不可赋值,每次调用时其值可能不同。ES5 引入 bind 方法以固定函数的 this 值,无视调用方式。ES2015 引入箭头函数,其自身不提供 this 绑定(保持词法上下文的 this 值)。
this 是如何绑定的?
函数的 this 在调用时绑定,完全取决于调用位置。确定调用位置后,应用以下四种绑定规则判断 this 指向。
1、默认绑定
函数 this 默认绑定到全局对象 window;严格模式下,this 绑定为 undefined。
function foo (){
console.log(this.a)
}
let a = 1
foo() // 12、隐式绑定
调用位置是否存在上下文对象,或被某对象拥有/包含。
function foo(){
console.log(this.a)
}
let obj = {
a: 2,
foo:foo
}
let a = 1
obj.foo(); // 2
function foo(){
console.log(this.a)
}
let obj1 = {
a: 2,
foo: foo
}
let obj2 = {
a: 3,
obj1: obj1
}
let a = 1
obj2.obj1.foo(); // 2
3、显式绑定
直接改变 this 指向,将其绑定至另一执行环境。
function foo(){
console.log(this.a)
}
let obj = {
a: 1
}
foo.call(obj)4、new 绑定
使用 new 调用的函数,其 this 绑定到新创建的对象。
function Foo(a){
this.a = a
}
let bar = new Foo(2)
console.log(bar.a) // 2
this 绑定优先级
默认绑定的优先级最低。
new 绑定 > 显式绑定 > 隐式绑定 > 默认绑定
1、显示绑定 VS 隐式绑定
function foo(){
console.log(this.a)
}
let obj1 = {
a: 1,
foo: foo
}
let obj2 = {
a: 2
}
console.log(obj1.foo()) // 1
obj1.foo.call(obj2) // 2
通过代码可见,显式绑定优先级高于隐式绑定。
2、显示绑定 VS new 绑定
function foo(a){
this.a = a
}
let obj1 = {
foo
}
let bar = foo.bind(obj1)
bar(2)
console.log(obj1.a) // 2
let bar2 = new bar(3)
console.log(obj1.a) // 2
console.log(bar2.a) // 3
new 修改了显式绑定调用 bar 中的 this,故 new 绑定优先级高于显式绑定。
二、this 指向
判断准则
第一准则:this 永远指向函数运行时所在的对象,而非创建时所在对象(箭头函数除外)。
第二准则:无论是否严格模式,全局执行环境(函数体外)中 this 均指向全局对象。
判断顺序
- 函数是否在 new 中调用?若是,this 绑定新创建对象;
- 函数是否通过 call、apply、bind 调用?若是,this 绑定指定对象;
- 函数是否在特定上下文中调用?若是,this 绑定调用上下文;
- 其他情况,this 绑定全局对象,严格模式下为 undefined。
常见的指向问题
- 箭头函数无自身 this 指针(需从执行上下文判断)。
三、改变 this 指向
有四种方式
- 变量保存 this:临时保存 this 值。
- call():使用指定 this 值和单独给出的一个或多个参数调用函数。
- bind():返回一个新函数,拥有原函数作用域。
- apply():调用具有给定 this 值的函数,参数以数组(或类数组对象)形式提供。
变量保存 this
var _this = window;
var obj = {
name:"张三",
show:function(){
console.log(this) //obj
console.log(_this) // window
}
}
obj.show()
call
call() 方法使用指定 this 值和单独给出的一个或多个参数调用函数。
函数名称.bind(参数1,参数2,a,b,c.....) 参数1:当前函数的作用域 参数2:需要传递的参数,参数是一个一个传
function fn(a,b){
console.log(this,a,b)
}
document.onclick = functioin(){
fn.call(document,1,2)
}
可使用 call 实现继承:定义方法后,让新对象继承它(无需在新对象中重写该方法)。
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
function Toy(name, price) {
Product.call(this, name, price);
this.category = 'toy';
}
var cheese = new Food('feta', 5);
var fun = new Toy('robot', 40);
bind
bind 创建新函数,调用时新函数的 this 指定为 bind 第一个参数,其余参数供调用时使用。
特性是返回一个新函数体,拥有第一个函数作用域。
函数名称.bind(参数1,参数2.....)() // 必须调用一下 参数1:当前函数的作用域 参数2:需要传递的参数
var obj = {
name:"张三",
show:function(val){
console.log(this) //obj 没有修改前
console.log(this,1) // document 1 修改后
}
}
obj.show().bind(document,1)()
MDN:ECMAScript 5 引入 Function.prototype.bind()。调用 f.bind(someObject) 创建与 f 相同函数体和作用域的新函数,但新函数中 this 永久绑定至 bind 第一个参数,无论调用方式。
apply
apply() 方法调用具有给定 this 值的函数,参数以数组(或类数组对象)形式提供。
函数名称.bind(参数1,[参数2,a,b,c.....]) 参数1:当前函数的作用域 参数2:需要传递的参数 数组
function fn(a,b,c){
console.log(this,a,b,c)
}
document.onclick = functioin(){
fn.apply(document,[1,2,3])
}
call ,apply ,bind 三者的区别
不同点:
- bind 有返回值(函数体),需加 () 调用。
- call,apply 无返回值,改变 this 指向时函数即执行,无需加 () 调用。
- call 传递参数时是一个一个传递的。
- apply 是传递一个数组或者类数组对象的参数。
到此这篇关于JavaScript this绑定与this指向问题的解析的文章就介绍到这了,更多相关JavaScript this绑定与this指向内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
JS动态构建复杂嵌套JSON对象的方法
2026-11-05 15:41:52
JS负数取余为什么是负数?详解余数与模运算区别
2026-11-05 13:34:41
JS 解压出现乱码或报错怎么解决?
2026-11-05 12:32:38
JS 中 startsWith、indexOf 与正则判断字符串前缀的对比
2026-11-04 22:19:43
JS解析Excel后怎么将数据转换为JSON格式
2026-11-04 20:58:28
