js中改变this指向的call、apply、bind 方法使用
前言:
由于js 中this的指向受函数运行环境的影响,指向经常改变,使得开发变得困难和模糊,所以在封装sdk,写一些复杂函数的时候经常会用到this 指向绑定,以避免出现不必要的问题,call、apply、bind基本都能实现这一功能,现对这三种方法使用总结一下:
1、function.prototype.call()
call 方法可以指定this 的指向(即函数执行时所在的的作用域),然后再指定的作用域中,执行函数
call 方法的参数,应该是对象obj,如果参数为空或null,undefind,则默认传参全局对象
var obj = {};
var f = function(){
return this;
};
console.log(f() === window); // this 指向window
console.log(f.call(obj) === obj) //改变this 指向 obj
如果call 传参不是以上类型,则转化成对应的包装对象,然后传入方法。例如,5 转成number 实例,绑定f 内部 this
var f = function () {
return this;
}; f.call(5)
// Number {[[PrimitiveValue]]: 5}
call 可以接受多个参数,第一个参数是this 指向的对象,之后的是函数回调所需的入参
function add(a, b) {
return a + b;
} add.call(this, 1, 2) //
call
方法的一个应用是调用对象的原生方法。
var obj = {};
obj.hasOwnProperty('toString') // false // 覆盖掉继承的 hasOwnProperty 方法
obj.hasOwnProperty = function () {
return true;
};
obj.hasOwnProperty('toString') // true Object.prototype.hasOwnProperty.call(obj, 'toString') // false
上面代码中hasOwnProperty 是 obj 继承来的方法,用来判断对象是否包含自身特点(非继承)属性,但是hasOwnProperty 并不是保留字,如果被对象覆盖,会造成结果错误。
call
方法可以解决这个问题,它将hasOwnProperty
方法的原始定义放到obj
对象上执行,这样无论obj
上有没有同名方法,都不会影响结果。
hasOwnProperty 相关应用:https://www.cnblogs.com/weiqinl/p/8683207.html
2、Function.prototype.apply()
apply 和call 作用类似,也是改变this 指向,然后调用该函数,唯一区别是apply 接收数组作为函数执行时的参数
func.apply(thisValue, [arg1, arg2, ...])
apply
方法的第一个参数也是this
所要指向的那个对象,如果设为null
或undefined
,则等同于指定全局对象。
第二个参数则是一个数组,该数组的所有成员依次作为参数,传入原函数。
原函数的参数,在call
方法中必须一个个添加,但是在apply
方法中,必须以数组形式添加。
function f(x, y){
console.log(x + y);
} f.call(null, 1, 1) //
f.apply(null, [1, 1]) //
利用这一特性,可以实现很多小功能
比如,输出数组的最大值
var a = [24,30,2,33,1]
Math.max.apply(null,a) //
将数组中的空值,转化成undefined,主要应用在数组遍历中,因为数组foreach 遍历会跳过空值,而不会跳过undefined
var a = ['a',,'b'];
Array.apply(null,a) //['a',undefind,'b']
将类似于数组的对象转化成数组
另外,利用数组对象的slice
方法,可以将一个类似数组的对象(比如arguments
对象)转为真正的数组。
Array.prototype.slice.apply({0: 1, length: 1}) // [1]
Array.prototype.slice.apply({0: 1}) // []
Array.prototype.slice.apply({0: 1, length: 2}) // [1, undefined]
Array.prototype.slice.apply({length: 1}) // [undefined]
上面代码的apply
方法的参数都是对象,但是返回结果都是数组,这就起到了将对象转成数组的目的。
从上面代码可以看到,这个方法起作用的前提是,被处理的对象必须有length
属性,以及相对应的数字键。
3.Function.prototype.bind()
bind 用于将函数体内的this绑定到某个对象,然后返回一个新函数
var d = new Date();
d.getTime() // var print = d.getTime;
print() // Uncaught TypeError: this is not a Date object.
报错是因为,d.getTime 赋值给 print 后,getTime 内部的this 指向方式变化,已经不再指向date 对象实例了
解决方法
var print = d.getTime.bind(d);
print() //
bind 接收的参数就是所要绑定的对象
ar counter = {
count: 0,
inc: function () {
this.count++;
}
}; var func = counter.inc.bind(counter);
func();
counter.count //
绑定到其他对象
var counter = {
count: 0,
inc: function () {
this.count++;
}
}; var obj = {
count: 100
};
var func = counter.inc.bind(obj);
func();
obj.count //
bind 还可以接收更多的参数,将这些参数绑定到原函数的参数
var add = function (x, y) {
return x * this.m + y * this.n;
} var obj = {
m: 2,
n: 2
}; var newAdd = add.bind(obj, 5);
newAdd(5) //
上面代码中,bind
方法除了绑定this
对象,还将add
函数的第一个参数x
绑定成5
,然后返回一个新函数newAdd
,这个函数只要再接受一个参数y
就能运行了。
总结:
1. call 、 apply 、bind 均能改变this 指向
2. apply 每次执行产生一个新函数,call、apply 不会
3. call ,bind 接收多个参数绑定到函数,参数单一传入,apply 接收方式为数组
更多详细资料:
http://javascript.ruanyifeng.com/oop/this.html#toc7
js中改变this指向的call、apply、bind 方法使用的更多相关文章
- js中修改this指向的方法(call,apply,bind)
前言:call.apply和bind都是为了改变某个函数运行时的this指向的,对于前端人员来说,关于this的掌握程度,直接决定了前端水平的高低.下面我们就来简单浅显易懂的来看一下es5中常用的三种 ...
- 彻底理解js中this的指向,不必硬背。
首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...
- 了解学习JS中this的指向
[转] 首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问 ...
- 彻底理解js中this的指向
首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...
- 【转发】彻底理解 JS 中 this 的指向
为什么要学习this?如果你学过函数式编程,面向对象编程,那你肯定知道干什么用的,如果你没有学过,那么暂时可以不用看这篇文章,当然如果你有兴趣也可以看看,毕竟这是js中必须要掌握的东西. 例子1: f ...
- JS中的this 指向问题
我发现在对JS的学习中有很多朋友对this的指向问题还是有很大的误区或者说只是大致了解,但是一旦遇到复杂的情况就会因为this指向问题而引发各种bug. 对于之前学习过c或者是Java的朋友来说可能这 ...
- 【转】彻底理解js中this的指向,不必硬背。
首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...
- 如何简单理解js中this的指向
前序 每个人学js都会被this指向这个东西搞得很蒙,那就是this的指向问题.首先,我们要明白 this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上thi ...
- 彻底理解js中this的指向,不必硬背
来自 https://blog.csdn.net/u011088260/article/details/79230661 首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行 ...
随机推荐
- webform 使用log4net配置
效果: web.config配置 <configuration> <configSections> <!--log4net日志记录--> <section n ...
- Java 开源博客 Solo 1.6.0 发布 - 新后台
简介 Solo 是一款一个命令就能搭建好的 Java 开源博客系统,并内置了 15+ 套精心制作的皮肤.除此之外,Solo 还有着非常活跃的社区,文章分享到社区后可以让很多人看到,产生丰富的交流互动. ...
- LintCode2016年8月22日算法比赛----将数组重新排序以构造最小值
将数组重新排序以构造最小值 题目描述 给定一个整数数组,请将其重新排序,以构造最小值. 样例 给定[3,32,321],通过将数组重新排序,可构造6个可能性的数字: 3+32+321=332321 3 ...
- 在datagridview中添加button按钮
.Net的DataGridView控件中,提供了一种列的类型,叫 DataGridViewButtonColumn ,这种列类型是展示为一个 按钮,可以给button赋予相应的text,并且,此but ...
- configparser logging collections 模块
configparser 模块: 这是一个写入的模块就是把你的信息给写入的模块 #这是一个把信息写入example文件内import configparserconfig = configparser ...
- iOS设计模式 - 装饰
iOS设计模式 - 装饰 原理图 说明 1. cocoa框架本身实现了装饰模式(category的方式实现了装饰模式) 2. 装饰模式指的是动态的给一个对象添加一些额外的职责,相对于继承子类来说,装饰 ...
- Python实例---利用正则实现计算器[参考版]
利用正则进行运算规则的计算 版本一: # import re # # ss = '1 - 2 * ((60 - 30 + (-40/5) * (9 - 2 * 5 / 3 + 7 / 3 * 99 / ...
- Java学习---JDK的安装和配置
控制面板\系统和安全\系统 CLASSPATH %JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar; JAVA_HOME C:\Program Files ...
- yaml 入手
一.变量 YAML使用冒号加缩进的方式代表层级(属性)关系,使用短横杠(-)代表数组元素. YAML中允许表示三种格式,分别是常量值,对象和数组 #即表示url属性值: url: http://www ...
- MVC 入门-MvcMovie
入门教程 ASP.NET MVC 5 入门 https://docs.microsoft.com/zh-cn/aspnet/mvc/overview/getting-started/introduct ...