JavaScript——this关键字
请看下面的代码,最后alert出来的是什么呢?

1 var name = "Bob";
2 var nameObj ={
3 name : "Tom",
4 showName : function(){
5 alert(this.name);
6 },
7 waitShowName : function(){
8 setTimeout(this.showName, 1000);
9 }
10 };
11
12 nameObj.waitShowName();

要解决这个问题我们需要了解Javascript的this关键字的用法。
this指向哪里?
一般而言,在Javascript中,this指向函数执行时的当前对象。
In JavaScript, as in most object-oriented programming languages,
thisis a special keyword that is used within methods to refer to the object on which a method is being invoked.
值得注意,该关键字在Javascript中和执行环境,而非声明环境有关。
The this keyword is relative to the execution context, not the declaration context.
我们举个例子来说明这个问题:

var someone = {
name: "Bob",
showName: function(){
alert(this.name);
}
};
var other = {
name: "Tom",
showName: someone.showName
}
other.showName(); //Tom

this关键字虽然是在someone.showName中声明的,但运行的时候是other.showName,所以this指向other.showName函数的当前对象,即other,故最后alert出来的是other.name。
没有明确的当前对象时
当没有明确的执行时的当前对象时,this指向全局对象window。
By default,
thisrefers to the global object.为什么说是全局对象(the global object),因为非浏览器情况下(例如:nodejs)中全局变量并非window对象,而就是叫“全局变量”(the global object)。不过由于我们这片文章主要讨论的是前端开发知识,所以nodejs就被我们忽略了。
例如对于全局变量引用的函数上我们有:

var name = "Tom";
var Bob = {
name: "Bob",
show: function(){
alert(this.name);
}
}
var show = Bob.show;
show(); //Tom

你可能也能理解成show是window对象下的方法,所以执行时的当前对象时window。但局部变量引用的函数上,却无法这么解释:

var name = "window";
var Bob = {
name: "Bob",
showName: function(){
alert(this.name);
}
};
var Tom = {
name: "Tom",
showName: function(){
var fun = Bob.showName;
fun();
}
};
Tom.showName(); //window

setTimeout、setInterval和匿名函数
文章开头的问题的答案是Bob。
在浏览器中setTimeout、setInterval和匿名函数执行时的当前对象是全局对象window,这条我们可以看成是上一条的一个特殊情况。
所以在运行this.showName的时候,this指向了window,所以最后显示了window.name。
浏览器中全局变量可以当成是window对象下的变量,例如全局变量a,可以用window.a来引用。
我们将代码改成匿名函数可能更好理解一些:

var name = "Bob";
var nameObj ={
name : "Tom",
showName : function(){
alert(this.name);
},
waitShowName : function(){
function(__callback){
__callback();
}(this.showName);
}
}; nameObj.waitShowName(); //Bob

在调用nameObj.waitShowName时候,我们运行了一个匿名函数,将nameObj.showName作为回调函数传进这个匿名函数,然后匿名函数运行时,运行这个回调函数。由于匿名函数的当前对象是window,所以当在该匿名函数中运行回调函数时,回调函数的this指向了window,所以alert出来window.name。
由此看来setTimeout可以看做是一个延迟执行的:
function(__callback){
__callback();
}
setInterval也如此类比。
但如果我们的确想得到的回答是Tom呢?通过一些技巧,我们能够得到想要的答案:

var name = "Bob";
var nameObj ={
name : "Tom",
showName : function(){
alert(this.name);
},
waitShowName : function(){
var that = this;
setTimeout(function(){
that.showName();
}, 1000);
}
}; nameObj.waitShowName(); //Tom

在执行nameObj.waitShowName函数时,我们先对其this赋给变量that(这是为了避免setTimeout中的匿名函数运行时,匿名函数中的this指向window),然后延迟运行匿名函数,执行that.showName,即nameObj.showName,所以alert出正确结果Tom。
eval
对于eval函数,其执行时候似乎没有指定当前对象,但实际上其this并非指向window,因为该函数执行时的作用域是当前作用域,即等同于在该行将里面的代码填进去。下面的例子说明了这个问题:

var name = "window";
var Bob = {
name: "Bob",
showName: function(){
eval("alert(this.name)");
}
};
Bob.showName(); //Bob

apply和call
apply和call能够强制改变函数执行时的当前对象,让this指向其他对象。因为apply和call较为类似,所以我们以apply为例:

var name = "window";
var someone = {
name: "Bob",
showName: function(){
alert(this.name);
}
};
var other = {
name: "Tom"
};
someone.showName.apply(); //window
someone.showName.apply(other); //Tom

apply用于改变函数执行时的当前对象,当无参数时,当前对象为window,有参数时当前对象为该参数。于是这个例子Bob成功偷走了Tom的名字。
new关键字
new关键字后的构造函数中的this指向用该构造函数构造出来的新对象:

function Person(__name){
this.name = __name; //这个this指向用该构造函数构造的新对象,这个例子是Bob对象
}
Person.prototype.show = function(){
alert(this.name);
}
var Bob = new Person("Bob");
Bob.show(); //Bob

思考题
1. 请问下面代码会alert出什么,为什么?

var name = "Bob";
var nameObj ={
name : "Tom",
showName : function(){
alert(this.name);
},
waitShowName : function(){
var that = this;
setTimeout("that.showName();", 1000);
}
}; nameObj.waitShowName();

2. 请问下面代码会alert出什么,为什么?
var fun = new Function("alert(this)");
fun();
3. 下面代码分别在IE和其他浏览器上运行有什么差异,可以用什么方法解决这个差异问题?
IE:

<button id = "box" name = "box">Click Me!</button> <script>
var name = "window"; function showName(){
alert(this.name);
} document.getElementById("box").attachEvent("onclick", showName);
</script>

Others:

<button id = "box" name = "box">Click Me!</button> <script>
var name = "window"; function showName(){
alert(this.name);
} document.getElementById("box").addEventListener("click", showName, false);
</script>
判别this指针的指导性原则
在Javascript里面,this指针代表的是执行当前代码的对象的所有者。
JavaScript——this关键字的更多相关文章
- javascript this关键字指向详解
在之前写代码的经历中,常常试过写着写着this就莫名其妙的不知道指向到哪里去了.今天看了曾探的javascript设计模式,里面特别谈到了this在不同情况下指代的对象,非常有意思. this指代的情 ...
- JavaScript 保留关键字
JavaScript 保留关键字 在 JavaScript 中,一些标识符是保留关键字,不能用作变量名或函数名. JavaScript 标准 所有的现代浏览器完全支持 ECMAScript 3(ES3 ...
- JavaScript保留关键字(全)
JavaScript 标准 所有的现代浏览器已经完全支持 ES5(ECMAScript 5). JavaScript 保留关键字(keyword) Javascript 的保留关键字(标识符)不可以用 ...
- JavaScript var关键字、变量的状态、异常处理、命名规范等介绍
本篇主要介绍var关键字.变量的undefined和null状态.异常处理.命名规范. 目录 1. var 关键字:介绍var关键字的使用. 2. 变量的状态:介绍变量的未定义.已定义未赋值.已定义已 ...
- javascript保留关键字
1.通用保留关键字 break delete function return typeof case do if switch var catch else in this void continue ...
- Javascript this 关键字
Javascript 的 this 关键字总是指向当前被执行函数的所有者. 换句话说,如果当前函数可以视为某个对象的一个方法,那么 this 就指向该对象. 例如有这么一个函数 doSomething ...
- JavaScript搜索关键字高亮的实现
高亮功能主要是指对页面中指定区域的指定文字进行高亮显示,也就是背景着色.一般在搜索结果页面会经常用到这个功能. 下面就为大家提供一种解决方案,用javascript实现. 首先在<head> ...
- 跟着9张思维导图学习Javascript js 关键字和保留字 css3中的BFC,IFC,GFC和FFC
跟着9张思维导图学习Javascript 学习的道路就是要不断的总结归纳,好记性不如烂笔头,so,下面将 po 出我收集的 9 张 javascript 相关的思维导图(非原创). 思维导图小ti ...
- javaScript的关键字与保留字
JavaScript 关键字: break case catch continue default delete do else finally for function if in instance ...
随机推荐
- winform只能有一个实例运行且打开已运行窗口
static class Program { private static Mutex onlyOne; [STAThread] static void Main() { onlyOne = new ...
- oracle 11g express 修改oem端口
begin dbms_xdb.sethttpport('8081'); dbms_xdb.setftpport('0'); end; / 这样就把端口设置为8081了.
- zabbix特性
在知道zabbix是什么之后,我们最关心的是zabbix有什么特性,了解特性之后,我们才能决定是否会使用zabbix,以及zabbix是否适合我们. 概述 Zabbix是一个高度集成的网络监控套件,通 ...
- 解决label点击事件触发两次问题
问题描述: 通常,为了用户体验,我们点击单选框或者复选框后面文字,即可选中当前项.代码如下: <label> <input type="radio" name=& ...
- 删除多个Safari书签
Safari 的书签多了,删除起来很麻烦,可以先选中所有书签,然后再按"Command+Delete",就可以全部删除了.
- 一款符合当前主流审美的Swing外观(Look and Feel)_测试版发布
[前言] 本文将展示的是一款J2SE平台Swing外观(Look and Feel)实现,目前给出的演示jar包仅供测试之用,主体工作已经完成,余下是兼容性测试和调整,附件中的演示jar包推荐运行于j ...
- [译]简单得不得了的教程-一步一步用 NODE.JS, EXPRESS, JADE, MONGODB 搭建一个网站
原文: http://cwbuecheler.com/web/tutorials/2013/node-express-mongo/ 原文的源代码在此 太多的教程教你些一个Hello, World!了, ...
- JLS(Third Edition) Chapter12 Execution
这一章详细说明在一个program执行时,发生的activities. 它根据JVM和组成program的类.接口.实例的生命周期 组织. 一个JVM从加载一个特定的类并调用它的main方法开始启 ...
- r8 - ASC 41(俄罗斯多校)
1 今天干的俄罗斯的一场多校,被虐哭啊,就做出两题. 2 3 4 5 6 7 Gym 100496D Data Mining 8 题目讲得是给你一串数字,然后给你i,p,表示从第i开始,对这串数离散话 ...
- Hadoop 之面试题
颜色区别: 蓝色:hive,橙色:Hbase.黑色hadoop 请简述hadoop怎样实现二级排序. 你认为用Java,Streaming,pipe 方式开发map/reduce,各有哪些优缺点: 6 ...