对于this的理解,大部分时间都比较模糊,最近几天做了一些研究,记录一下

首先应该明白,this是执行上下文的一个属性,它的值取决于执行上下文,执行上下文和函数调用方式相关,定义一个function的时候会激活一个上下文,关于上下文的介绍,参考《对javascript执行上下文的理解》一文。

this的几种使用场景:

一 、全局代码中的this

在全局的上下文中,this始终是全局对象本身,看代码:

this.a = 10;
alert(window.a);// b = 20;
alert(this.b);// var c = 30;
alert(this.c);//

二、function中的this

要彻底理解function,应该明白this的赋值原理,讲this赋值之前,先来看一下javascript的引用类型(reference type), 引用类型的值可以看作一个对象,包含两个属性,propertyName 标识属性的值,base标识该属性的拥有者,

{

  base : <base object>,

  propertyName : <property name>
}

javascript处理引用类型的值只可能有两种情况:① 处理一个标识符 ②属性访问符

先看标识符,把标识符处理成引用类型包含 声明变量,函数名,形参和全局对象中未识别的属性名

如下

var foo = 10;
function bar(){}

操作的中间结果中,引用类型的值分别被处理成如下所示:

var fooReference = {
base: global,
propertyName: 'foo'
}; var barReference = {
base: global,
propertyName: 'bar'
};

属性访问器都应该熟悉。它有两种变体:点(.)语法(此时属性名是正确的标示符,且事先知道),或括号语法([])

var foo = {
bar : function(){}
}
foo.bar();
foo['bar']();

在中间计算的返回值中,我们有了引用类型的值。

var fooBarReference = {
base: foo,
propertyName: 'bar'
};

那么引用类型和this的赋值有什么关系呢,在javascript中,一个函数上下文中确定this值的通用规则如下:

在一个函数上下文中,this由调用者提供,由调用函数的方式来决定。如果调用括号()的左边是引用类型的值,this将设为引用类型值的base对象(base object),在其他情况下(与引用类型不同的任何其它属性),这个值为null。不过,实际不存在this的值为null的情况,因为当this的值为null的时候,其值会被隐式转换为全局对象。

#demo1

function foo(){
alert(this);
}
foo();//this-> global

上面提到,标识符包含函数名,即foo被当成引用类型的值来处理,处理过程中值为

var fooBarReference = {
base: global,
propertyName: 'foo'
};

所以执行上下文中的this被赋值为global

#demo2

var foo = {
bar : function(){
alert(this);
}
}
foo.bar();//this->foo

demo2中方法调用属于属性访问器的方式,base被置为foo

#demo3 看一个调用方式,

var name ="i am from window";
var foo = {
name : "i am in foo",
getName : function(){
alert(this.name);
}
}
var bar = foo.getName;
bar();//i am from window foo.getName();//i am in foo

bar属于标识符,解析成引用类型的值后base为global,foo.getName属性访问器访问方式调用方法,base 为foo,为什么用表达式的不同形式激活同一个函数会不同的this值,答案在于引用类型(type Reference)不同的中间值

三、函数调用和非引用类型

当调用括号的左边不是引用类型而是其它类型,这个值自动设置为null,结果为全局对象

(function () {
alert(this); // null => global
})();

在这个例子中,我们有一个函数对象但不是引用类型的对象(它不是标示符,也不是属性访问器),相应地,this值最终设为全局对象。

四、引用类型和this为null

有一种情况是这样的:当调用表达式限定了call括号左边的引用类型的值, 尽管this被设定为null,但结果被隐式转化成global。当引用类型值的base对象是被活动对象时,这种情况就会出现。

下面的实例中,内部函数被父函数调用,此时我们就能够看到上面说的那种特殊情况。

function foo() {
function bar() {
alert(this); // global
}
bar(); // the same as AO.bar()
}

活动对象总是作为this返回,值为null——(即伪代码的AO.bar()相当于null.bar())。这里我们再次回到上面描述的例子,this设置为全局对象。

五、构造方法中的this

构造方法中的this比较简单,

function Foo(){
this.a = 'inner';
this.getA = function(){
alert(this.a);
}
} var f1 = new Foo();
f1.a;// inner
f1.getA();//inner

new Foo()执行的时候,首先先创建一个空对象{},然后把对象作为this传入到构造方法Foo()中执行初始化操作,然后把标识符f1指向该对象。

六、调用函数中手动修改this

在函数原型中定义的两个方法(因此所有的函数都可以访问它)允许去手动设置函数调用的this值。它们是.apply和.call方法。他们用接受的第一个参数作为this值,this 在调用的作用域中使用。这两个方法的区别很小,对于.apply,第二个参数必须是数组(或者是类似数组的对象,如arguments,反过来,.call能接受任何参数。两个方法必须的参数是第一个——this。

var b = 10;

function a(c) {
alert(this.b);
alert(c);
} a(20); // this === global, this.b == 10, c == 20 a.call({b: 20}, 30); // this === {b: 20}, this.b == 20, c == 30
a.apply({b: 30}, [40]) // this === {b: 30}, this.b == 30, c == 40

对javascript this的理解的更多相关文章

  1. javascript单例模式的理解

    javascript单例模式的理解 阅读目录 理解单例模式 使用代理实现单例模式 理解惰性单例 编写通用的惰性单例 单例模式使用场景 回到顶部 理解单例模式 单例模式的含义是: 保证一个类只有一个实例 ...

  2. JavaScript面向对象的理解

    JavaScript面向对象的理解  笔记链接: http://pan.baidu.com/s/1c0hivuS 1:JavaScript 中分两种对象,函数对象和普通对象new Function() ...

  3. javascript javascript面向对象的理解及简单的示例

    javascript面向对象的理解及简单的示例 零.本节重点: 1.封装: 2.继承: 壹.下面理解: 一. javascript面向对象概念: 为了说明 JavaScript 是一门彻底的面向对象的 ...

  4. javaScript深入浅出之理解闭包

    javaScript深入浅出之理解闭包 引言 闭包是个老生长谈的话题了,对于闭包网上也有很多不同的看法 <你不知道的javaScript>对于闭包是这么定义的:函数创建和函数执行不在同一个 ...

  5. JavaScript:彻底理解同步、异步和事件循环(Event Loop) (转)

    原文出处:https://segmentfault.com/a/1190000004322358 一. 单线程 我们常说"JavaScript是单线程的". 所谓单线程,是指在JS ...

  6. 通过JavaScript原型链理解基于原型的编程

    零.此文动机 用了一段时间的Lua,用惯了Java C++等有Class关键字的语言,一直对Lua的中的面向对象技术感到费解,一个开源的objectlua更是看了n遍也没理解其中的原理,直到看到了Pr ...

  7. 细心看完这篇文章,刷新对Javascript Prototype的理解

    var person={name:'ninja'}; person.prototype.sayName=function(){ return this.name; } 分析上面这段代码,看看有没有问题 ...

  8. 【JavaScript】深入理解JavaScript之强大的原型和原型链

    由于JavaScript是唯一一个被广泛使用的基于原型继承的语言,所以理解两种继承模式的差异是需要一定时间的,今天我们就来了解一下原型和原型链. AD: hasOwnProperty函数: hasOw ...

  9. 深入理解JavaScript系列+ 深入理解javascript之执行上下文

    http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html http://blog.csdn.net/hi_kevin/article/d ...

随机推荐

  1. android学习笔记---发送状态栏通知

    发送消息的代码如下: //获取通知管理器 NotificationManager mNotificationManager = (NotificationManager) getSystemServi ...

  2. C++11多元组类别

    [C++11多元组类别] 多元组可被视为是 struct 其数据成员的一般化.底下是一个多元组类别的定义和使用情况: 我们可以定义一个多元组类别对象 proof 而不指定其内容,前提是 proof 里 ...

  3. win7 文件共享 xp

    前几天因为需要将win7内一文件夹共享给XP使用,因为NT5跟NT6安全机制的问题,共享的实现没有XP共享的方便,很多人是牺牲(关闭)了win7的系统防火墙才达到共享给XP的目的,但是关闭防火墙势必会 ...

  4. Network Object NAT配置介绍

    1.Dynamic NAT(动态NAT,动态一对一) 实例一: 传统配置方法: nat (Inside) 1 10.1.1.0 255.255.255.0 global (Outside) 1 202 ...

  5. GRUB加密

    在 /etc/grub.conf 内添加password=密码(也可使用加密的密码password= --md5 加密过的密码) 如何获得加密密码? 那就是grub-md5-crypt命令 简单流程如 ...

  6. csu oj 1804: 有向无环图 (dfs回溯)

    题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1804 中文题意就不说了. dfs从底到根回溯即可,看代码应该能清楚. //#pragma ...

  7. HDU 4870 Rating(高斯消元 )

    HDU 4870   Rating 这是前几天多校的题目,高了好久突然听旁边的大神推出来说是可以用高斯消元,一直喊着赶快敲模板,对于从来没有接触过高斯消元的我来说根本就是一头雾水,无赖之下这几天做DP ...

  8. 引用 1.9.1.min.js dom对象 没有live 绑定事件方法, 引用 1.7.js 就有live 绑定事件方法

    问题:相同环境,引用 1.9.1.min.js $('div[data-role="page"]').live('pagehide', function (event, ui) { ...

  9. 关于mysql存储过程的definer的问题

    由于对mysql了解不够透彻,导致对definer问题查了好久才解决问题 记录自己的一些理解! 问题描述: 在数据库写,为一个表写了一个触发器,此触发器调用一个存储过程:由公司写的一个c程序自动往该表 ...

  10. 使用sql访问EXECL文件

    --使用sql语句打开访问EXECL文件 --SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEMENT'OpenRowset/OpenDat ...