[JavaScript学习笔记] this

module1.init($div)              // 语法糖
module1.init.call(module1,$div) // 等价

详解

this 永远在函数调用时确定,只是由于语法糖的存在,我们在实际使用时会受到使用场景(浏览器/库)内部this指向的不同的影响。

  1. 由于语法糖的存在,我们在平常调用函数时很少使用.call(this,argument)的形式
  2. 所以如果你自己指定this,就call

例子

let module1 = {
  elment:null,
  init: ($div)=>{
    this.element = $div
    this.bindEvents()
  },
  bindEvents:function(){
    let $div = this.element
    $div.on('click', fucntion(e){
      console.log('div is clicked')
    })
    $div.on('click', 'button', this.onClickButton)
    // 浏览器
    // when user click button
    // fn.call('button', {target:'button',currentTarget:'button'})
    // 所以这里只跟调用时有关
    $div.on('change', 'input', function(e){
      console.log(xxx)
    })
  },
}

总结

一般情况下,

  1. 当函数作为对象方法调用时,this指向调用该方法最靠近的对象成员,因此:
  • 当函数被赋予另一个变量时,函数内部的this的指向会改变,其原因是调用他的对象有变更
  • 可以理解为对象即执行该函数的环境,在顶级作用域下执行函数,this指向全局变量(浏览器中为window)
var a = {
  b: {
    m: function() {
      console.log(this.p);
    },
    p: 'Hello'
  }
};

var hello = a.b.m;
hello() // undefined

var hello = a.b
hello()  // Hello
  1. 构造函数中的this默认绑定为被创建的新对象
    原理:
  1. 创建一个空对象,作为将要返回的对象实例
  2. 将这个空对象的原型指向prototype属性
  3. 将这个空对象的值赋给函数内部的this关键字
  4. 开始执行构造函数内部代码

参考前面的方法,总结为

var a = function(){
  this.balaba = 123;
}
var b 
b = {}
Object.setPrototypeOf(b, a)
a.call(b)
  1. 当函数被当做事件处理函数时,this指向触发事件的函数

  2. 内联事件处理函数的this指向监听器所在的DOM元素

  3. 当函数作为嵌套函数调用时, this指向全局对象(非严格模式下)或者undefined(严格模式)而不是其外包函数的上下文

var o = {
  f1: function () {
    console.log(this);
    var f2 = function () {
      console.log(this);
    }();
  }
}
o.f1()  
// Object 
// Window
    
// 上面等价于下面
var temp = function () {
  console.log(this);
};

var o = {
  f1: function () {
    console.log(this);
    var f2 = temp();
  }
}

// 解决办法
var o = {
  f1: function() {
    console.log(this);
    var that = this;
    var f2 = function() {
      console.log(that);
    }();
  }
}

o.f1() 
// Object
// Object

怎么看this

  1. console.log()
  2. 看浏览器/jQuery/DOM 源代码
  3. 看API 文档

bind()

bind() 会返回一个新的函数,该函数有指定的this,且不被call() / apply()

bind的使用例子

根据前面总结的第3条和第5,如果需要在一个函数中的事件监听设置this指向外包函数的this,可以用bind绑定this的指向,否则,监听事件触发时this会指向触发事件的元素。

var box = document.getElementById('box');
box.x = 'box'
function outFunc() {
  this.x = 'outFunc';//给全局对象window.x赋值(相当于赋值全局变量)
  box.addEventListener('click', func.bind(this), false); // bind(this) 的this 指向outFunc() 中的this,又等于指向window
}
function func() {
  console.log(this.x); //输出outFunc 使用bind设置this的值
}

参考:
JS中的this简单描述
addEventListener中事件函数的this指向
MDN - JavaScript - this

你可能感兴趣的:([JavaScript学习笔记] this)