javascript的this关键字


英文原文:http://devign.me/javascript-this-keyword/

什么是this

Javascript的this关键字是很容易理解混乱的。javascript的this关键字的定义是——调用这个函数的那个对象。this用于任何一个函数的作用域或者全局域,在每一个作用域接收一个不同的值。位于一个函数内部的this,它的值依赖于调用这个函数的对象,也就是说调用对象的不同,this的值也不同。

作用域是什么呢?每个函数有它自己的空间定义变量和属性,当访问一个变量时,必须通过定义这个变量的空间。在javascript中,当没有定义一个函数时,则任何事情都发生在全局域。

var o={};//声明一个对象
o.name = "moon";
o.method = function(){
    alert(this.name);
};
o.method();

我们定义了一个对象o,和一个方法用来显示this.name,但是this来自哪里呢?

通过调用函数o.method(),我们得到值"moon",其发生的过程是这样的:

1. 创建了一个string类型的变量,其值为"moon", 并且将这个name的属性赋予o;

2. 创建一个方法,并且将此方法赋予给了o;

3. 调用这个方法,o就是调用这个方法的对象;

4. 方法调用时,this实际就是o的一个参考,得到o.name就是moon;


函数其实也是一个普通意义上的变量,它包含了一个表达式,这些表达式在函数被调用时执行。将method方法赋予o的属性,并不使得this就与o连接。对象并不知道这个函数内的内容,this实际赋值是在这个函数被真正调用的时候,这时this被赋值为调用这个函数的对象,即o。

我们将之修改的更复杂点:

var o={};
o.name = "moon";
o.method = function(){
    alert(this.name);
};
var x={};
x.name = "sun";
x.method = o.method;
x.method();
上面定义了一个新的对象x,并且给它name的属性赋值为sun;将o的method的方法赋予x的method的属性。程序运行的结果是没有得到“moon",我们得到的值是sun,因为x是抵调用函数method的对象,所以this的值是x,而不是o.

我们可以说每一个javascript的函数都都有一个隐藏的参数叫this,可以更深地理解为每次调用函数的时候,都有一个this参数传递给这个函数,这个this就是调用这个函数的对象。

function f(){alert(this.name);};
变成
function f(this){alert(this.name);};


 
  
var o={};
o.name = "moon"
o.method = function(this)
{
   alert(this.name);
};
o.method(o);

var x={};
x.name = "sun";
x.method = o.method;
x.method(x);

改变this的值

javascript提供了两个函数可以方便地改变this的值,这两个函数时call和apply. 这两个函数很相似,他们都是一个函数方法(在Function.prototype定义),他们都有一个参数定义this的对象,同时也包含了函数调用的参数。两者不同的地方时参数传递的方式,call就是普通的参数传递,有几个参数就传递几个参数,apply只传递一个包含这些参数的数组;

将上面的代码该成call的调用:

var o={};
o.name = "moon";
o.method = function()
{
   alert(this.name);
};
var x={};
x.name = "sun";
o.method.call(x);

上面这段代码背后是什么呢,相当于

x.temporarymethod = o.method;
x.temporarymethod();

this的值是x,它的输出是sun;


this和new 操作符

一个javascript函数不仅仅是一组稍后使用的状态,它其实也是一个类。没一个函数都可以看做是一个类。我们可以创建一个类的实例:

function Foo(name)
{
  this.name = name;
}

这个函数像所有的函数一样也是一个类,因此可以创建它的一个实例

var instance = new Fool("bar");
alert(instance.name);//bar

当调用new Foo("bar")时,后面实际发生了什么呢?

var instance={};
Foo.call(instance,name);

调用构造函数将执行表达式

this.name = name;

编译器创建了一个新的,空的对象,并且用call激活了类的构造函数。这样this就是新创建的对象的引用,构造函数执行表达式,返回新的对象。

this和prototype

prototype是类的一个属性,不论给他赋予什么值,这个值对类的所有实例都是有效的。当访问一个对象属性,会首先检查对象是不是已经存在这个属性,如果不存在,这个值就会被赋予给这个对象所属的类(这个对象最基础的类);

javascript有一些预定义好的类:Object, Function, String, Number, Array, Date, Math, Error, RegExp

我们可以用我们自己的方法扩展这个任何的类,然后这个类的每个实例都包含了我们的扩展。

String.prototype.trim = function()
{
  return this.replace(/^\s+|\s+$/g,"");
}
var s = "       x         ";
alert("<"+s+">");
alert("<"+s.trim()+">");

上面给string类扩展了一个trim的方法,其功能是删除字符串从头到位的空白。我们可以从任何字符串方法这个方法,this将包含string的值,因为string变量就是调用这个函数的对象。

this和DOM

<div id="div" onclick="alert(this.innerHTML);">div</div>

DOM能够理解这段代码为:

div.onclick=function () {
    alert(this.innerHTML);
};

onclick定义为一个属性,它的值是一个函数。浏览器会应用一个监听器给鼠标点击动作。一旦click收到,它会检查他的位置是否是在div,然后检查div是否有onclick属性,然后调用这个方法:

div.onclick(event);

因此this就是div的引用。



猜你喜欢

转载自blog.csdn.net/wowo1109/article/details/6747641