【第22期】观点:IT 行业加班,到底有没有价值?

JS篇——javascript中的this

原创 2016年06月02日 14:55:00

  一直以来貌似都还没有更新js篇,本来是打算将css3和html5更新完之后再从头总结js,最后发现开始那些好像也没啥总结的,而且我这速度还不知道何时能把css3和html5总结完,所以就想到哪就更哪了,本来今天准备更新闭包,然后发现更新闭包之前,我最好先更新下js中的this关键字,所以这一篇更新js中的this关键字。

javascript中的this

在java中,this固定指向运行时的当前对象。但在javascript中,this的含义要多的多,它可以是全局对象、当前对象或者任意对象,完全取决于函数调用的方式。

this究竟指向哪里

一句话,javascript中的this指向的是执行时的当前对象,而不是声明时的当前对象。这句话什么意思,看下面例子。

var x=1;
var test= {  
      x: 2,  
      show : function(){  
          alert(this.x);  
      } 
 };  
 var obj = test.show;
 obj();//1

上面这个例子最后弹出的是全局变量1,虽然this是在test.show里面声明的,但是执行的时候的对象却不是test,所以this不是指向的test对象,这是为啥呢,后面再说。

Javascript一共有四种调用模式:对象方法调用模式、纯函数调用模式、构造器调用模式以及apply调用模式。调用模式不同,对应的隐藏参数this值也会不同。

对象方法调用模式

函数作为对象的属性时,称为方法。此时函数(即方法)中的this对应是该对象。

var x=1;
var test= {  
      x: 2,  
      show : function(){  
          alert(this.x);  
   } 
 };  
 test.show();//2
弹出2,此刻运行的是test对象的show属性,所以this指向test对象,所以当前对象是test对象。

然而,还有另外一种情况的方法调用,就是“this究竟指向哪里”中的例子。

var x=1;
var test= {  
      x: 2,  
      show : function(){  
          alert(this.x);  
      } 
 };  
 var obj = test.show;
 obj();//1
此时弹出的是1,此刻并不是调用了test这个对象的show属性,而是将test.show这个函数赋值给obj,又因为该函数是一个匿名函数,本身是没有对象的,所以show方法里的this就没有对象,没有对象就是window,window.x就是全局变量1。
谈到这里就顺便说一下setTimeout、setInterval和匿名函数中的“this”.

在浏览器中setTimeout、setInterval和匿名函数执行时的当前对象是全局对象window,浏览器中全局变量可以当成是window对象下的变量,例如:全局变量a,可以用window.a来引用。

var x=1;
 var test= {  
      x: 2,  
      show : function(){  
          alert(this.x);  
      },
      other:function(){
      	setTimeout(function(){
             alert(this.x);
      	}, 1000);
      }
    };  
test.other();//1
弹出1,这是因为setTimeout中的匿名函数运行时,匿名函数中的this指向window,所以window.x弹出1。setInterval与setTimeout类似。

怎样可以让上面例子弹出2呢?

var x=1;
var test= {  
      x: 2,  
      show : function(){  
          alert(this.x);  
      },
      other:function(){
      	var that = this;
      	setTimeout(function(){
             alert(that.x);
      	}, 1000);
      }
    };  
test.other();//2

弹出2,这是因为在setTimeout中的匿名函数运行前,this指定的当前对象是test(这时运行的test对象的other属性),现将test对象赋值给that,setTimeout中的匿名函数运行后,改变的是this指定的对象,与that无关,that仍指定test对象。

这里再说一下setTimeout(函数名,延迟),setTimeout(匿名函数,延迟),setTimeout(字符串,延迟)这三的区别。以下面例子为例:

var x=1;
var test= {  
      x: 2,  
      show : function(){  
          alert(this.x);  
      } 
 };
setTimeout(函数名,延迟)(比如setTimeout(test.show(),1000))

test.show()是函数运行,这种传递方式真正传进去的是test.show()函数的返回值。如果是setInterval(test.show(),1000)这种方式只会执行test.show()一次,因为test.show()已经执行了,和setTimeout、setInterval其实没有关系

setTimeout(匿名函数,延迟)(比如setTimeout(test.show,1000))

这个相当于一个延时执行,传入了一个匿名函数,此时this变量是全局变量window,但是注意,它是没有传入函数参数的,如果函数有参数的话,建议使用闭包或者使用setTimeout(字符串,延迟)

setTimeout(字符串,延迟)比如setTimeout("test.show()",1000))

这个也相当于一个延时执行,用字符串代码创建了一个新的函数,因此该函数没有明确的对象,所以this指向全局变量。

var x = 1;  
var obj ={  
    x : 2,  
    show : function(){  
        alert(this.x);  
    },  
    other : function(){
        var that = this;
        setTimeout("that.show();", 1000);
    }
}; 
 
obj.other();//报错
纯函数调用模式

这种很简单,此时this就代表全局对象,即window。

function show(){
	this.x = 2;
	alert(this.x);
}
show();//2
var x = 1;
function show(){
	alert(this.x);
}
show();//1
var x = 1;
function show(){
	this.x = 2;
}
show();
alert(this.x);//2
构造器调用模式
构造器,就是生成一个新对象,这时,这个this就指这个新对象。

var x=1;
function show(){
	x=2;
	alert(x);
	alert(this.x);
	var x;
	alert(this.x);
	alert(x);
}
show();
上面弹出的结果是2,1,1,2

这就是上面说的那种情况,纯函数调用模式,这里的this对象就是全局对象window.

var x=1;
function show(){
	x=2;
	alert(x);
	alert(this.x);
	var x;
	alert(this.x);
	alert(x);
}
var test = new show();
test();
上面弹出的是2,undefined,undefined,2

这里的this对象就是new新创建的对象,新创建的对象里面并没有定义this.a,所以this.a为undefined。

apply调用模式

apply()是函数对象的一个方法,它的作用是改变函数的调用对象,它的第一个参数就表示改变后的调用这个函数的对象,因此,this指的就是这第一个参数。
call的用法和apply大致相同,只有一点区别,apply只接受两个参数,第一个参数和call相同,第二个参数必须是一个数组,数组中的元素对应的就是函数的形参。所以这里只主要讲一个apply。

var x=1;
function show(a){
	this.x = this.x+a;
	alert(this.x);
}
var obj = {
	x:0
};
show.apply();//NaN,apply()的参数为空时,默认调用全局对象,所以this.x为1,但此时show函数的参数中没有定义a,因此a为undefined,所以结果为NaN
show.apply(obj,[3]);//3,此时this对象为obj对象,所以this.x为0。0+3等于3。
show.call(obj,4);//7,此时this对象是obj对象,但因为上一步,所以现在obj中的x为3,3+4等于7





版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

学习JavaScript 的必备 (一),让您对js的 function, javascript内置对象,this概念及之间的关系不再迷惑。(希望能置为推荐篇,为更多的js初学者关注)

-------------------该文摘自于匿名教程总结,希望对初学js的同学有帮助,因为它解决了我学习js的众多迷惑。。。 函数是进行模块化程序设计的基础,编写复杂的Ajax应用程序,必须对函数...

使用闭包构造模块(优化篇)——Object-Oriented Javascript之四

    上一篇博客(使用闭包构造模块(基础篇)——Object-Oriented Javascript之三)介绍了闭包构造模块的基础知识,这一篇着重介绍“优化”。这里“优化”指的是性能、可维护性。你可以不依照这篇文章推荐的实践方法,也可以写出具备相当功能的程序,但是程
  • lazy_
  • lazy_
  • 2013-02-04 15:41
  • 1852

JavaScript-读 You Dont Know JS,this到底是什么

You Dont Know JS一系列书不错。这一系列博客是我读这本书以后总结的干货。这篇博客讲解为什么使用this,以及如何确定一次函数调用的this到底是哪个对象。

Javascript学习笔记

一. 基础篇 Javascript学习笔记1——数据类型 在Javascript中只有五种简单类型,分别为null,undefined,boolean,String和Number.一种复杂类型:object。 代码类型只有一种形式就是function。 undefined:未定义,我们也可称之为不存在,typeof(undefined)=undefined. null:为空。undefined是不存在,而null是存在,但却无。typeof(null)=object,但null又不是object,这就是null的神奇而独特之处。 boolean:true or false。 Nu

轻松拿下JavaScript(四)——对象字面量,this,call()和apply()方法,JS的异常处理

我们今天这讲主要讲解JavaScript的面向对象的几个内容:对象字面量,this,this,call()和apply()方法,Js的异常处理。 对象字面量: 1、我们之前看到的例子都是使...
  • yi_zz
  • yi_zz
  • 2012-11-25 12:19
  • 8149
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)