美文网首页
理解 this

理解 this

作者: lyp82nkl | 来源:发表于2019-06-27 02:18 被阅读0次

函数调用

通常有三种函数执行方式
func(a, b) 
obj.child.fn(a, b)
func.call(context, a, b) 

一般来说前面两种方式大家用的比较多,但是其实第三种才是函数调用的本质。

fn.call(context, a, b)

其他两种可以等价地变为 call 形式:

fn(a, b)
// 等价于
fn.call(undefind, a, b)

obj.child.fn(a, b)
// 等价于
obj.child.fn.call(obj.child, a, b)
  • 严格模式,fn的this就是call第一个参数undefined
  • 非严格模式,call 传递的第一个参数如果是 undefined 或者 null, 那 this 会自动替换为 Window 对象
    函数执行的本质:函数的执行,都可以等价看做为fn.call的调用
var obj = {
   fn: function(a, b){
       console.log(this)
   },
   child: {
       fn2: function(){
           console.log(this)
       }
   }
}

obj.fn(2, 3)
// 等价
obj.fn.call(obj, 2, 3)  // fn的this 为 obj

obj.child.fn2()
// 等价
obj.child.fn2.call(obj.child) // fn2的this 为 obj.child

this 就是你 call 一个函数时,传入的第一个参数。

例题1:

button.onclick = function f1(){
console.log(this)   // 触发事件的元素。 button
}`
  • this 是什么?去看 onclick 的源码呀 -> 做不到
  • MDN 的开发者知道 onclick 的源码
  • MDN 的开发者写了文档
  • 看文档

例题2:

button.addEventListener('click', function(){
console.log(this) //该元素的引用 button
})

https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener

  • 去看 addEventListener 的源码呀 -> 做不到
  • MDN 的开发者知道 addEventListener 的源码
  • MDN 的开发者写了文档
  • 看文档

例题3:

$('ul').on('click', 'li', function(){     //  li  是  selector 
console.log(this) //this 则代表了与 selector 相匹配的元素
// 这里的 this 是某个 li  元素
})
})

当jQuery的调用处理程序时,this关键字指向的是当前正在执行事件的元素。对于直接事件而言,this 代表绑定事件的元素。对于代理事件而言,this 则代表了与 selector 相匹配的元素。若要使用 jQuery 的相关方法,可以根据当前元素创建一个 jQuery 对象,即使用 $(this)。

  • 去看 on 的源码呀 -> 做不到
  • jQuery 的开发者知道 onclick 的源码,f1.call(???)
  • jQuery 的开发者写了文档
  • 看文档

特殊情况:自己抢先的调用 它,自己去 call.
button.onclick.call({name:'xxx'}) //this 是 xxx
只要没看见 call ,就不知道 this 什么。因为 this 是 call 的第一个参数

例题4:

function x(){
  return object = {
    name: 'object',
options: null,
    f1(x){
      this,options = x  //所以这个 this 是外面的 x ,外面的 x 就是object 
this.f2()  //这个 this 是 f1 call 的第一个参数 ,所以这个this 就是  object
   },
    f2(){
     this.options.f2.call(this) //这个 this 也是 object
// 这个 this.options.f2 就是 x.f2 
// x.f2 也就是 options.f2
// 也就是调用下面的 options 的 f2 函数, 
//调这个函数传了一个 this,这个this 就是  object
    }
  }
}

var options = {
  name: 'options',
  f1(){},
  f2(){
    console.log(this)  //this 是啥?
  }
}

var x = X()
x.f1(options) //call 的第一个参数是 x

问:options 中 f2 的 this 是啥?
答:object

this.f2() 中的 this 是 x.f1(options)call 的第一个参数 ,call的第一个参数是 x.
,所以this.f2() 中this 是外面的 x , 外面的 x 就是 object 。this.f2() 中this 就是 object。
f2(){ this.options.f2.call(this) } 这个 this 也是 object。
this.options =x , 这个 this.options.f2 就是 x.f2
x.f2 也就是 options.f2,因为 x.f1(options)传的参数是 options。也就是调用 options 的 f2 函数,调这个函数传了一个 this,这个this 就是 object

例题5:

var a = {
  p: 'Hello',
  b: {
    m: function() {
      console.log(this.p);
    }
  }
};

a.b.m()

上面的a.b.m()执行后里面的this.p是什么?

答:因为前面说了,this就是函数call的第一个参数,上面的a.b.m()写成call的形式就是a.b.m.call()也就是(a.b).m.call(a.b),所以this是a.b,也可以而b里面没有p所以是undefined

例题6:

var obj = {
    fn(){
        return function(){
            console.log(this)
        }
    },
    f1(){
        var f =this.fn()
        f()
    }
}
obj.f1()

上面的代码因为是普通函数里的this,所以与它调用的时候有关,因为它是return的所以实际上就是f()的时候调用的,转成f.call(undefined),this就是window

例题7:

var obj = {
    fn(){
        return ()=>{
            console.log(this)
        }
    },
    f1(){
        var f =this.fn()
        f()
    }
}
obj.f1()

上面的代码因为this是在一个箭头函数里,所以直接忽略,它的this就是它的外层函数fn里的this,而fn是普通函数,所以它的this就是它在调用的时候call的第一个参数,也就是this.fn.call(this)这里的this就是f1这个函数被调用时的this,也就是obj.f1.call(obj)所以this是obj

例题8:

window.xx = 'hhhhhhhhhh'

let c = {
  xx:'name',
  find(){
    console.log(this.xx)
  },
  throttle(fn){
    var timer = null
    return ()=>{
      clearTimeout(timer)
      timer = setTimeout(()=>{
        fn()
      },1000)
    }
  },

  bindEvent(){
    var f = this.throttle(this.find)
    f()
  }
}
c.bindEvent()

上面的find里的this是什么?
答:是window,因为函数里的this只与函数被调用时有关,如果不是箭头函数,那这个函数调用的时候只需要转成call的形式就能知道this了,上面的find函数也就是fn,fn被调用的时候是fn(),因为find本身不是箭头函数,所以可以转成fn.call(undefined),所以this是window

例题9:

对于class中的this,如果是被直接call(undefined)那么this就是undefined

class Animal { 
  speak() {
    return this;
  }
  static eat() {
    return this;
  }
}
let obj = new Animal();
let speak = obj.speak;
speak(); // undefined

上面的speak()转成call的形式就是speak.call(undefined),因为class中所有的函数、方法、构造函数、getters或setters都在严格模式下执行。因此如果我们没有指定this的值,也就是call的时候传入的是undefined那么this就是undefined

有关 this 的理解,方老师的这篇 文章 很完美

相关文章

  • 理解!理解!!理解!!!

    1、如何理解MVC设计模式 MVC是一种架构模式,M表示MOdel,V表示视图View,C表示控制器Control...

  • 理解“理解”

    教育不是灌输而是揭示 教育就是向智者揭示智慧,对愚者掩盖无知。——安布罗斯 比尔斯 我们的课堂教学要做的是设计表现...

  • 理解理解,再理解

    【今日悦读】 1214-潇潇 书名:财富自由之路 作者:李笑来 篇目:10~12节 收获: 1,人生三大坑 莫名其...

  • 理解不被理解

    一个人的坐在电脑前发呆,不知道搞什么,闭上眼睛,感觉自己很孤独。这种是内心的那种,很不是滋味,不知道什么时候自己才...

  • 理解你的理解理顺理解

    理解你的理解理顺你的理解 生活中因为缺乏准确具体到位的沟通和具体的实施方向和可落地的方式,因为信息传达...

  • 理解不理解

    对于更多人而言,或许他们更看重的是对与错,是与非。这种执念而且经常让一些人变了味,甚至格格不入。 而对于个人而言,...

  • 理解不曾理解的

    上学时从来没把容貌当成大事儿,只是希望脸上的痘痘能少点,至于什么皮肤白、毛孔粗大、黑眼圈、肤色暗淡、脸型、眉形、眼...

  • 理解与被理解

    凡事都设身处地为别人着想,自己不愿做的事情也不强加给别人,理解的核心在于不自我。

  • 理解什么是理解

    《理解什么是理解》-花花 每个人都渴望被理解,希望被理解,不被理解是一件很痛苦的事情。 小朋友不理解妈妈为对自己反...

  • 理解与被理解

    问同事最喜欢的两个字的词什么,他们说不知道,而与我从小至大最喜欢的就是时间两字,不管是英文还是中文,莫名的喜欢...

网友评论

      本文标题:理解 this

      本文链接:https://www.haomeiwen.com/subject/bwpkcctx.html