js作用域使用方法说明,深入理解Javascript中this的
分类:关于美高梅

大家在使用Javascript的时候经常被this这个家伙搞得晕头转向的。对大多数有OOP开发经验的开发人员来说this是当前作用域中引用普通元素的标识符,但是在Javascript中它却显得古灵精怪的,因为它不是固定不变的,而是随着它的执行环境的改变而改变。在Javascript中this总是指向调用它所在方法的对象。

深入理解Javascript中this的作用域,深入理解javascript

大家在使用Javascript的时候经常被this这个家伙搞得晕头转向的。对大多数有OOP开发经验的开发人员来说this是当前作用域中引用普通元素的标识符,但是在Javascript中它却显得古灵精怪的,因为它不是固定不变的,而是随着它的执行环境的改变而改变。在Javascript中this总是指向调用它所在方法的对象。

举一个简单的例子:

复制代码 代码如下:

function test(){
alert(this);
}
var obj=function(){
var name='testObj';
}
obj.objTest=test;
test();
obj.objTest();

把这段代码放到HTML中运行这个页面,你会看到首先提示一个警告[object window],然后第二个警告。

复制代码 代码如下:

var obj=function(){
var name='testObj';
}

我们先定义了一个test()方法,并在方法内部调用alert()方法将this显示出来,然后定义了一个obj函数对象,并给它加了一个私有的字段name,同时给它加了一个静态的方法objTest(),而这个函数则直接指向test()函数。

分别调用test()和obj.objTest()方法,第一次警告框提示的是Window对象,而第二次提示的是我们定义的obj这个函数的代码。这说明了test函数在两次执行的时候this的值是不同的!

这就说明了当调用函数的对象不同的时候,其内部的this关键字指代的对象是不同的。这里需要值得注意的是Javascript是基于对象的语言,当我们的变量或者函数定义在<script></script>标签的根下的时候其实相当于给window对象加了相应的属性或方法,所以当我们利用function test(){}代码定义一个函数的时候,其实相当于给window对象添加了一个新的函数,即window.test()函数。

我们可以做一个实验:

复制代码 代码如下:

function test(){
alert(this);
}
alert(test===window.test);

警告框提示的将是true,这说明当我们在调用test()这个函数时相当于调用的是window.test()。所以当我们调用test()函数的时候调用这个函数的对象其实是window对象,this指代的是window对象,所以我们在alert(this)的时候弹出的警告窗口内容是[object Window]。我们将obj.objTest=test相当于把obj.objTest()指向test(),所以当我们调用obj.objTest()函数时相当于在obj调用了test()这个函数,所以现在this指代的是obj对象,提示的就是obj这个Function也就是我们看到的代码。

说到这应该也解释的差不多了,可能上面的例子太抽象,想象不出来它能在什么情况下用到,那我们现在就假设一个需求,做一个贴近实用一点的例子。

假设我们现在页面中的所有超链接在点击之后颜色要改为红色,用Javascript实现。大体的思路应该是获取页面中所有的<a>标签,然后遍历所有的<a>标签,给每一个注册一个click事件,事件触发后我们将它的color值设为red。

示例代码如下:

复制代码 代码如下:

//改变颜色
function changeColor(){
this.style.color='#f00';
}
//初始化,给所有 a 标签注册事件
function init(){
var customLinks=document.getElementsByTagName('a');
for(i in customLinks){
//你也可以使用事件侦听器方式来注册事件
//由于要兼容IE,FF等浏览器可能需要更多代码,您可以自行编写
customLinks[i].onclick=changeColor;
}
}
window.onload=init;

将这段代码添加到HTML文档中,并在文档中添加一些超链接,当超链接点击后颜色会变成红色,这里我们定义的changeColor()函数中this关键字在点击超链接触发函数的时候它指代的是当前这个超链接。而如果你直接调用changeColor()函数浏览器会报错,提示Error: ‘this.style' is null or not an object或者undefined之类的错误。

不知道说到这能不能让正在看文章的你对Javascript中的this关键字有了一些自己的了解呢?或者你已经不耐烦了?(:P)

其实要想真正对这个问题有更深入的理解那么必须对Javascript的作用域和作用域链有深入的理解。

作用域,顾名思义就是指某一属性或方法具有访问权限的代码空间,简单的说也就是这个变量或方法它在代码中的的适用范围。在大多数的OOP中主要有public,private,protect三种作用域,对着三种作用域在这里就不详细解释了,如果有OOP的经验应该都有深入的了解。在这里我要说的是这三种作用域类型对Javascript来说几乎是毫无意义的,因为Javascript中只有一种公共作用域,在Javascript中作用域是在函数中进行维护的。举个例子:

复制代码 代码如下:

var test1='globle variable';
function example(){
var test2='example variable';
alert(test1);
alert(test2);
}
example();
alert(test1);
alert(test2);

根据我们前面解释的,这里的test1变量相当于window的一个属性,所以它会在整个window作用域内起作用,而test2则在example()函数的内部声明,所以它的作用域也就维持在example()方法的内部,如果在函数的外部调用test2浏览器会提示出错。而在example()内部调用test1则没问题。

根据这个我们再举一个例子:

复制代码 代码如下:

var test='globle variable';
function example(){
var test='example variable';
}
example();
alert(test);

这个例子运行会是什么结果呢?对,警告框会提示“globle variable”,因为example()函数内部的test变量其作用域只维持在内部,不会影响外部的test变量。如果我们将example()内部test变量的var关键字去掉呢?你可以自己试试。

说到这就有牵扯出另外一个概念,那就是作用域链的概念。作用域链就是可以确定变量值的路径。由上面一个例子可以看出,var关键字是用来维护作用域链的,如果变量使用了var关键字声明那么他就可以看作为作用域链的终点。同样函数的形参的定义也会起到类似的作用。

说到这你对this这个精灵古怪的家伙有了比较清晰的认识了吧?根据它简单的一个诠释,this总是指向调用它所在函数的对象,根据作用域和作用域链,我们会很清晰的确定this的真面目。临末尾再来一个开始那个例子的简单变化:

复制代码 代码如下:

function test(){
alert(this);
}
var obj=function(){
var name='testObj';
}
obj.objTest=test;
obj.objTest2=function(){
test();
}
test();
obj.objTest();
obj.objTest2();

你猜会提示什么内容呢?你可以运行一下试试(:P);

既然this是根据调用其所在函数的对象的改变而改变的,那我们可不可以强制改变它的调用对象呢?答案是肯定的,以后的文章会介绍一下这部分内容,以及Javascript中不同类型的数据成员的实现方式,闭包等概念。

本人在学习过程中的一些经验和心得体会,写出来一是与大家分享另外也能检视自己的不足,如写的有问题还请批评指教,甚为感谢!

js作用域用法多样并且一个细节都会产生不同效果,下面我来总结一些js作用域使用方法说明,有需要的朋友可参考。

JavaScript中this的使用

举一个简单的例子:

javascript this作用域详解

如果从js 底层语法来讲,this 指的是当前对象的prototype.
即如果你调用的是一个方法:
function fun(){
this.val = "";
}
fun();
那么这里的this 指的就是fun这个方法对象的prototype 通俗来讲就是方法对象
如果是给你个Html的Button注册的时间方法,那么只想的是这个button.

所以this所指向的对象其实是可以动态改变的,并不是一成不变,1楼的回答只是浏览器的默认Prototype。  

一个面试题以它来详细介绍js作用域

在JavaScript中this变量是一个令人难以摸清的关键字,this可谓是非常强大,充分了解this的相关知识有助于我们在编写面向对象的JavaScript程序时能够游刃有余。

复制代码 代码如下:

在这里javascript 中this 是什作用域

看如何调用,如果
Ge.StringBuilder()//则Ge
Ge.StringBuilder.call(some)//则some
new Ge.StringBuilder()//则this
var fn=Ge.StringBuilder; fn()//则window  

大家在使用Javascript的时候经常被this这个家伙搞得晕头转向的。对大多数有OOP开发经验的...

 代码如下

对于this变量最要的是能够理清this所引用的对象到底是哪一个,也许很多资料上都有自己的解释,但有些概念讲的偏繁杂。而我的理解是:首先分析this所在的函数是当做哪个对象的方法调用的,则该对象就是this所引用的对象。

function test(){
alert(this);
}
var obj=function(){
var name='testObj';
}
obj.objTest=test;
test();
obj.objTest();

复制代码

示例一、

把这段代码放到HTML中运行这个页面,你会看到首先提示一个警告[object window],然后第二个警告。

function foo(){
 foo.abc = function(){alert('Alibaba')}
 this.abc = function(){alert('Alimama')}
 abc = function(){alert('Alipay')};
 var abc = function(){alert('Taobao')}
}
foo.prototype.abc = function(){alert('Alisoft');}
foo.abc = function(){alert('Yahoo');}
var obj = new foo();
obj.abc();
foo.abc();
abc();

复制代码 代码如下:

复制代码 代码如下:

我们就直接针对这输出按顺序进行分析,

var obj = {};

var obj=function(){
var name='testObj';
}

 

obj.x = 100;

我们先定义了一个test()方法,并在方法内部调用alert()方法将this显示出来,然后定义了一个obj函数对象,并给它加了一个私有的字段name,同时给它加了一个静态的方法objTest(),而这个函数则直接指向test()函数。

执行顺序

obj.y = function(){ alert( this.x ); };

分别调用test()和obj.objTest()方法,第一次警告框提示的是Window对象,而第二次提示的是我们定义的obj这个函数的代码。这说明了test函数在两次执行的时候this的值是不同的!

 代码如下

obj.y(); //弹出 100

这就说明了当调用函数的对象不同的时候,其内部的this关键字指代的对象是不同的。这里需要值得注意的是Javascript是基于对象的语言,当我们的变量或者函数定义在<script></script>标签的根下的时候其实相当于给window对象加了相应的属性或方法,所以当我们利用function test(){}代码定义一个函数的时候,其实相当于给window对象添加了一个新的函数,即window.test()函数。

复制代码

这段代码非常容易理解,当执行 obj.y() 时,函数是作为对象obj的方法调用的,因此函数体内的this指向的是obj对象,所以会弹出100。

我们可以做一个实验:

1.foo.prototype.abc = function(){alert('Alisoft');}

示例二、

复制代码 代码如下:

//这样之后,我们就可以用obj.abc();不懂prototype原型的,可以看这个prototype原型继承

复制代码 代码如下:

function test(){
alert(this);
}
alert(test===window.test);

2.foo.abc = function(){alert('Yahoo');}

var checkThis = function(){

警告框提示的将是true,这说明当我们在调用test()这个函数时相当于调用的是window.test()。所以当我们调用test()函数的时候调用这个函数的对象其实是window对象,this指代的是window对象,所以我们在alert(this)的时候弹出的警告窗口内容是[object Window]。我们将obj.objTest=test相当于把obj.objTest()指向test(),所以当我们调用obj.objTest()函数时相当于在obj调用了test()这个函数,所以现在this指代的是obj对象,提示的就是obj这个Function也就是我们看到的代码。

//alert yahoo

alert( this.x);

说到这应该也解释的差不多了,可能上面的例子太抽象,想象不出来它能在什么情况下用到,那我们现在就假设一个需求,做一个贴近实用一点的例子。

3.var obj = new foo();

};

假设我们现在页面中的所有超链接在点击之后颜色要改为红色,用Javascript实现。大体的思路应该是获取页面中所有的<a>标签,然后遍历所有的<a>标签,给每一个注册一个click事件,事件触发后我们将它的color值设为red。

//创建一个foo的实例obj,同时,执行了foo函数,也就是obj.abc() = function(){alert('Alimama')}

var x = 'this is a property of window';

示例代码如下:

4.foo.abc = function(){alert('Alibaba')}

var obj = {};

复制代码 代码如下:

//foo.abc是foo类的静态方法,在实例化foo后执行了代码片段foo.abc = function()

obj.x = 100;

//改变颜色
function changeColor(){
this.style.color='#f00';
}
//初始化,给所有 a 标签注册事件
function init(){
var customLinks=document.getElementsByTagName('a');
for(i in customLinks){
//你也可以使用事件侦听器方式来注册事件
//由于要兼容IE,FF等浏览器可能需要更多代码,您可以自行编写
customLinks[i].onclick=changeColor;
}
}
window.onload=init;

//覆盖了原来的foo.abc = function(){alert('Yahoo');},所以foo.abc()输出alibaba

obj.y = function(){ alert( this.x ); };

将这段代码添加到HTML文档中,并在文档中添加一些超链接,当超链接点击后颜色会变成红色,这里我们定义的changeColor()函数中this关键字在点击超链接触发函数的时候它指代的是当前这个超链接。而如果你直接调用changeColor()函数浏览器会报错,提示Error: ‘this.style' is null or not an object或者undefined之类的错误。

5.this.abc = function(){alert('Alimama')}

obj.y(); //弹出 100

不知道说到这能不能让正在看文章的你对Javascript中的this关键字有了一些自己的了解呢?或者你已经不耐烦了?(:P)

//这句话把function(){alert('Alimama')赋给了obj.abc,所以obj.abc输出alimama

checkThis(); //弹出 'this is a property of window'

其实要想真正对这个问题有更深入的理解那么必须对Javascript的作用域和作用域链有深入的理解。

6.abc = function(){alert('Alipay')};    var abc = function(){alert('Taobao')};

这里为什么会弹出 'this is a property of window',可能有些让人迷惑。在JavaScript的变量作用域里有一条规则“全局变量都是window对象的属性”。当执行checkThis() 时相当于window.checkThis(),因此,此时checkThis函数体内的this关键字的指向变成了window对象,而又因为window对象又一个x属性('thisis a property of window'),所以会弹出 'thisis a property of window'。

作用域,顾名思义就是指某一属性或方法具有访问权限的代码空间,简单的说也就是这个变量或方法它在代码中的的适用范围。在大多数的OOP中主要有public,private,protect三种作用域,对着三种作用域在这里就不详细解释了,如果有OOP的经验应该都有深入的了解。在这里我要说的是这三种作用域类型对Javascript来说几乎是毫无意义的,因为Javascript中只有一种公共作用域,在Javascript中作用域是在函数中进行维护的。举个例子:

//这两句一起分析,如果没有下一句,那么abc是个全局变量,abc输出alipay

上面的两个示例都是比较容易理解的,因为只要判断出当前函数是作为哪个对象的方法调用(被哪个对象调用)的,就可以很容易的判断出当前this变量的指向。

复制代码 代码如下:

//但是因为下一句var abc之后,abc的作用域被限制在foo类里,所以外部的abc()会显示未定义.

this.x 与apply()、call()

var test1='globle variable';
function example(){
var test2='example variable';
alert(test1);
alert(test2);
}
example();
alert(test1);
alert(test2);

 

通过call和apply可以重新定义函数的执行环境,即this的指向,这对于一些应用当中是十分常用的。

根据我们前面解释的,这里的test1变量相当于window的一个属性,所以它会在整个window作用域内起作用,而test2则在example()函数的内部声明,所以它的作用域也就维持在example()方法的内部,如果在函数的外部调用test2浏览器会提示出错。而在example()内部调用test1则没问题。

那么,答案就是

示例三:call()

根据这个我们再举一个例子:

alimama

复制代码 代码如下:

复制代码 代码如下:

alibaba

function changeStyle( type , value ){

var test='globle variable';
function example(){
var test='example variable';
}
example();
alert(test);

undefine

this.style[ type ] = value;

这个例子运行会是什么结果呢?对,警告框会提示“globle variable”,因为example()函数内部的test变量其作用域只维持在内部,不会影响外部的test变量。如果我们将example()内部test变量的var关键字去掉呢?你可以自己试试。

闭包:表示能访问和操作其他本地作用域的变量的表达式(通常是函数)。

}

说到这就有牵扯出另外一个概念,那就是作用域链的概念。作用域链就是可以确定变量值的路径。由上面一个例子可以看出,var关键字是用来维护作用域链的,如果变量使用了var关键字声明那么他就可以看作为作用域链的终点。同样函数的形参的定义也会起到类似的作用。

作用域

var one = document.getElementByIdx( 'one' );

说到这你对this这个精灵古怪的家伙有了比较清晰的认识了吧?根据它简单的一个诠释,this总是指向调用它所在函数的对象,根据作用域和作用域链,我们会很清晰的确定this的真面目。临末尾再来一个开始那个例子的简单变化:

表示变量或函数起作用的区域,指代了它们在什么上下文中执行。Javascript总作用域一共有两种:全局作用域和本地作用域。在Javascript中本地作用域是按照函数来区分的。

changeStyle.call( one , 'fontSize' , '100px' );

复制代码 代码如下:

 代码如下

changeStyle('fontSize' , '300px'); //出现错误,因为此时changeStyle中this引用的是window对象,而window并无style属性。

function test(){
alert(this);
}
var obj=function(){
var name='testObj';
}
obj.objTest=test;
obj.objTest2=function(){
test();
}
test();
obj.objTest();
obj.objTest2();

复制代码

注意changeStyle.call()中有三个参数,第一个参数用于指定该函数将被哪个对象所调用。这里指定了one,也就意味着,changeStyle函数将被one调用,因此函数体内this指向是one对象。而第二个和第三个参数对应的是changeStyle函数里的type和value两个形参。最总我们看到的效果是Dom元素one的字体变成了20px。

你猜会提示什么内容呢?你可以运行一下试试(:P);

var global = "11"; //全局作用域

示例四:apply()

既然this是根据调用其所在函数的对象的改变而改变的,那我们可不可以强制改变它的调用对象呢?答案是肯定的,以后的文章会介绍一下这部分内容,以及Javascript中不同类型的数据成员的实现方式,闭包等概念。

function fun() {

复制代码 代码如下:

本人在学习过程中的一些经验和心得体会,写出来一是与大家分享另外也能检视自己的不足,如写的有问题还请批评指教,甚为感谢!

var local = "22";//本地作用域1

function changeStyle( type , value ){

您可能感兴趣的文章:

  • js中的this关键字详解
  • javascript中onclick(this)用法介绍
  • javascript this用法小结
  • JS中的this变量的使用介绍
  • Javascript this关键字使用分析
  • 改变javascript函数内部this指针指向的三种方法
  • 关于js里的this关键字的理解
  • javascript中this的四种用法
  • Javascript this指针
  • JS函数this的用法实例分析
  • JAVASCRIPT THIS详解 面向对象
  • javascript中的self和this用法小结
  • javascript中this用法实例详解

}

this.style[ type ] = value;

function fun2() {

}

var local2 = "22";//本地作用域2

var one = document.getElementByIdx( 'one' );

for (var i=0;i<100;i++) {

changeStyle.apply( one , ['fontSize' , '100px' ]);

//本地作用域2

changeStyle('fontSize' , '300px'); //出现错误,原因同示例三

}

apply的用法和call大致相同,只有一点区别,apply只接受两个参数,第一个参数和call相同,第二个参数必须是一个数组,数组中的元素对应的就是函数的形参。

}

无意义(诡异)的this用处

 

示例五:

不象Java语言那样for循环也是一个作用域,在Javascript中本地作用域是按照函数来区分的。Javascript的作用域概念类似词法作用域。
词法作用域:也叫做静态作用域,变量的作用域是在定义时决定而不是执行时决定。即词法作用域取决于源码,通过静态分析就能确定。

复制代码 代码如下:

作用域链

var obj = {

与“原型链”类似,Javascript的作用域链也是按有顺序查询的。在访问变量时,先查看本地作用域是否有此变量,如果没有则依次向上一级作用域查找直到全局作用域。如果全局作用域也没有此变量,那么将会在全局作用域中声明这个变量。如下的代码:

x : 100,

 代码如下

y : function(){

复制代码

setTimeout(

function f() {

function(){ alert(this.x); } //这里的this指向的是window对象,并不是我们期待的obj,所以会弹出undefined

name = "global";

, 2000);

var local = "local";

}

}

};

f();

obj.y();

console.log(name); //global

如何达到预期的效果

console.log(local);//undefine

复制代码 代码如下:

name变量被声明在全局作用域。

var obj = {

上下文

x : 100,

又可以理解为上下文对象,表示当前代码执行时所处的环境。即是this变量所指代的对象;这么理解比较困难,直接看个例子:

y : function(){

 代码如下

var that = this;

复制代码

setTimeout(

function Test() {

function(){ alert(that.x); }

console.log(this);

, 2000);

}

}

Test(); //window

};

new Test();//Object

obj.y(); //弹出100

在执行Test()时,此时的上下文对象是window,即Javascript的全局对象!在执行new Test();时新建了一个Object,此时执行Test函数的上下文对象就是Object。如果还不理解,可以看我的如何用Javascript实现面向对象编程一文中有一段代码如下:

事件监听函数中的this

 代码如下

复制代码 代码如下:

复制代码

var one = document.getElementByIdx( 'one' );

function newObj(Fun,arguments) {

one.onclick = function(){

var o = {};

alert( this.innerHTML ); //this指向的是one元素,这点十分简单..

if (Fun && typeof Fun === "function") {

};

o.__proto__ = Fun.prototype;

注意:js中的全局变量都会动态添加到Window 的实例 window,作为其属性。

Fun.apply(o, arguments);

this是js的一个关键字,随着函数使用场合不同,this的值会发生变化。但是总有一个原则,那就是this指的是调用函数的那个对象。

return o;

1、纯粹函数调用。

}

复制代码 代码如下:

}

function test() {
this.x = 1;
alert(x);
}
test();

 

其实这里的this就是全局变量。看下面的例子就能很好的理解其实this就是全局对象Global。

这主要是new函数操作的模拟,可以看到Fun.apply(o,arguments);这一步,apply的作用是指定执行Fun函数并制定其上下文为o,输入参数为arguments对象。所以new Test()得到的结果是Object。

复制代码 代码如下:

闭包

var x = 1;
function test() {
alert(this.x);
}
test();//1

表示能访问和操作其他内部作用域的变量的表达式(通常是函数)。用简单的语言描述就是:能操作其他本地作用域变量的函数就是闭包。还是看代码:

var x = 1;
function test() {
this.x = 0;
}
test();
alert(x);//0

 代码如下

2、作为方法调用,那么this就是指这个上级对象。

复制代码

复制代码 代码如下:

function fun() {

function test() {
alert(this.x);
}

var i = 1;

var o = {};
o.x = 1;
o.m = test;
o.m(); //1

return function() {

3、作为构造函数调用。所谓构造函数,就是生成一个新的对象。这时,这个this就是指这个对象。

i++;

复制代码 代码如下:

console.log(i);

function test() {
this.x = 1;
}
var o = new test();
alert(o.x);//1

}

4、apply调用

}

this指向的是apply中的第一个参数。

var closure = fun();

复制代码 代码如下:

closure(); //2

var x = 0;
function test() {
alert(this.x);
}

closure(); //3

var o = {};
o.x = 1;
o.m = test;
o.m.apply(); //0
o.m.apply(o);//1

请先按Java语言或其他非闭包语言的逻辑思考。当fun函数执行完毕时,其内部变量i应该会被释放,当closure函数再此执行并调用i时输出错误(因为i未被声明)。但是在Javascript中却打印出了值,这一切都归功于闭包。在执行fun()函数时,闭包就被创建。此时i并没有被释放,closure依然可以被访问到。

当apply没有参数时,表示为全局对象。所以值为0。

另外注意闭包的本质是表达式(通常是函数),所以闭包是在函数生成时定义的。(上面代码的第3行定义闭包)!

您可能感兴趣的文章:

  • js中的this关键字详解
  • javascript this用法小结
  • javascript中this的四种用法
  • 改变javascript函数内部this指针指向的三种方法
  • JS中改变this指向的方法(call和apply、bind)
  • JS函数this的用法实例分析
  • Javascript对象中关于setTimeout和setInterval的this介绍
  • Javascript this指针
  • js原生态函数中使用jQuery中的 $(this)无效的解决方法
  • this,this,再次讨论javascript中的this,超全面(经典)
  • JavaScript中this关键字用法实例分析

闭包的作用

闭包最大的作用就是来阻止外部程序随意访问内部变量,只能通过提供的接口来访问和操作。如下面一个记数器的实现:

 代码如下

复制代码

var counter = (function() {

var i=0;

return {

add:function() {

i++;

return this;

},

get:function() {

return i;

}

}

})();

counter.add().add().add();

console.log(counter.get()); //3

如果不用闭包直接暴露变量,那就会出现如下的情况产生bug:

 代码如下

复制代码

i=0;

function add() {

i++;

}

add();

add();

i+="1";

add();

console.log(i);//22

至于为什么产生这么奇怪的结果就要归功与+=和++这两个操作符了。

举一个简单的例子:

 代码如下

复制代码

function test(){

 

alert(this);

 

}

 

var obj=function(){

 

var name='testObj';

 

}

 

obj.objTest=test;

 

test();

 

obj.objTest();

把这段代码放到HTML中运行这个页面,你会看到首先提示一个警告[object window],然后第二个警告

 

 代码如下

复制代码

var obj=function(){

 

var name='testObj';

 

}

我们先定义了一个test()方法,并在方法内部调用alert()方法将this显示出来,然后定义了一个obj函数对象,并给它加了一个私有的字段name,同时给它加了一个静态的方法objTest(),而这个函数则直接指向test()函数。

分别调用test()和obj.objTest()方法,第一次警告框提示的是Window对象,而第二次提示的是我们定义的obj这个函数的代码。这说明了test函数在两次执行的时候this的值是不同的!

这就说明了当调用函数的对象不同的时候,其内部的this关键字指代的对象是不同的。这里需要值得注意的是Javascript是基于对象的语言,当我们的变量或者函数定义在<script></script>标签的根下的时候其实相当于给window对象加了相应的属性或方法,所以当我们利用function test(){}代码定义一个函数的时候,其实相当于给window对象添加了一个新的函数,即window.test()函数。
我们可以做一个实验:

 

 代码如下

复制代码

function test(){

 

alert(this);

 

}

 

alert(test===window.test);

警告框提示的将是true,这说明当我们在调用test()这个函数时相当于调用的是window.test()。所以当我们调用test()函数的时候调用这个函数的对象其实是window对象,this指代的是window对象,所以我们在alert(this)的时候弹出的警告窗口内容是[object Window]。我们将obj.objTest=test相当于把obj.objTest()指向test(),所以当我们调用obj.objTest()函数时相当于在obj调用了test()这个函数,所以现在this指代的是obj对象,提示的就是obj这个Function也就是我们看到的代码。

说到这应该也解释的差不多了,可能上面的例子太抽象,想象不出来它能在什么情况下用到,那我们现在就假设一个需求,做一个贴近实用一点的例子。
假设我们现在页面中的所有超链接在点击之后颜色要改为红色,用Javascript实现。大体的思路应该是获取页面中所有的<a>标签,然后遍历所有的<a>标签,给每一个注册一个click事件,事件触发后我们将它的color值设为red。
示例代码如下:

 代码如下

复制代码

 

function changeColor(){

 

this.style.color='#f00';

 

}

 

//初始化,给所有 a 标签注册事件

 

function init(){

 

var customLinks=document.getElementsByTagName('a');

 

for(i in customLinks){

 

//你也可以使用事件侦听器方式来注册事件

 

//由于要兼容IE,FF等浏览器可能需要更多代码,您可以自行编写

 

customLinks[i].onclick=changeColor;

 

}

 

}

 

window.onload=init;

将这段代码添加到HTML文档中,并在文档中添加一些超链接,当超链接点击后颜色会变成红色,这里我们定义的changeColor()函数中this关键字在点击超链接触发函数的时候它指代的是当前这个超链接。而如果你直接调用changeColor()函数浏览器会报错,提示Error: ‘this.style’ is null or not an object或者undefined之类的错误。

不知道说到这能不能让正在看文章的你对Javascript中的this关键字有了一些自己的了解呢?或者你已经不耐烦了?(:P)

其实要想真正对这个问题有更深入的理解那么必须对Javascript的作用域和作用域链有深入的理解。

作用域,顾名思义就是指某一属性或方法具有访问权限的代码空间,简单的说也就是这个变量或方法它在代码中的的适用范围。在大多数的OOP中主要有public,private,protect三种作用域,对着三种作用域在这里就不详细解释了,如果有OOP的经验应该都有深入的了解。在这里我要说的是这三种作用域类型对Javascript来说几乎是毫无意义的,因为Javascript中只有一种公共作用域,在Javascript中作用域是在函数中进行维护的。举个例子:

 代码如下

复制代码

var test1='globle variable';

 

function example(){

 

var test2='example variable';

 

alert(test1);

 

alert(test2);

 

}

 

example();

 

alert(test1);

 

alert(test2);

 

根据我们前面解释的,这里的test1变量相当于window的一个属性,所以它会在整个window作用域内起作用,而test2则在example()函数的内部声明,所以它的作用域也就维持在example()方法的内部,如果在函数的外部调用test2浏览器会提示出错。而在example()内部调用test1则没问题。
根据这个我们再举一个例子:

 代码如下

复制代码

var test='globle variable';

 

function example(){

 

var test='example variable';

 

}

 

example();

 

alert(test);

 

这个例子运行会是什么结果呢?对,警告框会提示“globle variable”,因为example()函数内部的test变量其作用域只维持在内部,不会影响外部的test变量。如果我们将example()内部test变量的var关键字去掉呢?你可以自己试试。

说到这就有牵扯出另外一个概念,那就是作用域链的概念。作用域链就是可以确定变量值的路径。由上面一个例子可以看出,var关键字是用来维护作用域链的,如果变量使用了var关键字声明那么他就可以看作为作用域链的终点。同样函数的形参的定义也会起到类似的作用。

说到这你对this这个精灵古怪的家伙有了比较清晰的认识了吧?根据它简单的一个诠释,this总是指向调用它所在函数的对象,根据作用域和作用域链,我们会很清晰的确定this的真面目。临末尾再来一个开始那个例子的简单变化:

   

 代码如下

复制代码

  function test(){

 

alert(this);

 

}

 

var obj=function(){

 

var name='testObj';

 

}

 

obj.objTest=test;

 

obj.objTest2=function(){

 

test();

 

}

 

test();

 

obj.objTest();

 

obj.objTest2();

 

你猜会提示什么内容呢?你可以运行一下试试(:P);

既然this是根据调用其所在函数的对象的改变而改变的,那我们可不可以强制改变它的调用对象呢?答案是肯定的,以后的文章会介绍一下这部分内容,以及Javascript中不同类型的数据成员的实现方式,闭包等概念。

一个面试题以它来详细...

本文由美高梅网址发布于关于美高梅,转载请注明出处:js作用域使用方法说明,深入理解Javascript中this的

上一篇:js判断是否为空和typeof的用法,使用typeof判断fu 下一篇:没有了
猜你喜欢
热门排行
精彩图文