JavaScript中this指向规则与call/apply/bind用法详解
本文详细解析JavaScript中this关键字在不同调用场景下的指向规则,包括全局环境、对象方法、定时器及事件处理等。重点讲解call、apply和bind三个改变this指向的方法,对比它们在参数传递、执行时机及返回值上的区别,并结合数组操作示例说明apply的实际应用。
this关键字
在JavaScript中,this的指向取决于函数被调用的方式。简单来说,哪个对象调用了函数,函数内部的this就指向哪个对象。
在严格模式下,如果在全局环境中调用函数,this的值是undefined。
在非严格模式下,如果在全局环境中调用函数,this的值指向全局对象window(在浏览器环境中)。
当直接调用全局定义的函数时,this指向window。
function fn(){
console.log(this);
// 此时 this 指向 window
}
fn();
// 相当于 window.fn()
当通过对象内部的方法调用函数时,this指向调用该方法的对象。
var obj = {
fn:function(){
console.log(this);
}
}
obj.fn();
// 此时 this 指向 obj
在定时器的处理函数中,this指向window。
setTimeout(function(){
console.log(this);
},0)
// 此时定时器处理函数里面的this 指向 window
在事件处理函数中,this指向触发该事件的事件源元素。
div.onclick = function(){
console.log(this);
}
//当你点击 div 的时候,this指向 div
在自调用函数(立即执行函数表达式)中,this指向window。
(function () {
console.log(this)
})()
// 此时 this 指向 window
改变 this 指向
上述内容涵盖了函数基本调用方式中的this指向规则。此外,JavaScript提供了三种方法可以忽略函数原本的this指向,强制将其指向其他对象。这三种方法分别是call、apply和bind,它们用于强行改变函数执行时的this绑定。
- call、apply和bind都附加在函数调用之后使用,它们的核心作用是忽略函数本身的this绑定,转而指定新的this指向。
- 需要注意的是,call和apply在调用时会立即执行函数,而bind则会创建一个新的函数,该新函数需要被手动调用才会执行。
call
语法格式为:fn.call(指定this指向的对象, arg1, arg2, ...)。
其作用是调用被绑定的函数fn,同时指定函数内部this的指向,并传递参数。
参数说明如下:
- 第一个参数指定函数内部this指向的对象。
- 其余参数是需要传入函数的值,可以有多个,使用逗号分隔。
使用 call 方法不传参
var num = 666;
function fn() {
console.log('num = ', this.num);
}
fn.call(); // num = 666
使用 call 方法指定this
var name = 'Rose';
var obj = {name:'Jack'};
function fn(){
console.log(this.name);
}
fn(); // Rose
fn.call(); // Rose
fn.call(obj); // jack
使用 call 方法指定this并传参
var name = 'Rack';
var obj = {name:'Jack'};
function fn(a,b){
console.log(this,a,b);
}
fn(1,2); // window 1 2
fn.call(obj,1,2); // obj 1 2
fn(1,3); // window 1 3
apply
apply方法与call类似,但它接受的第二个参数是一个包含多个值的数组。
语法格式为:fn.apply(指定this指向的对象, [arg1, arg2, ...])。
其作用是调用被绑定的函数fn,指定函数内部this的指向,并传递参数。
参数说明如下:
- 第一个参数指定this指向的对象。
- 第二个参数是一个数组,包含需要传入函数的多个参数。
var obj = {name:'jack'};
function fn(a,b){
console.log(this,a,b);
}
fn(1,2); // window 1 2
fn.apply(obj,[1,2]); // obj 1 2
使用 apply 合并数组
如果使用push将元素追加到数组,且参数是数组,它会将该数组作为一个单独的元素添加,而不是将数组内的每个元素分别添加,最终结果是一个包含数组的数组。
var arr1 = [1,2];
var arr2 = [3,4];
arr1.push(arr2);
console.log(arr1); // [1,2,[3,4]]
concat方法虽然可以合并数组,但它不会修改现有数组,而是创建并返回一个新数组。
var arr1 = [1,2];
var arr2 = [3,4];
var arr3 = arr1.concat(arr2);
console.log(arr1); // [1,2]
console.log(arr3); // [1,2,3,4]
如果希望将元素追加到现有数组而不创建新数组,除了使用循环,apply方法可以派上用场。
var arr1 = [1,2];
var arr2 = [3,4];
arr1.push.apply(arr1,arr2);
console.log(arr1); // [1,2,3,4]
使用 apply 与内置函数连用
/* 找出数组中最大/小的数字 */
var numbers = [5, 6, 2, 3, 7];
var max = Math.max(numbers)
var min = Math.min(numbers)
console.log(min,max); // NaN NaN
var max = Math.max.apply(null, numbers);
/* 基本等同于 Math.max(numbers[0], ...) 或 Math.max(5, 6, ..) */
var min = Math.min.apply(null, numbers);
console.log(min,max); // 2 7
bind
语法格式为:fn.bind(指定this指向的对象, arg1, arg2, ...)。
其作用是创建一个新的绑定函数,指定该新函数的this指向并预设参数。必须调用这个新创建的函数,代码才会执行。
参数说明如下:
- 第一个参数指定this指向的对象。
- 其余参数是需要传入的值,可以有多个,使用逗号分隔。
var obj = {name:'jack'};
function fn(a,b){
console.log(this,a,b);
}
fn(1,2); // window 1 2
fn.bind(obj,1,2); // 未调用不执行
fn.bind(obj,1,3)() // obj 1 3
var newFn = fn.bind(obj,3,4);
newFn(); // obj 1 4
newFn(5,6); // obj 3 4
总结
到此这篇关于JavaScript函数中this指向问题的文章就介绍到这了,更多相关JavaScript函数this指向内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
ES6模块化中js文件怎么用import和export交互
2026-11-05 17:00:48
JS读取本地文件时报错或无响应的常见原因
2026-11-05 16:32:31
let、const与var的区别:JavaScript变量声明最佳实践
2026-11-05 14:16:38
JS中直接定义静态二维数组的字面量写法
2026-11-05 14:16:08
JS 怎么查找字符串中所有匹配项的位置
2026-11-05 14:15:53
