Javascript 方法call、apply、bind的使用详解及区别

javascript 的这几种方法在我的编程中不经常出现,所以对之知之甚少,偶尔看见也是查一下,并没有深入了解,他们的区别也就更不知道了,所以在这里总结一下,也学习一下。

call() & apply()

每个函数都包含两个非继承而来的方法:apply()和call(),他们的用途都是在特定作用域中调用函数。

fun.call(thisArg[, arg1[, arg2[, ...]]]) 

call()作用就是改变当前作用域,即改变this的指向,将函数对象从初始的上下文改变为由thisArg指定的新对象。
thisArg:可选项,将被当做当前对象。如果没有thisArg,那么global对象将被用作thisArg。
arg1,arg2:可选项,将被传递方法参数序列。

call() 案例

demo1
1
2
3
4
5
6
7
8
9
10
11
12
<input type="text" id="idTxt" value="input text">

var value = "global var";
function mFunc(){
this.value = "member var";
}
function gFunc(){
console.log(this.value);
}
window.gFunc(); //=>global var
gFunc.call(window); //=>global var
gFunc.call(document.getElementById('idTxt')); //=>input text
demo2
1
2
3
4
5
6
7
8
9
10
11
var func = new function() {
this.a = "func";
}

var func2 = function(x) {
var a = "func2"
console.log(this.a); // func
console.log(x); // lalala
}

func2.call(func, "lalala");

首先解释下为啥func函数用了new这个关键字,用了new关键字就是一个构造函数,实际上就是创建了一个对象,这样就可以使this成为这个对象本身,而不是全局对象。

demo3
1
2
3
4
5
6
7
8
9
10
var animals = [
{ species: 'Lion', name: 'King' },
{ species: 'Whale', name: 'Fail' }
];

for (var i = 0; i < animals.length; i++) {
(function(i) {
console.log('#' + i + ' ' + this.species + ': ' + this.name);
}).call(animals[i], i);
}

匿名函数的调用,把animals里的对象当做this指针,也很好理解。

apply()方法与call()方法基本一样,只是第二个参数传入的是数组,这里就不举例子了

fun.apply(thisArg, [arg1,arg2,…argN])

bind()

bind()最简单的用法是创建一个函数,使这个函数不论怎么调用都有同样的this值。

bind()案例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var x = 9;
var module = {
x: 81,
getX: function () {
return this.x;
}
};

console.log(module.getX()); // 81

var getX = module.getX;
console.log(getX()); // 9,因为this是全局变量

// 创建一个新方法,把this指向module
var boundGetX = getX.bind(module);
console.log(boundGetX()); // 81
和setTimeout一起使用

一般情况下setTimeout()的this指向window或global对象。当使用类的方法时需要this指向类实例,就可以使用bind()将this绑定到回调函数来管理实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Bloomer() {  
this.petalCount = Math.ceil(Math.random() * 12) + 1;
}

// 1秒后调用declare函数
Bloomer.prototype.bloom = function() {
setTimeout(this.declare.bind(this), 1000);
};

Bloomer.prototype.declare = function() {
console.log('我有 ' + this.petalCount + ' 朵花瓣!');
};

var blom = new Bloomer();
blom.bloom(); // 我有 ** 朵花瓣!

注意:对于事件处理函数和setInterval方法也可以使用上面的方法

坚持原创技术分享,您的支持将鼓励我继续创作!