this关键字的一二三

为什么要用this

在一段代码中,在不同的上下文对象中,会重复性使用部分函数,这样就需要给相应函数显示传入一个上下文对象
随着使用模式越来越复杂,显式上下文会让代码越来越复杂混乱,而this提供了一个更加优雅的方式来隐式“传递”一个对象应用。

原理

  • this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window,而当普通函数被当作某个对象的方法调用时,this等于那个对象。注意:匿名函数的执行环境具有全局性,因此其this对象通常指向window
  • this既不指向函数自身也不指向函数的词法作用域
  • this绑定和函数声明的位置没有任何关系,只取决于函数的调用方式
  • 当一个函数被调用时,会创建一个执行上下文,其中包含了调用栈,调用方式和传入参数等信息。this是其中的一个属性

定义解释

  • 调用位置:函数被调用的位置而非声明的位置,其决定了this的绑定
  • 调用栈:为了达到当前执行位置所调用的所有函数

this绑定规则

  • 默认绑定:在非严格模式下,独立函数调用,即该函数是直接使用的,不带有任何修饰的函数引用进行调用的,因此this指向全局对象;在严格模式下,不能将全局对象用于默认绑定,因此this绑定在undefined上。
  • 隐式绑定:在一个对象内部包含一个指向函数的属性,并通过这个属性间接引用函数,从而把this间接(隐性)绑定到这个对象上。
    注意:对象属性只有上一层或者最后一层在调用位置中起作用,如:
function foo() {
	console.log(this.a);
}

var obj2 = {
	a: 42,
	foo : foo
};

var obj1 = {
	a: 2,
	obj2 : obj2 
};

obj1.obj2.foo(); //42

隐性丢失
回调函数丢失this绑定是非常常见的,比如参数传递或函数传入语言内置的函数而不是传入自己声明的函数,由于被隐性赋值,所以导致了this的丢失。

  • 显式绑定:在某个对象上强制调用函数时,this被绑定到指定的对象。
    如:call(), apply()中,你传入了一个原始值来当作this的绑定对象,这个原始值会被转换成它的对象形式。

    1. 硬绑定
      在一个函数内部手动调用了call(), apply()方法,因此强制把函数的this绑定到了将传入的对象,之后无论怎样调用该函数,this总是绑定到该对象。
      注:bind()会把指定的参数设置为this的上下文并调用原始函数。

    2. 第三方库中函数和JS语言和宿主环境中内置新函数,都提供了一个可选参数,通常被称为上下文,确保回调函数使用指定的this

  • new绑定: 包括内置对象函数在内的所有函数都可以使用new来调用,这种函数调用被称为构造函数的调用。它会创造一个全新的对象,新对象会绑定到函数调用的this,若函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。

绑定规则:
  • 函数是否在new中调用,如果是的话this绑定的是新创建的对象

  • 函数是否通过call,apply(显式绑定)或者硬绑定,如果是的话,this绑定的是指定对象

  • 函数是否在某个上下文中调用(隐式绑定),如果是的话,this绑定的是那个上下文对象

  • 如果都不是的话使用默认绑定,在严格模式下绑定的为undefined,非严格模式下为全局对象

  • 若把null或undefined作为this绑定对象传入call,apply或bind,这些值调用的时候会被忽略,使用默认绑定规则

  • 函数在发生了间接引用的时候,使用默认绑定规则,如赋值的情况
    注意:对于默认绑定来说,决定this的绑定对象并不是调用位置是否处于严格模式,而是函数体是否处于严格模式。

  • **软绑定:**给默认绑定指定了一个全局对象或者undefined以外的值,可以实现和硬绑定一样的效果同时也保留隐式绑定或者显式绑定修改this的能力。

this词法

箭头函数斌不是this的四种标准规则,而是根据外层(函数或者全局)作用域来决定this,箭头函数的this同时也无法修改。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章