[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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 单例模式 适用场景:可能会在场景中使用到对象,但只有一个实例,加载时并不主动创建,需要时才创建 最常见的单例模式,...
    Obeing阅读 6,350评论 1 10
  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 12,375评论 2 17
  • 转载请著名出处 GitHub-TYRMars 文章Github地址 JavaScript基础知识剖析 01 01-...
    TYRMars阅读 3,610评论 0 7
  • 原文链接 Haskell和scala都支持函数的柯里化,JavaScript函数的柯里化还与JavaScript的...
    dreamapple阅读 7,284评论 0 24
  • 1. this之谜 在JavaScript中,this是当前执行函数的上下文。因为JavaScript有4种不同的...
    百里少龙阅读 4,613评论 0 3