各种上下文中的this

开头闲扯几句。上篇写对象原型的文章获得了1K多的阅读和几条评论,心里还是蛮欣喜的。那种写出来然后有人跟你讨论的感觉很不错。

公告里已经有写,自己开这个博客以及为什么要写文章的原因就是为了能把自己所思所想以文字的形式表述出来。有时候自己以为理解了某个知识点,但是当你尝试着去给别人讲的时候却发现原来自己一直是半知半解而已,会用不代表理解,所以能够把一个知识点很全面又极尽清晰的写下来的时候才能发现自己还有哪些死角没有注意到还有哪些方面没有考虑到。很明显,一篇文章肯定会有各种的表述性错误,所以写下来的过程也是自己认识自己错误的过程。

共勉,成长。

下面试着总结下JavaScript中的this关键字。

还是按照概念相关性的顺序按照1234展开来讲。

1.this关键字在何处出现?

  this他只能出现在函数中。当然在全局作用域中是个例外,意思是this只可能在两种情境下出现,一个是在函数体内,另一个是在全局作用域。

2.this是什么?

  this是关键字,语言规范里规定他指向函数执行时的当前对象。它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。

3.this到底指向哪?

  首先明确this在JavaScript中和函数的执行环境而不是声明环境相关。

  第一条中已经说过,this只能出现在函数中和全局作用域中,全局作用域中this指向全局对象(全局对象在浏览器这个环境中指window)。

  如果this出现在函数中,那就要分情况来看this到底指向哪了。指向的依据就是函数的执行环境而不是声明环境。其实可以以一句话来概括就是this永远指向所在函数的所有者,当没有显示的所有者的时候,那么this指向全局对象。

4.各种情况下的this的具体指向?

  (1).全局作用域

console.log(this)

  直接在全局作用域中打印this,其指向为window。

  所以在全局作用域中this指向全局对象。

  (2).函数作为某个对象的成员方法调用

var name = "chirenmiao1";
var obj= {
    name: "chirenmiao2",
    getName: function () {
        console.log(this.name);
    }
}
obj.getName();//chirenmiao2

  

  在全局作用域中声明全局变量name,在obj对象中声明同时也声明一个name。当用对象obj调用他的成员方法getName的时候,this指向这个obj,因此打印出来的this.name为obj的name。

  所以函数作为某个对象的成员方法调用时this指向该对象。

  (3).函数作为函数直接使用

var name = "chirenmiao1";
var obj= {
    name: "chirenmiao2",
    getName: function () {
        console.log(this.name);
    }
}
var getName= obj.getName;
getName();   //chirenmiao1

  同样的还是上边的一段代码,只不过这次我们把getName这个函数直接执行,这时在函数执行的时候他没有明确的当前对象,所以默认这时this就指向了全局对象。

  所以函数作为函数直接使用时this指向全局对象。

  

function myFun() {
    console.log(this);
}
myFun();

  还有就是函数声明直接执行的时候,this也指向全局对象。

  其实上边三条就已经简单覆盖了this指向的所有情况,下面紧接着讲述一些稍微特殊的情况。

  (4).函数作为构造函数调用

var name = ‘chirenmiao1‘;
var Obj = function (x, y) {
    this.name = ‘chirenmiao2‘;
}
Obj.prototype.getName = function () {
    console.log(this.name);
}
var myObj = new Obj();
myObj.getName();//chirenmiao2

  函数作为构造函数调用时this指向用该构造函数构造出来的新对象。

  (5).setTimeout和setInterval以及匿名函数

var name = "chirenmiao1";
var obj = {
    name: "chirenmiao2",
    getName: function () {
        setTimeout(function () {
            console.log(this.name);
        }, 1000);
    },
};

obj.getName();//chirenmiao1

  这两个函数执行的时候第一个参数可以为一个匿名函数,也可以是一个声明好的函数引用,所以this指向也就是指这个匿名函数或者函数引用的this的指向。通过第一条已经知道匿名函数或者在全局作用域中声明的函数直接执行的时候,其中的this指向全局对象,所以在这里也一样,setTimeout和setInterval两者运行时,this指向全局对象。

  这个时候如果还想输出的是chirenmiao2,也就是this指向obj的话就需要做点手脚了。

var name = "chirenmiao1";
var obj = {
    name: "chirenmiao2",
    getName: function () {
        var self = this;
        setTimeout(function () {
            console.log(self.name);
        }, 1000);
    },
};

obj.getName();//chirenmiao2

  当然这样是改变不了this指向的,但是可以通过把this赋值给self,就实现了保存this指向的作用。

  紧接着是匿名函数。

(function () {
    console.log(this);
})()//window

  匿名函数中的this指向全局对象,因为他没有显示的所有者。

  (6)apply、call、bind

  这三个函数是函数对象的一个方法,他们的作用就是为了改变函数执行时候的this指向,具体用法如下:

  call:call(obj[,arg1][,arg2]);第一个参数为强制改变需要指向的对象,后边可选的是该函数的参数,如果不传obj的话默认为window。

  apply:apply(obj[,arr]);第一个参数为强制改变需要指向的对象,后边可选的是该参数集合的数组形式,如果不传obj的话默认为window。

  apply和call的作用和调用形式基本一致,不同的是call后面的参数与方法中是一一对应的,而apply的第二个参数是一个数组,数组中的元素是和方法中一一对应的,这就是两者最大的区别。两者都可以不传参数,此时默认改变指向的对象为全局对象。

  bind:bind的调用形式和call相同,但是他返回的是改变调用对象后的函数引用,所以还要再执行一次,也就是obj.fun().bind()()。

总结:this作为函数运行时,自动生成的一个内部对象,只能在函数内部使用。具体this指向谁,要看this的所有函数是谁调用的,具体情况可分为全局作用域、作为某对象的方法调用、直接执行、匿名函数直接执行、call、apply、bind强制改变调用对象等。

完!

祝愉快。

  

时间: 2024-12-13 06:35:08

各种上下文中的this的相关文章

曾在同文中学任教的中外人士若干

一些零碎的笔记,本不足以成为一文的,不过庶几有益于他人,姑录于此. 库思非(Carl Frederick Kupfer,1852-1925),德裔美国人.1881年作为美以美会传教士来华,担任九江同文书院校长.他于1885年将学校迁至南门附近,即学校现址.1888年后,他又赴镇江.南京等地做传教工作.1896年他在雪城大学获得博士学位.1901年,为纪念德裔卫理宗领袖南伟烈(William Nast),同文书院更名为南伟烈大学(William Nast College,中文中也称同文大学),库思

《Single Image Haze Removal Using Dark Channel Prior》一文中图像去雾算法的原理、实现、效果

本文完全转载:http://www.cnblogs.com/Imageshop/p/3281703.html,再次仅当学习交流使用.. <Single Image Haze Removal Using Dark Channel Prior>一文中图像去雾算法的原理.实现.效果(速度可实时) 本文算法合作联系QQ: 33184777, 非诚勿扰 邮件地址:   [email protected] 最新的效果见 :http://video.sina.com.cn/v/b/124538950-125

如何用python从文中获取文件名再用正则表达式批量修改文件名

第零步:问题的提出 我在网上购买了星火英语的六级晨读美文100篇(六级早已高分飘过,不过很喜欢这些文章,买来重新品味),但是发现其文章的命名都为01.txt或10.txt等.为了便于检索需要修改文件名称. 第一步:从文件中取出文件名. 我发现txt文件的第一行为文件名,格式为如:Passage 3. Three Passions I Have Lived for, 后面还有几个换行符.写下如下代码进行第一步修改: import os x = 1 while x < 101: if x < 10

当前上下文中不存在名称“ConfigurationManager”

Visual Studio调试出现错误:当前上下文中不存在名称“ConfigurationManager” 解决方法: 1.System.Configuration引用这个dll参考:http://keleyi.com/a/bjac/rh2ouu5w.htm 2.再引用此名称空间using System.Configuration;

【错误】ASP.net上下文中不存在XXX字段

最近在把网站改为web项目的时候,出现几百个错误,而且全是上下文不存在XXX字段的错误.在把web项目里的aspx项移动到其他的文件夹下时,也是出现几百个这种上下文中不存在XXX字段的错.开始以为是用了FineUI的问题,因为错误的字段全是FineUI控件的ID字段,把FineUI折腾了好久,最后发现其实跟FineUI一点关系都没有.问题定位多重要啊,还好很快走出了这个死胡同. 错误原因:在XXX.aspx , XXX.aspx.cs , xxx.designer.cs中命名空间不一致的原因 修

申论备考攻略:议论文中两大论证方法

考生在作答申论作文时,在明确主题和立意之后,下一步是紧扣文章立意展开论证.从文章评阅和平日批改情况看,许多考生无法恰当或综合运用议论文中常见的一些论证方式,所以导致写出的议论文说理不透,蜻蜓点水,观点模糊不清. 下面给考生们介绍两种在议论文写作时常用的较为好用的论证方法. 第一,例证法 也被称为事例论证,是通过令人信服的经典案例证明自身论点正确的一种方法.是议论文写作中最为常见的一种论证方式."事实胜于雄辩",在典型的事例面前,所要阐述的道理自然就不言而喻了. 要充分利用例证法,考生们

ERROR无法从静态上下文中引用非静态变量

ERROR无法从静态上下文中引用非静态变量 2012-06-16 20:58:52 分类: Java 什么是“static”? 学习过java.C++或C的人都应该认识这个关键字.用这个关键字修饰的变量叫做静态变量,有其特殊的作用.在java中static也用来修饰静态方法和静态内部类. 静态变量的特点: (1)生存周期:静态局部变量的生存周期也是整个源程序.当定义整个变量的函数结束时,整个变量并没有消失,他始终是存在的. (2)作用域:作用域与自动变量是一样的,只能在定义其的子函数中使用,当退

报错!无法从静态上下文中引用非静态 变量

1 import java.awt.Point; 2 class rectangle 3 { int x1=0; 4 int y1=0; 5 int x2=0; 6 int y2=0; 7 8 rectangle point(int x,int y,int z,int w) 9 {x1= x; 10 y1= y; 11 x2= z; 12 y2= w; 13 return this; 14 } 15 16 public static void main(String[] args) 17 18

jQuery -&gt; 获取指定上下文中的DOM元素

作者 : 卿笃军 一个String对象的长度是固定的,不能改变它的内容,或者是附加新的字符至String对象中.您也许会使用+来串联字符串以达到附加新字符或字符串 的目的,但+会产生一个新的String实例.如果程序对这种附加字符串的需求很频繁,并不建议使用+来进行字符串的串联.在面向对象程序设计中,最好是 能重复运用已生成的对象,对象的生成需要内存空间与时间,不断地产生String实例是一个没有效率的行为.J2SE 5.0提供java.lang.StringBuilder类,使用这个类所产生的

请求在此上下文中不可用

项目环境:ASP.NET MVC 4 部属环境:WIN2008 X64 IIS7 异常详细信息: System.Web.HttpException: 请求在此上下文中不可用 解决方案一: 把Response.Request.Session写全: System.Web.HttpContext.Current.Response System.Web.HttpContext.Current.Request System.Web.HttpContext.Current.Session 解决方案二: Ap