call() 、 apply() 、bind()方法的作用和区别!
本文转载:https://www.cnblogs.com/liuyilong/p/11710798.html
js中call、apply、bind方法的作用和区别
这三个方法的作用都是改变函数的执行上下文!换句话说就是改变函数体内部的this的指向,以此来扩充函数赖以运行作用域。
1. call方法
- 作用:专门用于修改方法内部的
this
指向 - 格式:
xxx.call( 对象名, 参数1, 参数2 , ...);
。即:将xxx
方法的this
指向为对象名
- 实例:
function test(a,b){ console.log(this); console.log(a + b); } test(1,2); // window 3 var obj = {name:'zjy'}; window.test.call(obj,3,5); // {name:'zjy'} 8
解析:没有使用 call 方法时,test方法的this指向全局对象window,而当使用了call方法后,将test的this指向从window变成了obj对象,而后面的参数则是对应方法的形参顺序
2. apply方法
- 作用:和call方法一样也是修改方法内部的
this
指向的,它们的区别在于apply的第二个参数必须为一个数组(部署了Iterator接口的类数组对象也可以) - 格式:
xxx.apply( 对象名, [数组]);
。即:将xxx
方法的this
指向为对象名
,数组中的元素依次与方法的形参对应 - 实例:
function test(a,b){ console.log(this); console.log(a + b); } test(1,2); // window 3 var obj = {name:'zjy'}; window.test.apply(obj,[3,5]); // {name:'zjy'} 8
解析:没有使用 apply 方法时,test方法的this指向全局对象window,而当使用了apply方法后,将test的this指向从window变成了obj对象,而后面的数组参数则是将数组中元素依次对应到test方法形参的位置
3. bind方法
- 作用:也是改变this的指向问题
- 格式:
xxx.bind( 对象名 , 参数1, 参数2 , ...);
。即:将xxx
方法的this
指向为对象名
- 实例:
var obj = {key:"value"} var foo = function(){ console.log(this) } foo.bind(obj)() // obj
解析:在没有使用bind方法时,foo()中的this指向的是全局对象window,而使用了bind方法之后则指向的是obj对象
4. 真数组转变为类数组过程
- 写法:
var arr = [1,3,5]; var obj = {}; [].push.apply(obj,arr); // { 0:1, 1:3 , 2:5 , length:3 }
5. 类数组转变为真数组过程
- ES5写法:
// 系统自带类数组对象 var divs = document.querySelectorAll('div'); // 自定义类数组对象 var obj = {0:'zjy' , 1:18 , length:2}; var arr = []; // 真数组 // 在高级的浏览器中使用如下的方法是可以实现类数组对象转换为真数组,但是在 IE8 及其以下是不行的 // [].push.apply(arr,divs); // [].push.apply(arr,obj); // 为了兼容 IE8 及其以下的浏览器,需要使用数组的 slice 方法 // 数组的 slice 方法不传递参数的时候是将数组中的元素依次遍历然后放到一个 新的数组 中原样返回 var arr2 = [].slice.call(obj);
- ES6写法:
Array.from();方法用于将类数组对象和可遍历(Iterator)对象转换为真数组
var obj = {0:'zjy' , 1:18 , length:2}; var arr = Array.from(obj) // ['zjy',18]
扩展运算符(...
)也可以将可遍历(Iterator)对象转换为真数组
[..document.querySelectorAll('div')]
题目:
var test = { a : 5, b : 6, sum : function (a,b) { var self = this; function getA() { console.log(self.a);//2 console.log(a);//4 return self.a; } function getB(){ console.log(self.b);//3 console.log(b);//5 return self.b; } alert(a); alert(b); return getA() + getB(); } } var obj = {a:2,b:3}; --------------------------------------------------------------------------------------- alert(test.sum.call(obj,4,5)); 调用test.sum.call(obj,4,5)时self = this = obj,alert顺序4,5,5 sum 函数的入参是4,5,函数体内部alert(a)直接打印的值是参数的值, 但是里面的this指向已经发生改变,this.a已经是obj的值 --------------------------------------------------------------------------------------- alert(test.sum.apply(obj,[6,7])); 调用时self = this = obj,alert顺序6,7,5 ----------------------------------------------------------------------------------- var sum = test.sum.bind(obj,8); 此处返回的sum函数是只有一个参数的函数sum(b) 概念点:bind方法返回的形参数量length,等于原函数的形参个数减去传入bind方式的实参数量(第一个参数后的所有参数) 因为传入bind中的实参都会绑定到原函数的形参。 console.log(sum); alert(sum(9)); 这里调用的时候sum就是sum(8,9),this指向的是obj alert顺序8,9,5