JS中的this指向问题

此文首发于 https://lijing0906.github.io在上篇JS继承中涉及到的好几个知识点都想写,比如call()、apply()从而牵出和bind()的区别,由Object.create()想到与new Object()、{}的区别,原型链以及作用域,然而在参考其他博客时发现,应该先把JS中的this指向弄明白。《你不知道的JavaScript》(上卷)第二部分讲到了this,...
摘要由CSDN通过智能技术生成

此文首发于 https://lijing0906.github.io
在上篇JS继承中涉及到的好几个知识点都想写,比如call()apply()从而牵出和bind()的区别,由Object.create()想到与new Object(){}的区别,原型链以及作用域,然而在参考其他博客时发现,应该先把JS中的this指向弄明白。
《你不知道的JavaScript》(上卷)第二部分讲到了this,算是比较权威的关于this的讲解,但我觉得有些地方讲得还是晦涩难懂,需要结合一些博客来理解会容易理解一些。

为什么要用this

this提供一种优雅的方式来隐式“传递”一个对象引用,在函数中显示传入一个上下文对象,避免在代码越来越复杂的情况下造成上下文对象混乱。

this到底是什么

this就像它的词性一样,是个代词,表指代什么,在JS中表示指代某个对象。this是在函数运行时绑定到某个对象上,并不是在函数定义时被绑定的,因此this的绑定(即this的指向)与函数的声明位置没关系,只取决于函数的调用方式。

绑定规则

说五种绑定规则之前,先说说不同作用域中this的指向,包括全局作用域(Global Scope)和局部作用域(Local Scope)。
全局作用域(Global Scope)
所有运行环境中JS运行时都只有唯一的全局对象,在浏览器中,全局对象是window;在node.js中全局对象是global
在全局作用域中(任何函数体外的代码),this指向的是全局对象,不管是不是在严格模式下。
局部作用域(Local Scope)
局部作用域可以理解为{}包裹的区域,this的指向就根据调用方法不同而不同。

一、默认绑定

  1. 独立函数调用,没有其他规则绑定时的默认规则,也是最常用的绑定规则,this指向全局对象window
function foo() {
    
    console.log(this);
    console.log(this.a);
}       
var a = 2; 
foo(); // Window对象  2
  1. 严格模式下,无法执行默认绑定把this绑定到全局对象上,因此,没有指定值时,this会绑定到undefined上。
    虽然this的绑定规则完全取决于调用位置,但是只有foo()***运行***在非严格模式下时,默认绑定才能把this绑定到全局对象;严格模式下***调用***函数则不影响默认绑定。
function foo() {
    // 运行在严格模式下,this会绑定到undefined
    "use strict";
    console.log(this.a);
}
var a = 2;
// 这里虽然foo()是在全局作用域中执行,但是foo里的代码运行在严格模式下,所以this被绑定到了undefined上。
foo(); // TypeError: Cannot read property 'a' of undefined

// --------------------------------------

function foo() {
   
    console.log(this.a);
}
var a = 2;
(function() {
    // 严格模式下调用函数则不影响默认绑定
    "use strict";
    foo(); // 2
})();

二、隐式绑定

当函数作为对象属性被调用时,函数中的this指向(被绑定到)调用这个函数的对象,这就是隐式绑定。注意:最后一层在调用中起作用,即最接近函数调用的那层起作用。

function foo() {
    
    console.log(this.a);
}
var a = 2;
var obj = {
    
    a: 3,
    foo: foo 
};
obj.foo(); // 3

为什么是3?那就需要了解一下内存中基础类型数据和引用数据类型是怎么存储的,可以看看阮一峰的JavaScript的this原理
上面代码的执行过程:获取obj.foo属性——>根据引用关系(引用地址)找到foo函数,执行函数调用。objfoo()最近,this被绑定到obj上。

  1. 多层调用
function foo() {
    
    console.log(this.a);
}
var a = 2;
var obj1 = {
    
    a: 4,
    foo: foo 
};
var obj2 = {
    
    a: 3,
    obj1: obj1
};
obj2.obj1.foo(); // 4

同样看一下调用过程:获取obj2.obj1属性——>根据引用关系(引用地址)获取obj1对象——>再重复第二步找到foo函数——>执行函数调用。obj1foo()最近,this被绑定到obj1上。
2. 隐式丢失(函数别名)

function foo() {
    
    console.log(this.a);
}
var
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值