apply&call 小记

定义

在阅读代码的过程中,经常会看到call()和apply()两个函数。每次我见到这两个函数都很好奇他们的使用方法到底是怎样。今天抽空具体研究了一下,在此做下记录。

语法

1
2
call(obj,[arg1],[arg2])
apply(obj,argArray)

call和apply的官方解释:
调用一个对象的方法,以另外一个对象替换当前对象。
通俗的讲就是调用方法,并改变对象的运行时上下文。根据传入的对象上下文运行方法,让人更灵活的使用方法并传入参数,二者除传入参数的规则不同外基本完全相同。

几个案例

1.调用方法

1
2
3
4
5
6
7
8
9
10
function add (a, b) {
console.log(a + b);
}
function sub(a, b) {
console.log(a - b);
}
add.call(sub, 3, 1); //4
sub(3,1); //2

将add方法的运行时context改为sub并传入参数并进行调用,sub方法并没有改变。

2.更改函数运行时上下文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function Animal(name) {
this.name = name;
this.age = 19;
this.showName = function () {
console.log('name: ' + this.name);
}
this.showAge = function () {
console.log('age: ' + this.age);
}
}
function Cat(name) {
this.name = 'cat';
this.showName = function () {
console.log('原方法');
}
}
var animal = new Animal();
var cat = new Cat();
animal.showName.call(cat); //name: cat
cat.showName(); //调用原方法
animal.showAge.call(cat); //age: 19
cat.showAge(); //error 没有showAge方法

将animal的showName方法运行时改为cat并调用,
因此此时的this为cat,则this.name为’cat’。但是cat对象并没有获得此方法。

3.实现继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function Animal(name) {
this.name = name;
this.showName = function () {
console.log('name: ' + this.name);
}
}
Animal.prototype.eat = function() {
console.log(this.name + 'startEat');
};
function Dog(name) {
Animal.call(this, name);
}
var dog = new Dog('dog');
dog.showName(); //name: dog
dog.eat(); //error 无法调用到eat方法

将Animal类替换到this对象,使Dog获得Animal类的方法及属性从而实现继承。
当一个object没有某个方法,但是其他的有,我们可以借助call或apply用其它对象的方法来操作。
但是试验中dog并没有继承到Animal原型上的eat方法,此点需要深入研究下。

4.常用方法 (引自知乎

通过document.getElementsByTagName选择的dom节点返回动态的 NodeList,只有length属性和方法item。它不能应用Array下的push,pop等方法。我们可以通过:

1
var domNodes = Array.prototype.slice.call(document.getElementsByTagName(*));

这样domNodes就可以应用Array下的所有方法了。

总之 call和apply能够很好的提高我们的代码效率。如何更好的使用这两个方法,就要靠平时的认真积累拉。