人生自是有情痴,此恨不关风与月javascript
今天所写的内容,是对以前的内容的总结和扩展。老实说,对于本身以前的一些杜撰和臆测,我并非很满意。因此这篇博文,我但愿能来点干货。java
在JavaScript中,咱们能够用this来指代当前的对象。这种感受就像使用Java同样。不过与Java不一样的是,在Java中,this的指代老是很明显的;然而在JavaScript中,this的指代在不一样的调用方式下,其指代每每不一样。我为此分为四类:数组
若是咱们定义如下函数:app
function f() { console.log(this); }
而后将其做为普通对象调用,即f()
,此时this指代的是全局对象window。函数
若是咱们将f做为一个对象的方法,也就是说做以下改造:this
var a = {}; a.f = f;
而后经过对象a调用方法f,即a.f()
,此时this指代的就是调用者a。prototype
若是咱们用new语句调用函数f,即new f()
, 则此时this指代的是新建的对象。code
除了上述几种方式外,咱们还能够任意指定this的指代,这就是call和apply发挥做用的地方了。call和apply是每一个函数对象都拥有的方法,其第一个参数就是要指定的this值,后面是函数正常的参数值。其细微的差异在于参见下面的示例:对象
function g(name, age) { this.name = name; this.age = age } var a = {}; g.call(a, 'xiaoming', 18); g.apply(a, ['xiaoming', 18]);
即call的非this参数只需在后面列出就能够了,apply要把它们封装到一个数组里面去。ip
从某种程度上说,前面的三种函数调用形式都是call方式的一种语法糖:
f() === f.call(window)
a.f() === f.call(a)
new f() === var _a = {}; f.call(_a)
call有很强大的能力,咱们经常使用的函数借用就是利用call能够动态指定this这一特性的。例如Array.prototype.slice.call(a)
能够将看起来像数组的对象a转化为实际的数组对象。
var a={length:2,0:'first',1:'second'}; Array.prototype.slice.call(a);// ["first", "second"] var a={length:2}; Array.prototype.slice.call(a);// [undefined, undefined]