Visual LabINTERACTIVE LEARNING
JavaScript 内核第 1 / 7 章

this 绑定规则

从默认、隐式、显式到 new 绑定,按调用位置建立判断顺序。

this原型异步
进阶预计 65 分钟查看源文 ↗

this绑定规则(四种方式)

默认绑定,直接调用

提示

  • 严格模式下,this默认绑定undefined
  • 非严格模式下,this默认绑定globalThis 浏览器是 window
  • 类中 默认开启严格模式 默认绑定和上层作用域的this不是一回事,直接调用函数时,没有显式绑定this的情况下,使用的this

隐式绑定

提示

被一个对象执行,调用,注意是被当作对象的一个方法来调用

 const obj = { 
     name:'obj',
     foo(){
          console.log(this.name)
       }
 }
 obj.foo() // this指向obj
 function foo(){ 
   console.log(this.length)
 }
 const arr = [foo,1,2]
 arr[0]() // 这也会把this绑定到arr 即结果是 3
 

显示绑定

提示

bind/apply/call方式调用

  • bind 函数只绑定,不执行,参数在绑定的时候可以传入,在调用的时候不能覆盖,会在后面添加新的参数
  • call调用即执行,参数是单独传入
  • apply调用即执行,参数通过数组传入
//三者调用
const obj ={ name:'this'}
var func = function(arg1, arg2) {};
// 直接调用了
func.call(obj, arg1, arg2);
func.apply(obj, [arg1, arg2]);

//返回一个函数
nfn = func.bind(obj,arg1)
nfn(arg2)

New 绑定

this - JavaScript | MDN

super调用会比较特殊

当一个函数以 super.method() 的形式被调用时,method 函数内的 thissuper.method() 调用周围的 this 值相同,通常不等于 super 所指向的对象。这是因为 super.method 不是像上面的对象成员访问——它是一种特殊的语法,有不同的绑定规则。有关示例,请参见 super 参考

🐵 提示

通过new 内部创建一个新的对象,绑定到this

绑定优先级

new绑定 > 显式绑定 > 隐式绑定 > 默认绑定

bind优先级高于apply/call

function Foo(){    
  console.log('this', this)
}
const objA ={ 
  name:'objA',
}
const objB ={ 
  name:'objB',
}

const fn = Foo.bind(objA)
fn.call(objB) // this { name: 'objA' }
new fn() // this Foo {}

const objC ={ 
  name:'objC',
  foo:fn
}

new objC.foo() // this Foo {}
特殊情况

非严格模式下,apply/call/bind绑定null/undefied时,这个绑定会被忽略,使用默认绑定(并不是降级,不会使用隐式绑定

非严格模式下,基本类型会被转换成包装类型(对象),null和undefined会使用默认绑定

严格模式下,会直接使用绑定的类型,默认绑定是undefined

箭头函数
 // 函数表达式
 const fn1 = function(){}
 // 用来改写 简化函数表达式
 const fn2 = ()=> {}
 const newArr = [1,2,3]
 //1. 只有一个参数,可以把小括号省略
newArr.forEach(item=>{
  console.log('item', item)
})
//2. 函数体只有一行代码,大括号可以省略(非return 语句)
newArr.forEach(item=>console.log('item', item))

//3. 如果函数体只有一行代码且是返回值,可以把return 也省略,默认返回
newArr.filter(item=>item>3)

//4. 如果默认返回是对象,那么需要给对象加上小括号
newArr.map(item=>({ num:item }))

规则:

  1. 箭头函数里没有绑定自己的this,如果在箭头函数使用了this,调用的时候会到上层作用域中查找this,就像普通变量查找一样的规则
  2. 没有arguments,可使用剩余参数来实现不定参数传递
 const obj = {
  name:'obj',
  foo: function() {
    const bar = ()=>{
      console.log('this', this)
    }
    return bar
  }
}
// 这里bar的this是上层作用域foo的this,如果改变foo的this指向,bar中的this也会跟着改变

const obj = {
  name:'obj',
  foo: ()=> {
    const bar = ()=>{
      console.log('this', this)
    }
    return bar
  }
}
//如果把foo也改成了箭头函数,那么foo和bar的this指向都要继续往外查找,是全局作用域的this
// 注意!! 对象不是代码块,没有产生作用域!!

函数的调用方式:这里也是直接调用!!! 因为obj.foo()函数执行后,返回值是一个新的函数的地址!!!
obj.foo()() 
也是通过小括号直接调用了

对象不是代码块,没有产生作用域!!