javascript
this
基础
call
apply
javascript
Javascript函数中的this关键字的行为相比其余语言有不少不一样。在Javascript的严格模式下和非严格模式下也略有不一样。html
在大多数状况下,函数的调用方式决定了this的值。this不能在执行期间被赋值,在每次函数被调用时this的值也会不一样。ES5增长了bind方法,能够在不对函数进行调用的状况下传入this值。java
在全局上下文中(在任何函数体外部),this指代全局对象,不管是否在严格模式下。web
console.log(this.doucment === document) //true //In web browsers, the window object is also the global object: console.log(this === window); //true this.a = 37; console.log(window.a); //37
在函数内部, this的值取决于函数是如何调用的。chrome
function f1() { return this; } f1() === window; //global object
在这个例子中,this的值不是由函数调用设定。由于代码不运行在严格模式下,this的值始终是一个对象且默认为全局对象。express
function f2() { "use strict"; return this } f2() === undefined; //return undefined
在严格模式下,this的值根据执行时的上下文,this所保存的值决定。若为定义,this还是undefined, 它可能被设置为任何的值,好比null,42或者是 " I'am not this "。浏览器
在第二个例子中,this的值应该是undefined。由于f2被调用时未基于任何对象(e.g.window.f2())。这个功能并未在全部第一次开始支持严格模式的浏览器中都获得普遍支持,在不支持的浏览器中,仍然返回window,好比chrome。app
当一个函数做为一个对象的方法被调用,它的this会被设置为调用该方法的对象。
在下面的例子中,当o.f()被调用,function内部的this会绑定到这个object。函数
var o = {}; o.prop = 37; o.f = function() { return this.prop; }; console.log(o.f()); //37
注意,如何调用或者在何处定义这个函数并不影响this的行为,在前一个例子中,咱们在定义的object中为成员f添加了一个匿名函数,然而,咱们能
更简便的先定义这些函数而后再将其附属到o.f上。这样作this的行为也是一致。ui
var o = {prop:37}; function independent(){ return this.prop; } o.f = independent; console.log(o.f()); //logs 37
这个例子只有o对象中的f才会令这个函数被调用。
一样的,this绑定只会被最当前的引用所决定。在接下来的例子中,当咱们调用这个function,把它看成o.b对象的g方法调用。在执行中,this会附属到o.b上。这个对象自己做为o的成员没有结果,其返回结果就是当前引用。
以下例:
o.b = {g: independent, prop:37} console.log(o.b.g()); //返回37
只要方法是定义在对象的原型链中上面的调用一样的仍然正确,若是方法在一个对象的原型链中,this对象指向调用这个方法的对象,就像这个方法存在于这个对象中同样。
var o = { f:function(){return this.a + this.b;} } var p = Object.create(o); p.a = 1; p.b = 5; console.log(p.f()); //6
在此例中,p对象并无它本身的实例f属性,它继承于原型链。可是没有关系f能在o对象中找到;查找以一个p.f的引用开始,所以这个function中的this取对象p的引用值。也就是说,当f函数做为p的对象被调用,它的this指向p。这是Javascript原型继承中很是有趣的特征。
当方法被getter或者setter调用一样的概念仍然成立,当对象的属性被set或者是gotten时,它的getter或者setter函数中的this对象会被绑定到当前对象。
function modulus(){ return Math.sqrt(this.re*this.re + this.im*this.im); } var o = { re : 1, im : -1, get phase(){ return Math.atan2(this.im,this.re); } }; Object.defineProperty(o,'modulus',{get: modulus,enumerable: true,configurable:true}); console.log(o.phase,o.modulus); //返回-7.86 1.414
当函数做为构造器(使用new关键词),它的this绑定为新构造的对象。
注意:固然默认的构造器返回的this对象为当前调用对象,它能被当前对象中return的新对象所取代(若是对象的返回值不是对象,那么this仍指向当前对象)。
/*注意中示例*/ var o = { a : 12, f : function(){ return this.a; } }; var p = { a : 21, f : function(){ return o.f(); } }; console.log(p.f()); //返回12
构造器示例
/* * Constructors work like this: * * function MyConstructor(){ * // Actual function body code goes here. Create properties on |this| as * // desired by assigning to them. E.g., * this.fum = "nom"; * // et cetera... * * // If the function has a return statement that returns an object, that * // object will be the result of the |new| expression. Otherwise, the * // result of the expression is the object currently bound to |this| * // (i.e., the common case most usually seen). * } */ function C(){ this.a = 37; } var o = new C(); console.log(o.a); //返回37 function C2(){ this.a = 38; return {a:38}; } o = new C2(); console.log(o.a); //返回38
在上一个例子中(c2),由于有一个对象在构建中返回,因此this对象绑定到了返回的对象上。
在function内部使用this关键词时,它的值能够在使用call或apply(全部的function对象都继承自Function.prototype)调用时绑定为该函数中传入的对象。
function add(c,d) { return this.a + this.b + c + d; } var o = { a : 2, b : 2 } console.log(add.call(o,2,2)); //返回8 console.log(add.apply(o,[2,4])); //返回10
ECMAScript 5介绍 Function.prototype.bind.调用f.bind(someObject).建立一个新的function拥有相同的内容和做用域,好比f,可是this对象仍然出如今原来的function中,在新的function中他仍然永久的被绑定在第一个bind的参数(someObj)上,好比下面的g函数,不管这个function被调用了多少次。
function f(){ return this.a; } var g = f.bind({a : "penouc"}); console.log(g()); var o = {a : 37,f : f, g : g}; console.log(o.f(),o.g());
当一个function被用做为一个事件处理程序,它的this被设置为当前的元素(一些浏览器并不遵循这个规则而是动态的添加方法好比使用addEventListener)。
//当元素被调用,其被激活为蓝色 function bluify(e) { console.log(this === e.target); console.log(this === e.currentTarget); this.style.backgroundColor = "#A5D9F3"; } //得到整个document的元素 var elements = document.getElementsByTagsName("*"); //当元素被点击时元素被调用 for(var i = 0; i < elements.length; i++) { elements[i].addEventListener('click',bluify,false); }
当代码被行内事件处理程序调用,它的this就是当前元素:
<button onclick="alert(this.tagName.toLowerCase());">Show this</button>
以上警告为button。注意不管如何只有在存在外层代码才设置为这样:
<button onclick="alert((function(){return this}}()));">Show inner this</button>
在这个例子中,内部的function的this并未设置所以返回为window/global对象。