JavaScript 中判断一个函数的 this 绑定
this
是一个很特别的关键字,被自动定义在所有函数的作用域中。this
实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用(这句话不适用于箭头函数,想了解箭头函数的可以前往ES6—箭头函数)。
要判断一个运行中函数的 this
绑定,就需要找到这个函数的直接调用位置。找到之后就可以应用下面这四条规则来判断 this
的绑定对象:
- 函数是否在
new
中调用(new
绑定)?如果是的话this
绑定的是新创建的对象。
var obj = new fun();
- 函数是否通过
call
、apply
、bind
(显式绑定)或者硬绑定调用?如果是的话,this
绑定的是指定的对象。
fun.apply(obj);
fun.call(obj);
fun.bind(obj)();
- 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this 绑定的是那个上下文对象。
obj.fun();
- 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到
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
的绑定对象传入 call
、apply
或者 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)
,因此强制把 fun1
的 this
绑定到了 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
来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。
- 创建一个新对象;
- 将构造函数的作用域赋给新对象(因此
this
就指向了这个新对象); - 执行构造函数中的代码(为这个新对象添加属性);
- 返回新对象。
如果某个函数的调用位置应用了多条规则,那么将按照:new 绑定 > 显式绑定 > 隐式绑定 > 默认绑定 的优先级来决定哪条规则会生效。
JavaScript 中判断一个函数的 this 绑定相关推荐
- 理解javascript中的回调函数(callback)【转】
在JavaScrip中,function是内置的类对象,也就是说它是一种类型的对象,可以和其它String.Array.Number.Object类的对象一样用于内置对象的管理.因为function实 ...
- 在javascript中使用纯函数处理副作用
在javascript中使用纯函数处理副作用 今天给大家带来一片译文, 详情请点击这里.可能在墙内哦 开始了, 如果你点开这篇文章, 就证明你已经开始涉及函数式编程了, 这距离你知道纯函数的概念不会很 ...
- 理解javascript中的回调函数(callback)
理解javascript中的回调函数(callback) 在JavaScrip中,function是内置的类对象,也就是说它是一种类型的对象,可以和其它String.Array.Number.Obje ...
- JavaScript中的工厂函数vs构造函数vs class
原文链接:JavaScript Factory Functions vs Constructor Functions vs Classes 作者:Eric Elliott 译者:sunny 转载需提前 ...
- 理解与使用Javascript中的回调函数
在Javascript中,函数是第一类对象,这意味着函数可以像对象一样按照第一类管理被使用.既然函数实际上是对象:它们能被"存储"在变量中,能作为函数参数被传递,能在函数中被创建, ...
- 关于javascript中的回调函数
关于javascript中的回调函数 原文地址:http://blog.csdn.net/sicluoyi/article/details/1737969 考虑一个这样的例子: 假如某个项目的底层和高 ...
- java两字符串是否相等_Java与JavaScript中判断两字符串是否相等的区别
JavaScript是一种常用的脚本语言,这也决定了其相对于其他编程语言显得并不是很规范.在JavaScript中判断两字符串是否相等 直接用==,这与C++里的String类一样.而Java里的等号 ...
- 【JavaScript】理解与使用Javascript中的回调函数
在Javascript中,函数是第一类对象,这意味着函数可以像对象一样按照第一类管理被使用.既然函数实际上是对象:它们能被"存储"在变量中,能作为函数参数被传递,能在函数中被创建, ...
- 深入认识javascript中的eval函数
来源:http://wanyij.blog.51cto.com/46570/43794 发现为本文起一个合适的标题还不是那么容易,呵呵,所以在此先说明下本文的两个目的: (1)介绍javascript ...
最新文章
- 22条 API 设计规范,API 一致性设计
- RedisClient 连接redis 提示 ERR Client sent AUTH, but no password is set
- react-native开发经验
- for循环中取出最大最小 累加_从零开始学Python - 第006课:循环结构
- 【CF566#D】 Restructuring Company (并查集---合并区间操作)
- mycat 1.6.5 for mysql 8分表攻略
- 创建一个二维数组,以4行4列左对齐的方式将数组输出
- python库skimage 常值轮廓寻找并标记
- 鼠标onfocus或onblur效果
- 高等数学 下册 第九章 多元函数的概念 笔记
- 安卓手机修改ip软件_为什么苹果手机不用杀毒软件?安卓表示要哭了
- ADC0808确定地址及查询方式示例
- 如何开发微信公众号后台
- 记忆训练: 记数字 (110数字图像编码)
- python爬虫模拟登录之图片验证码
- 天气预报接口使用及示例
- adf输稿器是什么_送稿器是什么
- LostDungeon迷失地牢-壹
- python列表写入txt文件中文乱码,python 字典格式的文本写入文件,中文乱码(Unicode)的问题...
- iPhone上使用网易云音乐的“我的音乐云盘”
热门文章
- 使用Xshell通过堡垒机登录服务器
- 【转】Jenkins怎么启动和停止服务
- 在MySQL中创建cm-hive使用的数据库及账号
- Java核心API -- 9(异常)
- CCNA学习指南十三章
- oracle数据库基础知识总结,oracle知识点总结(一)
- Opencv之Mat操作(重要)
- 操作 mysql 不生成日志_详解MySQL的日志
- linux 占用缓存前10_Ogre的不足与改进(Ogre2.0设计方案)-1.缓存优化
- python中tmp什么意思_python中temp是什么意思-问答-阿里云开发者社区-阿里云