this 是一个很特别的关键字,被自动定义在所有函数的作用域中。this 实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用(这句话不适用于箭头函数,想了解箭头函数的可以前往ES6—箭头函数)。
要判断一个运行中函数的 this 绑定,就需要找到这个函数的直接调用位置。找到之后就可以应用下面这四条规则来判断 this 的绑定对象:

  1. 函数是否在 new 中调用(new 绑定)?如果是的话 this 绑定的是新创建的对象。
var obj = new fun();
  1. 函数是否通过 callapplybind(显式绑定)或者硬绑定调用?如果是的话,this 绑定的是指定的对象。
fun.apply(obj);
fun.call(obj);
fun.bind(obj)();
  1. 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this 绑定的是那个上下文对象。
obj.fun();
  1. 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到 undefined,否则绑定到全局对象。
fun();

上面讲述的四种情况分别 this 的四种绑定规则:默认绑定、隐式绑定、显式绑定、new绑定

默认绑定:是没有应用其他绑定规则时使用的规则,通常是独立函数调用。这时 this 在非严格模式下指向的是全局对象 window,在严格模式下指向 undefined

function fun(){console.log(this === window);
}fun(); //true
function fun(){'use strict';console.log(this === undefined);
}fun(); //true

注意:对于默认绑定来说,决定 this 绑定对象的并不是调用位置是否处于严格模式,而是函数体是否处于严格模式。如果函数体处于严格模式,this 会被绑定到 undefined,否则 this 会被绑定到全局对象。

function fun(){console.log(this === window);
}(function(){'use strict';fun();
})();           //true

隐式绑定:函数的调用是在某个对象上触发的,即调用位置上存在上下文对象。这时 this 会指向这个上下文对象。

var obj = {fun : function(){console.log(this === obj);}
};obj.fun();    //true

对象属性引用链中只有最顶层或者说最后一层会影响调用位置。

function fun(){console.log(this === obj1);
}
var obj1 = {fun : fun
}
var obj2 = {obj1 : obj1
}
var obj3 = {obj2 : obj2
}obj3.obj2.obj1.fun();      //true

显式绑定:使用call()apply()bind() 把指定对象绑定到 this,这种方式称为显式绑定。想了解这三个方法的可以前往apply()、call()与bind()的用法与区别。

var obj = {};
function fun(){console.log(this === obj);
}fun();     //false
fun.apply(obj);     //true
fun.call(obj);      //true
fun.bind(obj)();        //true

如果你传入了一个原始值(字符串类型、布尔类型或者数字类型)来当作 this 的绑定对象,这个原始值会被转换成它的对象形式(也就是 new String(..)new Boolean(..) 或者new Number(..))。这通常被称为“装箱”。

var num = 123;
function fun(){console.log(this instanceof Number);console.log(this === num);console.log(typeof this);
}fun.apply(num);        //true  false   object

如果你把 null 或者 undefined 作为 this 的绑定对象传入 callapply 或者 bind,这些值在调用时会被忽略,实际应用的是默认绑定规则。也就是在非严格模式下 this 会绑定全局对象,在严格模式下指向 undefined

function fun(){console.log(this === window);
}fun.apply(null);       //true
fun.apply(undefined);       //true

硬绑定是显式绑定的一个变种,是一种显式的强制绑定。

var obj1 = {};
var obj2 = {};
function fun1(){console.log(this === obj1);
}
function fun2(){fun1.apply(obj1);
}fun2.apply(obj2);      //true

这里我们创建了函数 fun2(),并在它的内部手动调用了 fun1.apply(obj1),因此强制把 fun1this 绑定到了 obj1。无论之后如何调用函数 fun2,它总会手动在 obj1 上调用 fun1。这种绑定是一种显式的强制绑定,因此我们称之为硬绑定

new绑定:使用 new 来调用函数,会将 this 绑定到新创建的对象上面。

function fun(){this.age = 23;
}
var obj = new fun();console.log(window.age);       //undefined
console.log(obj.age);       //23

使用 new 来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。

  1. 创建一个新对象;
  2. 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
  3. 执行构造函数中的代码(为这个新对象添加属性);
  4. 返回新对象。

如果某个函数的调用位置应用了多条规则,那么将按照:new 绑定 > 显式绑定 > 隐式绑定 > 默认绑定 的优先级来决定哪条规则会生效。

JavaScript 中判断一个函数的 this 绑定相关推荐

  1. 理解javascript中的回调函数(callback)【转】

    在JavaScrip中,function是内置的类对象,也就是说它是一种类型的对象,可以和其它String.Array.Number.Object类的对象一样用于内置对象的管理.因为function实 ...

  2. 在javascript中使用纯函数处理副作用

    在javascript中使用纯函数处理副作用 今天给大家带来一片译文, 详情请点击这里.可能在墙内哦 开始了, 如果你点开这篇文章, 就证明你已经开始涉及函数式编程了, 这距离你知道纯函数的概念不会很 ...

  3. 理解javascript中的回调函数(callback)

    理解javascript中的回调函数(callback) 在JavaScrip中,function是内置的类对象,也就是说它是一种类型的对象,可以和其它String.Array.Number.Obje ...

  4. JavaScript中的工厂函数vs构造函数vs class

    原文链接:JavaScript Factory Functions vs Constructor Functions vs Classes 作者:Eric Elliott 译者:sunny 转载需提前 ...

  5. 理解与使用Javascript中的回调函数

    在Javascript中,函数是第一类对象,这意味着函数可以像对象一样按照第一类管理被使用.既然函数实际上是对象:它们能被"存储"在变量中,能作为函数参数被传递,能在函数中被创建, ...

  6. 关于javascript中的回调函数

    关于javascript中的回调函数 原文地址:http://blog.csdn.net/sicluoyi/article/details/1737969 考虑一个这样的例子: 假如某个项目的底层和高 ...

  7. java两字符串是否相等_Java与JavaScript中判断两字符串是否相等的区别

    JavaScript是一种常用的脚本语言,这也决定了其相对于其他编程语言显得并不是很规范.在JavaScript中判断两字符串是否相等 直接用==,这与C++里的String类一样.而Java里的等号 ...

  8. 【JavaScript】理解与使用Javascript中的回调函数

    在Javascript中,函数是第一类对象,这意味着函数可以像对象一样按照第一类管理被使用.既然函数实际上是对象:它们能被"存储"在变量中,能作为函数参数被传递,能在函数中被创建, ...

  9. 深入认识javascript中的eval函数

    来源:http://wanyij.blog.51cto.com/46570/43794 发现为本文起一个合适的标题还不是那么容易,呵呵,所以在此先说明下本文的两个目的: (1)介绍javascript ...

最新文章

  1. 22条 API 设计规范,API 一致性设计
  2. RedisClient 连接redis 提示 ERR Client sent AUTH, but no password is set
  3. react-native开发经验
  4. for循环中取出最大最小 累加_从零开始学Python - 第006课:循环结构
  5. 【CF566#D】 Restructuring Company (并查集---合并区间操作)
  6. mycat 1.6.5 for mysql 8分表攻略
  7. 创建一个二维数组,以4行4列左对齐的方式将数组输出
  8. python库skimage 常值轮廓寻找并标记
  9. 鼠标onfocus或onblur效果
  10. 高等数学 下册 第九章 多元函数的概念 笔记
  11. 安卓手机修改ip软件_为什么苹果手机不用杀毒软件?安卓表示要哭了
  12. ADC0808确定地址及查询方式示例
  13. 如何开发微信公众号后台
  14. 记忆训练: 记数字 (110数字图像编码)
  15. python爬虫模拟登录之图片验证码
  16. 天气预报接口使用及示例
  17. adf输稿器是什么_送稿器是什么
  18. LostDungeon迷失地牢-壹
  19. python列表写入txt文件中文乱码,python 字典格式的文本写入文件,中文乱码(Unicode)的问题...
  20. iPhone上使用网易云音乐的“我的音乐云盘”

热门文章

  1. 使用Xshell通过堡垒机登录服务器
  2. 【转】Jenkins怎么启动和停止服务
  3. 在MySQL中创建cm-hive使用的数据库及账号
  4. Java核心API -- 9(异常)
  5. CCNA学习指南十三章
  6. oracle数据库基础知识总结,oracle知识点总结(一)
  7. Opencv之Mat操作(重要)
  8. 操作 mysql 不生成日志_详解MySQL的日志
  9. linux 占用缓存前10_Ogre的不足与改进(Ogre2.0设计方案)-1.缓存优化
  10. python中tmp什么意思_python中temp是什么意思-问答-阿里云开发者社区-阿里云