关于javascript中的call方法,网上查了一些资料老是不得详解。总结网上的观点,call有两个妙用:javascript
1: 继承。(不太喜欢这种继承方式。)java
2: 修改函数运行时的this指针。函数
js中关于call的解释以下:测试
js关于call的这份文档容易让人迷糊。而《javascript权威指南》对call的描述就比较容易理解了。this
注意红色框中的部分,f.call(o)其原理就是先经过 o.m = f 将 f做为o的某个临时属性m存储,而后执行m,执行完毕后将m属性删除。指针
如 function f(){对象
var a = "name";blog
this.b = "test1";继承
this.add = function (){ return "add" }ip
}
function o(){
this. c = "c";
}
f.all(o);
图 1
图1中 f.call(o)其实至关于: function o(){
this.c = "c" ;
var a = "name";
this.b = "test1";
this.add = function (){ return "add" }
}
说白了,就是把f的方法在o中走一遍,但不作保存。既然不作保存,那么如何经过call实现继承和修改函数运行时的this指针等妙用?关键在于this,对,关键仍是在于this的做用域。在以前的文章反复说过,this的做用域不是定义它的函数的做用域,而是执行时的做用域。
以下例子:
图 2
如图2, 在执行A.call(this)以前,输出的this 不包含任何属性和方法,以后则继承了A的属性和方法。仍是按照上面的方法解释,执行完A.call(this) (this此时表明执行时的做用域,即B)后,B构造函数以下:
function B()
{
console.log(this);
this.test1 = "test1";
this.test2 = "test2";
this.add = function(){ return this.test1 + this.test2 ; }
console.log(this);
}
由于调用A.call(this)的时候,this做用域已经发生改变了,表明的都是B(),哪怕执行A中的方法和属性的时候,this也是表明着执行时的做用域B();因此如此才能实现继承,即将A()中的属性赋值和方法定义在B()中再走一遍。其实此时也修改了函数运行时的this指针。
关于call的第二个妙用,修改函数运行时的this指针:
这里采用一位贴吧大神的回答,作了一个测试例子,其实应该也是js中关于each遍历的定义。
图 3
如图3,第一个中直接调用fn方法,其中由于没有定义函数做用域,输出的this表示window对象,即全局对象。而第二个中经过fn.call(array[index] , index , array[index] )将fn方法放到array[index]做用域中执行,输出的this表示的是array[index]对象。
换一个视角:
图 4
如图 4 , 经过each方法中调用call方法能够实现遍历。咱们假设array[index]是DOM元素集合,如标签为li的全部集合,假设fn是咱们自定义实现的方法,不就是咱们用的each遍历DOM元素的方法吗?
图 5
如图5,简单的代码即实现了遍历DOM元素的each方法。