js中的this与call/apply/bind的关系
this指向总结:
1.在浏览器中,在全局范围内this指向window对象;
2.在函数中,this永远指向最后调用他的那个对象;
3.构造函数中,this指向new出来的那个新对象;
4.call/apply/bind中的this被强绑定在指定的那个对象上;
5.箭头函数中this比较特殊,箭头函数this为父作用域的this,不是调用时的this,要知道前四种方式,都是调用的时候确定,也就是动态的,而箭头函数的this是静态的,声明的时候就确定了下来;
6.apply,call,bind都是js给函数内置的一些api,调用他们可以为函数指定this的执行,同时也可以传参。
apply和call
在js中,call和apply都是为了改变某个函数运行时的上下文(context)而存在,换句话说,就是为了改变函数体内部this的指向。
js的特点就是,函数存在定义时上下文和运行时上下文以及上下文时可以改变的这样一个概念:
function fruits(){}
fruits.prototype = {
color:"red",
say:function(){
console.log("My color is" + this.color);
}
}
var apple = new fruits;
apple.say(); //my color is red
但是如果我们有一个对象banana={color:"yrllow"},我们不想对它重新定义say方法,那我们可以通过call或apply的say方法:
banana = {
color:"yellow"
}
apple.say.call(banana); //my color is yellow
apple.say.apply(banana); //my color is yellow
所以可以看出call和apply是为了动态改变this而出现的,当一个obj没有某个方法(本例子中banana没有say方法,但是其他的有(本例子中apple有say方法),我们可以借助call或apply用其它对象的方法来操作。
apply,call的用法
call()方法的作用和apply()方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。
apply的语法:
func.apply(thisArg,[argsArray])
参数讲解:
thisArg
:必选的,在func函数运行时指定使用的this值。在非严格模式下,该参数指定为Null
或undefined
时会自动替换为全局对象。argsArray
:可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给fnc函数。如果该参数的值为null或者undefined,则表示不需要传入任何参数。
apply,call的区别
对于apply,call二者而言,作用完全一样,只是接受参数的方式不太一样。例如,有一个函数的定义如下:
var func = function(arg1,arg2){
}
就可以通过如下方式来调用:
func.call(this,arg1,arg2);
func.apply(this,[atg1,arg2])
其中this就是想指定的上下文,可以是任何一个js对象,call需要把参数按顺序传递进去,而apply则是把参数放在数组里。
总结区别:
call()方法的作用和apply()方法类似,区别就是call()方法接受的参数列表,而apply()方法接受的是一个参数数组。
JavaScript中,某个函数的参数数量是不固定的,因此要说使用条件:
- 当参数是明确知道数量的时候用call.
- 而不确定时用apply,然后把参数push进数组传递进去。
bind
bind和call/apply有一个很重要的区别,一个函数被call/apply的时候,会立即执行函数,但是bind会创建一个新函数,不会立即执行。
var obj = {
x:81,
};
var foo = {
getX:function(){
return this.x;
}
}
console.log(foo.getX.bind(obj)()); //81
console.log(foo.getX.call(obj)); //81
console.log(foo.getX.apply(obj)); //81
三个输出的都是81,但是注意使用bind()方法的,他后面多了括号。也就是说,区别时,当希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用了bind()方法。而apply/call则会立即执行函数。
当这个新函数被调用的时候,bind()的第一个参数将作为它运行时的this,传入bind()方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。
如上,bind另一个重要的区别是,后面传入的这个参数列表可以分多次传入,call和apply则必须一次性传入所有参数。
示例:
var arr = [1,10,5,8,12]
var max = Math.max.bind(null,arr[0],arr[1],arr[2],arr[3]);
console.log(max(arr[4])); //12,分两次传参
bind方法可以分多次传参,最后函数运行时会把所有参数连接起来一起放入函数运行。
应用场景
数组之间追加
var array1 = [12,'foo',{name:"Joe"},-2458];
var array2 = ["Doe",555,100];
Array.prototype.push.apply(array1,array2);
/* array1 值为 [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */
获取数组中的最大值和最小值
var numbers = [5,458,120,-215];
var maxInNumbers = Math.max.apply(Math,numbers),
maxInNumbers = Math.max.call(Math,5,458,120,-215); //458
总结:
1.call,apply,bind都能改变函数的内部this指向。
2.call和apply在改变函数this指向的同时会调用函数,但是传递参数的形式不同,call时一个一个的接收参数,而apply时以数组的形式接收参数,call通常和构造函数来模拟继承。
3.bind传参和call一样,但是不会调用函数,通常用于自执行函数改变this指向。
参考资料:
https://blog.csdn.net/weixin_43638968/article/details/107523660
https://blog.csdn.net/qq_46448507/article/details/107500736
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律