javascript中this的使用

javascript中this指向四个基本场景

  1. 显式绑定,指向绑定对象(call、apply、bind)
  2. 隐式绑定,指向归属属性
  3. new 绑定指向实例
  4. 默认指向全局

一、显式绑定

显式绑定,this的指向比较明确(例如:call、apply、bind等)

var a = 'test '
function foo() {
    console.log('---foo---', this , this.a)
}
const obj = {
    a:'obj'
}
foo.call(obj)  // this => obj对象。 this.a => obj.a
复制代码

问题1「 如果是foo.call(null), this => 指的对象是什么呢? this.a => 展示的值是什么呢? 」

二、 隐式绑定

隐式绑定常常出现在链式调用中,this总是指向调用它的对象

var a = 'test '
function foo() {
    console.log('---foo---', this , this.a)
}
const obj = {
    a:'obj'
    foo:foo,
    foo2:{
      a:'foo2',
      foo:foo
    }
}
obj.foo() 
// ---foo--- {a: "obj", foo2: {…}, foo: ƒ} obj
// this => {a: "obj", foo2: {…}, foo: ƒ}  this.a => obj

obj.foo2.foo() 
// ---foo--- {a: "foo2", foo: ƒ} foo2
// this => {a: "foo2", foo: ƒ} this.a => foo2

const objFoo = obj.foo;
复制代码
  • 上面obj.foo的调用中,foothis指向它的调用对象,即obj对象
  • obj.foo2.foo的调用中,foothis指向的是foo2

问题2「执行objFoo(),返回的结果又是什么呢?」

三、new绑定

new绑定的原理其实和显式绑定有一定关系。看下实现new的四步走就明白了

function bar(){
    console.log('---bar---', this , this.a)
}
const fn = new bar();
// ---bar--- bar {} undefined
// this => fn 即Object.create(bar.prototype)
复制代码

四、默认绑定

当不符合上面的情况的时候,就应该考虑是不是默认绑定全局对象了

问题1

var a = 'test '
function foo() {
    console.log('---foo---', this, this.a)
}
const obj = {
    a: 'obj'
}
foo.call(null)
// ---foo--- Window {window: Window, self: Window, document: document, name: "", location: Location, …} test 
// this => window.  this.a => test
复制代码

虽然foo显式指定指向了null,显式绑定的方法中会做非空判断,如果不存在便指向当前的上下文对象。

问题2

var a = 'test '
  function foo() {
      console.log('---foo---', this , this.a)
  }
  const obj = {
      a:'obj'
      foo:foo,
      foo2:{
        a:'foo2',
        foo:foo
      }
  }
  const objFoo = obj.foo;
  objFoo()
  // ---foo--- Window {window: Window, self: Window, document: document, name: "", location: Location, …} test 
  this => window.  this.a => test
复制代码

为什么这次明明使用了obj.foo还是指向默认绑定呢?

答案:obj.foo指向的是foo的引用地址,此时把这个引用地址赋值给了objFoo,等价于 const objFoo = foo,而此时调用 objFoo() 和直接调用 foo() 是等价的,都使用了默认绑定

参数的形式

var a = 'test '
function foo() {
    console.log('---foo---', this, this.a)
}
function bar(fn) {
    fn()
}
const obj = {
    a:'obj'
    foo:foo
}
bar(foo)
bar(obj.foo)
// foo 还是 obj.foo 传递的都是引用地址
// this都是指向全局上下文对象
复制代码

多层嵌套

var a = 'test '
function foo() {
    console.log('---foo---', this, this.a)
}
function bar() {
    function barch(){
        foo()
        function barchch(){
            foo()
        }
        barchch()
    }
    barch()
}
bar()
// this => window
复制代码

规则小记

this指向可以总结为:有绑定指向绑定对象,有归属指向归属对象,有new指向实例对象,其他指向上下文对象

箭头函数

使用es6中的箭头函数

var a = 'global => a '
 const obj = {
    a:'ojb => a'
     foo: () => {
         console.log('foo:',this.a)
     }, 
    boo:function(){
         console.log('boo:',this.a)
     }
 }
 obj.foo()
 //  this => window  this.a => 'global => a'
 //  箭头函数没有this, 所以foo的this使用的是其父层obj的this,根据上面?规则obj没有显示绑定,也不归属其他对象,非new的实例对象,只能使用默认指向当前上下文对象了
 obj.boo()
 // this => obj  this.a => 'obj => a'
 // 还是?上面的规则对比,boo没有显示绑定,但是是obj链式调用,在执行的属于obl的属性,则boo的this指向了obj,所以this.a = obj.a
复制代码

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享