浏览器原理:4.6JS中的this

this机制的背景

  • 对象内部的方法中使用对象内部的属性是一个非常普遍的需求,但JS的作用域机制无法做到这一点!
let obj = {
	a:4;
	foo(){
		a = 3;
	}
}
obj.foo() // undifined

从上面可以发现,对象内部的方法如果通过作用域链来直接访问对象内部的变量会找不到,因为foo方法的outer是指向全局执行上下文的,所以这个时候 this 应运而生!需要注意的是,this 和 作用域链是两套不同的机制,二者之间并无多大联系

this 是什么

  • 在JS的执行上下文中,除了变量环境、词法环境,outer以外,还有一个 this,this是和执行上下绑定的,即每一个执行上下文中都会存在一个 this,this 随执行上下文分三种

    • 全局执行上下文 —— 全局 this (浏览器中一般指向 window对象)
    • 函数执行上下文 —— 函数中的 this
    • eval 的执行上下文 —— eval 中的 this (eval()用于执行一段JS代码)

重点关注函数中的 this

函数中的 this

function foo(){
	console.log(this)
}
foo() // window对象
window.foo() // window对象 

通常情况下,有三种方式来设置函数执行上下文中的 this 的指向

  • 通过函数的 call,bind,apply 方法
    let bar = {}
    function foo(){
    	console.log(this)
    }
    foo.call(bar) // bar对象
    foo.bind(bar) // function()...  bind() 返回的是一个新函数
    foo.bind(bar)() // bar 对象
    foo.apply(bar) // bar对象
    
  • 通过对象调用方法设置
    let bar = {
    	foo(){
    		console.log(this)
    	}
    }
    bar.foo() // bar对象
    // 也可以理解成
    bar.foo().call(bar) // bar对象
    
    let baz = bar.foo
    baz() // window对象
    // 在全局环境中调用一个函数,函数内部的this指向的是全局变量window
    
  • 通过构造函数设置
    function CreateObj(){
    	console.log(this)
    	this.name = 'obj'
    }
    let obj = new CreateObj(); // obj对象
    // 这里可以理解成
    let obj = {}
    CreateObj.call(obj)
    return obj
    

不难发现后面两种方法其实都是根据第一种方法改编而来,即本质上都是通过函数内置的方法 call、bind、apply 来改变 this 的

this 的设计缺陷以及应对方案

  • 嵌套函数中的 this 不会从外层函数继承
    let myObj = {
    	foo(){
    		function() bar{
    			console.log(this)
    		}
    		bar() // window对象
    	}
    }
    
    这可以通过设置一个临时变量来保存this,然后在bar函数中使用该变量即可,这个方法的本质是转换变量机制,从this机制换到了作用域链的机制
  • 普通函数中的 this 默认指向全局对象 window
    可以通过严格模式解决,在严格模式下,默认一个普通函数的 this 是 undifined
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值