javascript中的this详解

本文详细解析了JavaScript中this关键字的指向规则,包括普通函数调用、对象方法调用、构造函数调用、apply/call/bind的应用及setTimeout中的this指向问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

首先我们扫一下盲:this在javascript这门语言中只有在函数内部才有被讨论的价值。
this的指向应该始终由调用方来决定,而不是由定义方决定。当然我们这篇文章是针对ES5,至于ES6中箭头函数的this指向由定义方决定这种问题我们这里不进行讨论

应用场景分析

1、普通函数调用
普通函数的调用,在非严格模式下this指向window,当然严格模式下修复了指向window这个bug,我们在这儿不在赘述,因为这不是我们这次讨论的范畴。

var name = 'ice';
function foo() {
  this.age = 18;
  return this.name;
}
foo(); // ice
console.log(age); // 18

2、对象方法调用

  • 当作为对象方法调用,this通常指向该对象
var name = 'ace';
function getName() {
  return this.name;
}
var obj = {
  name: 'ice',
  getName: getName
}
obj.getName(); // ice
  • 也会有一些“对象方法的调用并未指向该对象”的情况,其实不然,新对象的方法调用时并未继承旧对象的作用域,所以this还是指向新对象,如下:
// 例1
function getName() {
  return this.name;
}
var obj = {
  name: 'ice',
  getName: getName
}
var _obj = {
  name: 'ace',
  getName: obj.getName
}
_obj.getName(); // ace

// 例2
document.body.onclick = obj.getName;
// 当点击body元素输出:undefined,此时this指向body元素

3、构造函数被调用
作为构造函数时,this指向该构造函数实例化的对象。当然也有奇葩的写法来扰乱我们的视线,即使这样并不会改变this的指向,只是实例的作用域问题,如下例2:

// 例1
function Person() {
  this.name = 'ice';
}
var person = new Person();
console.log(person.name); // ice

// 例2
function Person() {
  this.name = 'ice';
  return {name: 'ace'}
}
var person = new Person();
console.log(person.name); // ace

4、apply、call、bind做主了
apply和call可以在调用期间改变this指向,而bind可以在函数定义期间就可以改变this指向:

// 例1
function getName() {
  return this.name;
}
var obj = {
  name: 'ice',
  getName: getName
}
obj.getName.call({name: 'ace'}) // ace
/**
 * obj.getName.apply({name: 'ace'}) // ace
 */

// 例2
function getName() {
  return this.name;
}
var obj = {
  name: 'ice',
  getName: getName.bind({name: 'ace'})
}
obj.getName() // ace

5、setTimeout
我们最后来说一个使用场景很多,但this定位很尴尬的使用方式setTimeout,当作为setTimeout的回调函数时,this指向window(当然是非严格模式),不过我们可以用bind或者参数传递等方法实现功能(例3):

// 例1
var name = 'ice';
setTimeout(function() {
   console.log(this.name); // ice
}, 1000)

// 例2
function showTagName() {
  console.log(this);
  console.log(this.tagName);
}
var obj = {
  tagName: 'OBJ',
  showTagName: showTagName
}
document.body.onclick = function() {
  setTimeout(showTagName, 1000)
  // 1、window。2、undefined
}

// 例3
document.body.onclick = function() {
  setTimeout(showTagName.bind(this), 1000) 
  // 1、body元素。2、"BODY"
}

至此我们对于javascript这门语言的this指向有了一个比较清晰的理解了,其实导致this指向这么杂乱的主要原因是javascript之父(布兰登·艾奇(Brendan Eich,1961年~))只用相当短的时间(10天)创造了这门语言,已经很伟大了,有诸如this这种问题不可避免。

ES6、ES7、ES8、node等都在完善javascript,它依然是当下最流行的脚本语言,所以好好撸吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值